@@ -270,34 +270,47 @@ func (m *Manager) initReserved() {
270270
271271// UpdateControllerConfigItem updates the controller config item.
272272func (m * Manager ) UpdateControllerConfigItem (key string , value any ) error {
273- kp := strings .Split (key , "." )
274- if len (kp ) == 0 {
275- return errors .Errorf ("invalid key %s" , key )
276- }
273+ return m .UpdateControllerConfigItems (map [string ]any {key : value })
274+ }
275+
276+ // UpdateControllerConfigItems updates controller config items atomically.
277+ func (m * Manager ) UpdateControllerConfigItems (items map [string ]any ) error {
277278 m .Lock ()
278- var config any
279- switch kp [0 ] {
280- case "request-unit" :
281- config = & m .controllerConfig .RequestUnit
282- default :
283- config = m .controllerConfig
284- }
285- updated , found , err := jsonutil .AddKeyValue (config , kp [len (kp )- 1 ], value )
279+ controllerConfig , err := cloneControllerConfig (m .controllerConfig )
286280 if err != nil {
287281 m .Unlock ()
288282 return err
289283 }
290-
291- if ! found {
284+ updatedItems := make ([]struct {
285+ key string
286+ value any
287+ }, 0 , len (items ))
288+ for key , value := range items {
289+ updated , err := applyControllerConfigItem (controllerConfig , key , value )
290+ if err != nil {
291+ m .Unlock ()
292+ return err
293+ }
294+ if updated {
295+ updatedItems = append (updatedItems , struct {
296+ key string
297+ value any
298+ }{key : key , value : value })
299+ }
300+ }
301+ if len (updatedItems ) == 0 {
292302 m .Unlock ()
293- return errors . Errorf ( "config item %s not found" , key )
303+ return nil
294304 }
305+ if err := m .storage .SaveControllerConfig (controllerConfig ); err != nil {
306+ m .Unlock ()
307+ log .Error ("save controller config failed" , zap .Error (err ))
308+ return err
309+ }
310+ m .controllerConfig = controllerConfig
295311 m .Unlock ()
296- if updated {
297- if err := m .storage .SaveControllerConfig (m .controllerConfig ); err != nil {
298- log .Error ("save controller config failed" , zap .Error (err ))
299- }
300- log .Info ("updated controller config item" , zap .String ("key" , key ), zap .Any ("value" , value ))
312+ for _ , item := range updatedItems {
313+ log .Info ("updated controller config item" , zap .String ("key" , item .key ), zap .Any ("value" , item .value ))
301314 }
302315 return nil
303316}
@@ -309,6 +322,40 @@ func (m *Manager) GetControllerConfig() *ControllerConfig {
309322 return m .controllerConfig
310323}
311324
325+ func cloneControllerConfig (config * ControllerConfig ) (* ControllerConfig , error ) {
326+ data , err := json .Marshal (config )
327+ if err != nil {
328+ return nil , err
329+ }
330+ cloned := & ControllerConfig {}
331+ if err := json .Unmarshal (data , cloned ); err != nil {
332+ return nil , err
333+ }
334+ return cloned , nil
335+ }
336+
337+ func applyControllerConfigItem (config * ControllerConfig , key string , value any ) (bool , error ) {
338+ kp := strings .Split (key , "." )
339+ if len (kp ) == 0 {
340+ return false , errors .Errorf ("invalid key %s" , key )
341+ }
342+ var target any
343+ switch kp [0 ] {
344+ case "request-unit" :
345+ target = & config .RequestUnit
346+ default :
347+ target = config
348+ }
349+ updated , found , err := jsonutil .AddKeyValue (target , kp [len (kp )- 1 ], value )
350+ if err != nil {
351+ return false , err
352+ }
353+ if ! found {
354+ return false , errors .Errorf ("config item %s not found" , key )
355+ }
356+ return updated , nil
357+ }
358+
312359// AddResourceGroup puts a resource group.
313360// NOTE: AddResourceGroup should also be idempotent because tidb depends
314361// on this retry mechanism.
0 commit comments