Repository: moby/moby
File: daemon/reload.go (Go)

Code before:
	// two-phase commit protocol to achieve this. Any fallible reload operation is
	// split into two phases. The first phase performs all the fallible operations
	// and mutates the newCfg copy. The second phase atomically swaps newCfg into
	// the live daemon configuration and executes any commit functions the first
	// phase registered to apply the side effects. If any first-phase returns an
	// error, the reload transaction is rolled back by discarding newCfg and
	// executing any registered rollback functions.

	var txn reloadTxn
	for _, reload := range []func(txn *reloadTxn, newCfg *configStore, conf *config.Config, attributes map[string]string) error{
		// TODO(thaJeztah): most of these are defined as method, but don't use the daemon receiver; consider making them regular functions.
		daemon.reloadPlatform,
		daemon.reloadDebug,
		daemon.reloadMaxConcurrentDownloadsAndUploads,
		daemon.reloadMaxDownloadAttempts,
		daemon.reloadShutdownTimeout,
		daemon.reloadFeatures,
		daemon.reloadLabels,
		daemon.reloadRegistryConfig,
		daemon.reloadLiveRestore,
		daemon.reloadNetworkDiagnosticPort,
	} {
		if err := reload(&txn, newCfg, conf, attributes); err != nil {
			if rollbackErr := txn.Rollback(); rollbackErr != nil {
				return errors.Join(nil, err, rollbackErr)
			}
			return err
		}
	}

	daemon.configStore.Store(newCfg)
	daemon.LogDaemonEventWithAttributes(events.ActionReload, attributes)
	return txn.Commit()
}

func marshalAttributeSlice(v []string) string {
	if v == nil {
		return "[]"
	}
	b, err := json.Marshal(v)
	if err != nil {
		panic(err) // Should never happen as the input type is fixed.
	}
	return string(b)
}

// reloadDebug updates configuration with Debug option
// and updates the passed attributes
func (daemon *Daemon) reloadDebug(txn *reloadTxn, newCfg *configStore, conf *config.Config, attributes map[string]string) error {
	// update corresponding configuration
	if conf.IsValueSet("debug") {

Review comment (suggestion):
Not sure why the `nil` was there, but maybe `go-multierror` needed it; this can probably be;


```go
return errors.Join(err, rollbackErr)
```


Code after:
	// successfully, or the daemon config and state are left untouched. We use a
	// two-phase commit protocol to achieve this. Any fallible reload operation is
	// split into two phases. The first phase performs all the fallible operations
	// and mutates the newCfg copy. The second phase atomically swaps newCfg into
	// the live daemon configuration and executes any commit functions the first
	// phase registered to apply the side effects. If any first-phase returns an
	// error, the reload transaction is rolled back by discarding newCfg and
	// executing any registered rollback functions.

	var txn reloadTxn
	for _, reload := range []func(txn *reloadTxn, newCfg *configStore, conf *config.Config, attributes map[string]string) error{
		// TODO(thaJeztah): most of these are defined as method, but don't use the daemon receiver; consider making them regular functions.
		daemon.reloadPlatform,
		daemon.reloadDebug,
		daemon.reloadMaxConcurrentDownloadsAndUploads,
		daemon.reloadMaxDownloadAttempts,
		daemon.reloadShutdownTimeout,
		daemon.reloadFeatures,
		daemon.reloadLabels,
		daemon.reloadRegistryConfig,
		daemon.reloadLiveRestore,
		daemon.reloadNetworkDiagnosticPort,
	} {
		if err := reload(&txn, newCfg, conf, attributes); err != nil {
			return errors.Join(err, txn.Rollback())
		}
	}

	daemon.configStore.Store(newCfg)
	daemon.LogDaemonEventWithAttributes(events.ActionReload, attributes)
	return txn.Commit()
}

func marshalAttributeSlice(v []string) string {
	if v == nil {
		return "[]"
	}
	b, err := json.Marshal(v)
	if err != nil {
		panic(err) // Should never happen as the input type is fixed.
	}
	return string(b)
}

// reloadDebug updates configuration with Debug option
// and updates the passed attributes
func (daemon *Daemon) reloadDebug(txn *reloadTxn, newCfg *configStore, conf *config.Config, attributes map[string]string) error {
	// update corresponding configuration
	if conf.IsValueSet("debug") {
		newCfg.Debug = conf.Debug
	}