@@ -33,14 +33,16 @@ const (
3333
3434type (
3535 CommandService struct {
36- commandServiceClient mpi.CommandServiceClient
37- subscribeClient mpi.CommandService_SubscribeClient
38- agentConfig * config.Config
39- isConnected * atomic.Bool
40- subscribeCancel context.CancelFunc
41- subscribeChannel chan * mpi.ManagementPlaneRequest
42- subscribeMutex sync.Mutex
43- subscribeClientMutex sync.Mutex
36+ commandServiceClient mpi.CommandServiceClient
37+ subscribeClient mpi.CommandService_SubscribeClient
38+ agentConfig * config.Config
39+ isConnected * atomic.Bool
40+ subscribeCancel context.CancelFunc
41+ subscribeChannel chan * mpi.ManagementPlaneRequest
42+ configApplyRequestQueue map [string ][]* mpi.ManagementPlaneRequest // key is the instance ID
43+ subscribeMutex sync.Mutex
44+ subscribeClientMutex sync.Mutex
45+ configApplyRequestQueueMutex sync.Mutex
4446 }
4547)
4648
@@ -54,10 +56,11 @@ func NewCommandService(
5456 isConnected .Store (false )
5557
5658 commandService := & CommandService {
57- commandServiceClient : commandServiceClient ,
58- agentConfig : agentConfig ,
59- isConnected : isConnected ,
60- subscribeChannel : subscribeChannel ,
59+ commandServiceClient : commandServiceClient ,
60+ agentConfig : agentConfig ,
61+ isConnected : isConnected ,
62+ subscribeChannel : subscribeChannel ,
63+ configApplyRequestQueue : make (map [string ][]* mpi.ManagementPlaneRequest ),
6164 }
6265
6366 var subscribeCtx context.Context
@@ -165,6 +168,11 @@ func (cs *CommandService) SendDataPlaneResponse(ctx context.Context, response *m
165168 backOffCtx , backoffCancel := context .WithTimeout (ctx , cs .agentConfig .Client .Backoff .MaxElapsedTime )
166169 defer backoffCancel ()
167170
171+ err := cs .handleConfigApplyResponse (ctx , response )
172+ if err != nil {
173+ return err
174+ }
175+
168176 return backoff .Retry (
169177 cs .sendDataPlaneResponseCallback (ctx , response ),
170178 backoffHelpers .Context (backOffCtx , cs .agentConfig .Client .Backoff ),
@@ -271,6 +279,81 @@ func (cs *CommandService) sendDataPlaneResponseCallback(
271279 }
272280}
273281
282+ func (cs * CommandService ) handleConfigApplyResponse (
283+ ctx context.Context ,
284+ response * mpi.DataPlaneResponse ,
285+ ) error {
286+ cs .configApplyRequestQueueMutex .Lock ()
287+ defer cs .configApplyRequestQueueMutex .Unlock ()
288+
289+ isConfigApplyResponse := false
290+ var indexOfConfigApplyRequest int
291+
292+ for index , configApplyRequest := range cs .configApplyRequestQueue [response .GetInstanceId ()] {
293+ if configApplyRequest .GetMessageMeta ().GetCorrelationId () == response .GetMessageMeta ().GetCorrelationId () {
294+ indexOfConfigApplyRequest = index
295+ isConfigApplyResponse = true
296+
297+ break
298+ }
299+ }
300+
301+ if isConfigApplyResponse {
302+ err := cs .sendResponseForQueuedConfigApplyRequests (ctx , response , indexOfConfigApplyRequest )
303+ if err != nil {
304+ return err
305+ }
306+ }
307+
308+ return nil
309+ }
310+
311+ func (cs * CommandService ) sendResponseForQueuedConfigApplyRequests (
312+ ctx context.Context ,
313+ response * mpi.DataPlaneResponse ,
314+ indexOfConfigApplyRequest int ,
315+ ) error {
316+ instanceID := response .GetInstanceId ()
317+ for i := 0 ; i < indexOfConfigApplyRequest ; i ++ {
318+ newResponse := response
319+
320+ newResponse .GetMessageMeta ().MessageId = proto .GenerateMessageID ()
321+
322+ request := cs.configApplyRequestQueue [instanceID ][i ]
323+ newResponse .GetMessageMeta ().CorrelationId = request .GetMessageMeta ().GetCorrelationId ()
324+
325+ slog .DebugContext (
326+ ctx ,
327+ "Sending data plane response for queued config apply request" ,
328+ "response" , newResponse ,
329+ )
330+
331+ backOffCtx , backoffCancel := context .WithTimeout (ctx , cs .agentConfig .Client .Backoff .MaxElapsedTime )
332+
333+ err := backoff .Retry (
334+ cs .sendDataPlaneResponseCallback (ctx , newResponse ),
335+ backoffHelpers .Context (backOffCtx , cs .agentConfig .Client .Backoff ),
336+ )
337+ if err != nil {
338+ slog .ErrorContext (ctx , "Failed to send data plane response" , "error" , err )
339+ backoffCancel ()
340+
341+ return err
342+ }
343+
344+ backoffCancel ()
345+ }
346+
347+ cs .configApplyRequestQueue [instanceID ] = cs .configApplyRequestQueue [instanceID ][indexOfConfigApplyRequest + 1 :]
348+ slog .DebugContext (ctx , "Removed config apply requests from queue" , "queue" , cs .configApplyRequestQueue [instanceID ])
349+
350+ if len (cs .configApplyRequestQueue [instanceID ]) > 0 {
351+ cs .subscribeChannel <- cs .configApplyRequestQueue [instanceID ][len (cs .configApplyRequestQueue [instanceID ])- 1 ]
352+ }
353+
354+ return nil
355+ }
356+
274357// Retry callback for sending a data plane health status to the Management Plane.
275358func (cs * CommandService ) dataPlaneHealthCallback (
276359 ctx context.Context ,
@@ -333,7 +416,25 @@ func (cs *CommandService) receiveCallback(ctx context.Context) func() error {
333416 return recvError
334417 }
335418
336- cs .subscribeChannel <- request
419+ switch request .GetRequest ().(type ) {
420+ case * mpi.ManagementPlaneRequest_ConfigApplyRequest :
421+ cs .configApplyRequestQueueMutex .Lock ()
422+ defer cs .configApplyRequestQueueMutex .Unlock ()
423+
424+ instanceID := request .GetConfigApplyRequest ().GetOverview ().GetConfigVersion ().GetInstanceId ()
425+ cs .configApplyRequestQueue [instanceID ] = append (cs .configApplyRequestQueue [instanceID ], request )
426+ if len (cs .configApplyRequestQueue [instanceID ]) == 1 {
427+ cs .subscribeChannel <- request
428+ } else {
429+ slog .DebugContext (
430+ ctx ,
431+ "Config apply request is already in progress, queuing new config apply request" ,
432+ "request" , request ,
433+ )
434+ }
435+ default :
436+ cs .subscribeChannel <- request
437+ }
337438
338439 return nil
339440 }
0 commit comments