@@ -88,7 +88,7 @@ type ConnectionState struct {
8888// ControlPlaneClient interface defines the methods needed from the control plane client
8989type ControlPlaneClient interface {
9090 IsConnected () bool
91- NotifyAPIDeployment (apiID string , apiConfig * models.StoredConfig , revisionID string ) error
91+ NotifyAPIDeployment (apiID string , apiConfig * models.StoredConfig , deploymentID string ) error
9292}
9393
9494// Client manages the WebSocket connection to the control plane
@@ -590,7 +590,7 @@ func (c *Client) handleAPIDeployedEvent(event map[string]interface{}) {
590590 c .logger .Info ("Processing API deployment" ,
591591 slog .String ("api_id" , apiID ),
592592 slog .String ("environment" , deployedEvent .Payload .Environment ),
593- slog .String ("revision_id " , deployedEvent .Payload .RevisionID ),
593+ slog .String ("deployment_id " , deployedEvent .Payload .DeploymentID ),
594594 slog .String ("vhost" , deployedEvent .Payload .VHost ),
595595 slog .String ("correlation_id" , deployedEvent .CorrelationID ),
596596 )
@@ -685,7 +685,114 @@ func (c *Client) handleAPIUndeployedEvent(event map[string]interface{}) {
685685 slog .Any ("timestamp" , event ["timestamp" ]),
686686 slog .Any ("correlationId" , event ["correlationId" ]),
687687 )
688- // TODO: Implement actual API undeployment logic in Phase 6
688+
689+ // Parse the event into structured format
690+ eventBytes , err := json .Marshal (event )
691+ if err != nil {
692+ c .logger .Error ("Failed to marshal event for parsing" ,
693+ slog .Any ("error" , err ),
694+ )
695+ return
696+ }
697+
698+ var undeployedEvent APIUndeployedEvent
699+ if err := json .Unmarshal (eventBytes , & undeployedEvent ); err != nil {
700+ c .logger .Error ("Failed to parse API undeployment event" ,
701+ slog .Any ("error" , err ),
702+ )
703+ return
704+ }
705+
706+ // Extract API ID
707+ apiID := undeployedEvent .Payload .APIID
708+ if apiID == "" {
709+ c .logger .Error ("API ID is empty in undeployment event" )
710+ return
711+ }
712+
713+ c .logger .Info ("Processing API undeployment" ,
714+ slog .String ("api_id" , apiID ),
715+ slog .String ("environment" , undeployedEvent .Payload .Environment ),
716+ slog .String ("vhost" , undeployedEvent .Payload .VHost ),
717+ slog .String ("correlation_id" , undeployedEvent .CorrelationID ),
718+ )
719+
720+ // Check if config exists in database first (source of truth when persistent storage is available)
721+ var apiConfig * models.StoredConfig
722+ if c .db != nil {
723+ var err error
724+ apiConfig , err = c .db .GetConfig (apiID )
725+ if err != nil {
726+ c .logger .Warn ("API configuration not found in database for undeployment" ,
727+ slog .String ("api_id" , apiID ),
728+ slog .Any ("error" , err ),
729+ )
730+ // Not an error - the API might already be undeployed or deleted
731+ return
732+ }
733+ } else {
734+ // Fall back to in-memory store if database is not available
735+ var err error
736+ apiConfig , err = c .store .Get (apiID )
737+ if err != nil {
738+ c .logger .Warn ("API configuration not found in storage for undeployment" ,
739+ slog .String ("api_id" , apiID ),
740+ slog .Any ("error" , err ),
741+ )
742+ // Not an error - the API might already be undeployed or deleted
743+ return
744+ }
745+ }
746+
747+ // Set status to undeployed (preserve config, keys, and policies)
748+ apiConfig .Status = models .StatusUndeployed
749+ apiConfig .UpdatedAt = time .Now ()
750+ // Keep DeployedVersion as-is - it tracks when it was last deployed
751+
752+ // Update database (only if persistent mode)
753+ if c .db != nil {
754+ if err := c .db .UpdateConfig (apiConfig ); err != nil {
755+ c .logger .Error ("Failed to update config status in database" ,
756+ slog .String ("api_id" , apiID ),
757+ slog .Any ("error" , err ),
758+ )
759+ return
760+ }
761+ }
762+
763+ // Update in-memory store
764+ if err := c .store .Update (apiConfig ); err != nil {
765+ c .logger .Error ("Failed to update config status in memory store" ,
766+ slog .String ("api_id" , apiID ),
767+ slog .Any ("error" , err ),
768+ )
769+ return
770+ }
771+
772+ // Note: We keep API keys and policies for potential redeploy
773+ // They will be reused if the API is redeployed
774+
775+ // Update xDS snapshot asynchronously (undeployed APIs will be filtered out)
776+ go func () {
777+ ctx , cancel := context .WithTimeout (context .Background (), 10 * time .Second )
778+ defer cancel ()
779+
780+ if err := c .snapshotManager .UpdateSnapshot (ctx , undeployedEvent .CorrelationID ); err != nil {
781+ c .logger .Error ("Failed to update xDS snapshot after API undeployment" ,
782+ slog .String ("api_id" , apiID ),
783+ slog .Any ("error" , err ),
784+ )
785+ } else {
786+ c .logger .Info ("Successfully updated xDS snapshot after API undeployment" ,
787+ slog .String ("api_id" , apiID ),
788+ )
789+ }
790+ }()
791+
792+ c .logger .Info ("Successfully processed API undeployment event" ,
793+ slog .String ("api_id" , apiID ),
794+ slog .String ("correlation_id" , undeployedEvent .CorrelationID ),
795+ )
689796}
690797
691798// handleAPIKeyCreatedEvent handles API key created events from platform-api
@@ -1119,7 +1226,7 @@ func (c *Client) IsConnected() bool {
11191226}
11201227
11211228// NotifyAPIDeployment sends a REST API call to platform-api when an API is deployed successfully
1122- func (c * Client ) NotifyAPIDeployment (apiID string , apiConfig * models.StoredConfig , revisionID string ) error {
1229+ func (c * Client ) NotifyAPIDeployment (apiID string , apiConfig * models.StoredConfig , deploymentID string ) error {
11231230 // Check if connected to control plane
11241231 if ! c .IsConnected () {
11251232 c .logger .Debug ("Not connected to control plane, skipping API deployment notification" ,
@@ -1128,7 +1235,7 @@ func (c *Client) NotifyAPIDeployment(apiID string, apiConfig *models.StoredConfi
11281235 }
11291236
11301237 // Use the api utils service to send the deployment notification
1131- return c .apiUtilsService .NotifyAPIDeployment (apiID , apiConfig , revisionID )
1238+ return c .apiUtilsService .NotifyAPIDeployment (apiID , apiConfig , deploymentID )
11321239}
11331240
11341241// getWebSocketURL constructs the base WebSocket URL from configuration
0 commit comments