@@ -228,6 +228,25 @@ async def _sync_all_task():
228228        salt .engines .start_engines , self .opts , self .process_manager , proxy = self .proxy 
229229    )
230230
231+     # At this point the control proxy finished its own initialization, allow 
232+     # requests targeting the control proxy to flow even if sub proxies are 
233+     # still spinning up (which can take a while when managing dozens of ids). 
234+     setup_future  =  getattr (self , "_setup_future" , None )
235+     self .ready  =  True 
236+     if  self .opts .get ("return_retry_timer" , 0 ) <  20 :
237+         new_retry  =  20 
238+         self .opts ["return_retry_timer" ] =  new_retry 
239+         current_max  =  self .opts .get ("return_retry_timer_max" , new_retry )
240+         if  current_max  <  new_retry :
241+             current_max  =  new_retry 
242+         self .opts ["return_retry_timer_max" ] =  max (current_max , new_retry  +  10 )
243+         log .debug (
244+             "Control proxy %s adjusted return retry timers to %s-%s seconds" ,
245+             self .opts ["id" ],
246+             self .opts ["return_retry_timer" ],
247+             self .opts ["return_retry_timer_max" ],
248+         )
249+ 
231250    proxy_init_func_name  =  f"{ fq_proxyname }  
232251    proxy_shutdown_func_name  =  f"{ fq_proxyname }  
233252    if  (
@@ -425,16 +444,22 @@ async def _sync_grains_task():
425444    if  self .opts ["proxy" ].get ("parallel_startup" ):
426445        log .warning ("Initiating parallel startup for proxies" )
427446        waitfor  =  []
447+         max_concurrency  =  max (1 , self .opts ["proxy" ].get ("startup_concurrency" , 4 ))
448+         semaphore  =  asyncio .Semaphore (max_concurrency )
449+ 
428450        for  _id  in  self .opts ["proxy" ].get ("ids" , []):
429-             waitfor .append (
430-                 subproxy_post_master_init (
431-                     _id ,
432-                     uid ,
433-                     self .opts ,
434-                     self .proxy ,
435-                     self .utils ,
436-                 )
437-             )
451+ 
452+             async  def  _initialise_subproxy (sub_id , * , _sem = semaphore ):
453+                 async  with  _sem :
454+                     return  await  subproxy_post_master_init (
455+                         sub_id ,
456+                         uid ,
457+                         self .opts ,
458+                         self .proxy ,
459+                         self .utils ,
460+                     )
461+ 
462+             waitfor .append (_initialise_subproxy (_id ))
438463
439464        try :
440465            results  =  await  asyncio .gather (* waitfor )
@@ -504,28 +529,41 @@ async def subproxy_post_master_init(minion_id, uid, opts, main_proxy, main_utils
504529    proxy_grains  =  {}
505530    proxy_pillar  =  {}
506531
507-     proxyopts  =  opts .copy ()
508-     proxyopts ["id" ] =  minion_id 
532+     loop  =  asyncio .get_running_loop ()
509533
510-     proxyopts  =  salt .config .proxy_config (
511-         opts ["conf_file" ], defaults = proxyopts , minion_id = minion_id 
512-     )
513-     proxyopts .update ({"id" : minion_id , "proxyid" : minion_id , "subproxy" : True })
534+     def  _load_proxyopts_and_grains ():
535+         proxyopts_local  =  opts .copy ()
536+         proxyopts_local ["id" ] =  minion_id 
514537
515-     proxy_context  =  {"proxy_id" : minion_id }
538+         proxyopts_local  =  salt .config .proxy_config (
539+             opts ["conf_file" ], defaults = proxyopts_local , minion_id = minion_id 
540+         )
541+         proxyopts_local .update (
542+             {"id" : minion_id , "proxyid" : minion_id , "subproxy" : True }
543+         )
516544
517-     # We need grains first to be able to load pillar, which is where we keep the proxy 
518-     # configurations 
519-     proxy_grains  =  salt .loader .grains (
520-         proxyopts , proxy = main_proxy , context = proxy_context 
545+         proxy_context_local  =  {"proxy_id" : minion_id }
546+ 
547+         proxy_grains_local  =  salt .loader .grains (
548+             proxyopts_local , proxy = main_proxy , context = proxy_context_local 
549+         )
550+         return  proxyopts_local , proxy_context_local , proxy_grains_local 
551+ 
552+     proxyopts , proxy_context , proxy_grains  =  await  loop .run_in_executor (
553+         None , _load_proxyopts_and_grains 
521554    )
522-     proxy_pillar  =  await  salt .pillar .get_async_pillar (
523-         proxyopts ,
524-         proxy_grains ,
525-         minion_id ,
526-         saltenv = proxyopts ["saltenv" ],
527-         pillarenv = proxyopts .get ("pillarenv" ),
528-     ).compile_pillar ()
555+ 
556+     def  _compile_proxy_pillar ():
557+         pillar  =  salt .pillar .get_pillar (
558+             proxyopts ,
559+             proxy_grains ,
560+             minion_id ,
561+             saltenv = proxyopts ["saltenv" ],
562+             pillarenv = proxyopts .get ("pillarenv" ),
563+         )
564+         return  pillar .compile_pillar ()
565+ 
566+     proxy_pillar  =  await  loop .run_in_executor (None , _compile_proxy_pillar )
529567
530568    proxyopts ["proxy" ] =  proxy_pillar .get ("proxy" , {})
531569    if  not  proxyopts ["proxy" ]:
@@ -534,8 +572,6 @@ async def subproxy_post_master_init(minion_id, uid, opts, main_proxy, main_utils
534572        )
535573        return  {"proxy_minion" : None , "proxy_opts" : {}}
536574
537-     loop  =  asyncio .get_running_loop ()
538- 
539575    def  _finish_subproxy_setup ():
540576        proxyopts ["proxy" ].pop ("ids" , None )
541577
@@ -1049,12 +1085,18 @@ async def handle_payload(self, payload):
10491085    Verify the publication and then pass 
10501086    the payload along to _handle_decoded_payload. 
10511087    """ 
1088+     log .debug (
1089+         "Control proxy %s received payload enc=%s keys=%s" ,
1090+         self .opts ["id" ],
1091+         payload .get ("enc" ) if  payload  else  None ,
1092+         sorted (payload ["load" ].keys ()) if  payload  and  "load"  in  payload  else  None ,
1093+     )
10521094    setup_future  =  getattr (self , "_setup_future" , None )
10531095    if  setup_future  is  not None  and  not  setup_future .done ():
1054-         log .warning ("Control proxy waiting for setup to finish before handling payload" )
1096+         log .debug ("Control proxy waiting for setup to finish before handling payload" )
10551097        await  asyncio .shield (setup_future )
10561098    else :
1057-         log .warning ("Control proxy setup already complete; handling payload" )
1099+         log .debug ("Control proxy setup already complete; handling payload" )
10581100    if  payload  is  not None  and  payload ["enc" ] ==  "aes" :
10591101        # First handle payload for the "control" proxy 
10601102        if  self ._target_load (payload ["load" ]):
0 commit comments