@@ -11,54 +11,70 @@ import (
1111 "github.com/openshift-hyperfleet/hyperfleet-api/pkg/errors"
1212)
1313
14+ // computeNodePoolConditionsJSON aggregates adapter statuses into marshaled conditions JSON.
15+ // Returns nil if conditions are unchanged relative to np.StatusConditions.
16+ func computeNodePoolConditionsJSON (
17+ ctx context.Context ,
18+ np * api.NodePool ,
19+ adapterStatuses []* api.AdapterStatus ,
20+ requiredAdapters []string ,
21+ ) ([]byte , * errors.ServiceError ) {
22+ ready , available , adapterConditions := AggregateResourceStatus (ctx , AggregateResourceStatusInput {
23+ ResourceGeneration : np .Generation ,
24+ RefTime : nodePoolRefTime (np ),
25+ PrevConditionsJSON : np .StatusConditions ,
26+ RequiredAdapters : requiredAdapters ,
27+ AdapterStatuses : adapterStatuses ,
28+ })
29+
30+ allConditions := make ([]api.ResourceCondition , 0 , 2 + len (adapterConditions ))
31+ allConditions = append (allConditions , ready , available )
32+ allConditions = append (allConditions , adapterConditions ... )
33+
34+ conditionsJSON , err := json .Marshal (allConditions )
35+ if err != nil {
36+ return nil , errors .GeneralError ("Failed to marshal conditions: %s" , err )
37+ }
38+
39+ if bytes .Equal (np .StatusConditions , conditionsJSON ) {
40+ return nil , nil
41+ }
42+
43+ return conditionsJSON , nil
44+ }
45+
46+ // updateNodePoolStatusFromAdapters fetches a single nodepool by ID, recomputes its status
47+ // conditions from current adapter reports, and persists the result via Replace.
48+ // Returns the updated nodepool unchanged if conditions have not changed.
1449func updateNodePoolStatusFromAdapters (
1550 ctx context.Context ,
1651 nodePoolID string ,
1752 nodePoolDao dao.NodePoolDao ,
1853 adapterStatusDao dao.AdapterStatusDao ,
1954 adapterConfig * config.AdapterRequirementsConfig ,
2055) (* api.NodePool , * errors.ServiceError ) {
21- // Get the nodepool
2256 nodePool , err := nodePoolDao .Get (ctx , nodePoolID )
2357 if err != nil {
2458 return nil , handleGetError ("NodePool" , "id" , nodePoolID , err )
2559 }
2660
27- // Get adapter statuses
2861 adapterStatuses , err := adapterStatusDao .FindByResource (ctx , "NodePool" , nodePoolID )
2962 if err != nil {
3063 return nil , errors .GeneralError ("Failed to get adapter statuses: %s" , err )
3164 }
3265
33- // Compute reference time
34- refTime := nodePoolRefTime (nodePool )
35-
36- // Aggregate status
37- ready , available , adapterConditions := AggregateResourceStatus (ctx , AggregateResourceStatusInput {
38- ResourceGeneration : nodePool .Generation ,
39- RefTime : refTime ,
40- PrevConditionsJSON : nodePool .StatusConditions ,
41- RequiredAdapters : adapterConfig .RequiredNodePoolAdapters (),
42- AdapterStatuses : adapterStatuses ,
43- })
44-
45- // Build combined conditions
46- allConditions := make ([]api.ResourceCondition , 0 , 2 + len (adapterConditions ))
47- allConditions = append (allConditions , ready , available )
48- allConditions = append (allConditions , adapterConditions ... )
49-
50- // Marshal conditions
51- conditionsJSON , err := json .Marshal (allConditions )
52- if err != nil {
53- return nil , errors .GeneralError ("Failed to marshal conditions: %s" , err )
66+ conditionsJSON , svcErr := computeNodePoolConditionsJSON (
67+ ctx ,
68+ nodePool ,
69+ adapterStatuses ,
70+ adapterConfig .RequiredNodePoolAdapters ())
71+ if svcErr != nil {
72+ return nil , svcErr
5473 }
55-
56- // Short-circuit if unchanged
57- if bytes .Equal (nodePool .StatusConditions , conditionsJSON ) {
74+ if conditionsJSON == nil {
5875 return nodePool , nil
5976 }
6077
61- // Update and persist
6278 nodePool .StatusConditions = conditionsJSON
6379 nodePool , err = nodePoolDao .Replace (ctx , nodePool )
6480 if err != nil {
@@ -69,8 +85,8 @@ func updateNodePoolStatusFromAdapters(
6985}
7086
7187// batchUpdateNodePoolStatusesFromAdapters updates status conditions for multiple nodepools.
72- // It eliminates the N+1 query pattern by fetching all adapter statuses in one query
73- // and persisting all changed nodepools via UpdateStatusConditionsByIDs.
88+ // It's fetching all adapter statuses in one query and persisting
89+ // all changed nodepools via UpdateStatusConditionsByIDs.
7490func batchUpdateNodePoolStatusesFromAdapters (
7591 ctx context.Context ,
7692 nodePools []* api.NodePool ,
@@ -94,35 +110,19 @@ func batchUpdateNodePoolStatusesFromAdapters(
94110
95111 statusesByResource := make (map [string ][]* api.AdapterStatus )
96112 for i := range allStatuses {
97- status := allStatuses [i ]
98- statusesByResource [status .ResourceID ] = append (statusesByResource [status .ResourceID ], status )
113+ s := allStatuses [i ]
114+ statusesByResource [s .ResourceID ] = append (statusesByResource [s .ResourceID ], s )
99115 }
100116
101117 updates := make (map [string ][]byte )
102118 requiredAdapters := adapterConfig .RequiredNodePoolAdapters ()
103119
104120 for _ , np := range nodePools {
105- refTime := nodePoolRefTime (np )
106- adapterStatuses := statusesByResource [np .ID ]
107-
108- ready , available , adapterConditions := AggregateResourceStatus (ctx , AggregateResourceStatusInput {
109- ResourceGeneration : np .Generation ,
110- RefTime : refTime ,
111- PrevConditionsJSON : np .StatusConditions ,
112- RequiredAdapters : requiredAdapters ,
113- AdapterStatuses : adapterStatuses ,
114- })
115-
116- allConditions := make ([]api.ResourceCondition , 0 , 2 + len (adapterConditions ))
117- allConditions = append (allConditions , ready , available )
118- allConditions = append (allConditions , adapterConditions ... )
119-
120- conditionsJSON , marshalErr := json .Marshal (allConditions )
121- if marshalErr != nil {
122- return errors .GeneralError ("Failed to marshal conditions: %s" , marshalErr )
121+ conditionsJSON , svcErr := computeNodePoolConditionsJSON (ctx , np , statusesByResource [np .ID ], requiredAdapters )
122+ if svcErr != nil {
123+ return svcErr
123124 }
124-
125- if ! bytes .Equal (np .StatusConditions , conditionsJSON ) {
125+ if conditionsJSON != nil {
126126 updates [np .ID ] = conditionsJSON
127127 }
128128 }
0 commit comments