feat: P0-1e expand handleConfigPush with host config and cluster dispatch
Wires the remaining cluster_config_t data into the notification pipeline: - dispatchConfigPush() extracted as a pure-Go helper (CGO-free, testable) that drives OnQueueUpdated, OnResourceUpdated, OnHostConfigUpdated, and OnClusterUpdated from a single config push event - handleConfigPush() delegates to dispatchConfigPush via the new helper, eliminating the previous inline loops - OnHostConfigUpdated and OnClusterUpdated added to NotificationHandler interface and implemented with partial-merge semantics in DefaultHandler - rawHostConfigData/rawHostConfigToModel and rawClusterData/rawClusterToModel added to convert_pure.go with their CGO extraction counterparts in convert.go Safety fixes from code review: - OnHostUpdated, OnHostConfigUpdated, OnClusterUpdated now copy *incoming to a local merged value before mutation, closing the TOCTOU window between store.Get and store.Put under concurrent pushes - cClusterConfQueues and cClusterConfResources gain nil-pointer guards matching the existing guard in cClusterConfHostConfigs - handleConfigPush gains an explicit gHandler nil check - cClusterConfToClusterInfo returns nil on empty clustername (prevents phantom empty-key write to store.Clusters); handleConfigPush logs a warning when nil - 36 unit tests passing (CGO_ENABLED=0)
This commit is contained in:
parent
00c4472d6c
commit
893812e7aa
8 changed files with 850 additions and 11 deletions
|
|
@ -107,7 +107,7 @@ func cResourceToModel(res *C.xce_resource_t) *models.ResourceDefinitionInfo {
|
|||
// cClusterConfQueues extracts queue models from a cluster_config_t.
|
||||
func cClusterConfQueues(conf *C.cluster_config_t) []models.QueueInfo {
|
||||
n := int(conf.nqueues)
|
||||
if n == 0 {
|
||||
if n == 0 || conf.queues == nil {
|
||||
return nil
|
||||
}
|
||||
qps := unsafe.Slice(conf.queues, n)
|
||||
|
|
@ -123,7 +123,7 @@ func cClusterConfQueues(conf *C.cluster_config_t) []models.QueueInfo {
|
|||
// cClusterConfResources extracts resource definition models from a cluster_config_t.
|
||||
func cClusterConfResources(conf *C.cluster_config_t) []models.ResourceDefinitionInfo {
|
||||
n := int(conf.nres)
|
||||
if n == 0 {
|
||||
if n == 0 || conf.resources == nil {
|
||||
return nil
|
||||
}
|
||||
rps := unsafe.Slice(conf.resources, n)
|
||||
|
|
@ -136,6 +136,48 @@ func cClusterConfResources(conf *C.cluster_config_t) []models.ResourceDefinition
|
|||
return out
|
||||
}
|
||||
|
||||
// cHostConfigToModel extracts C xce_hostconfig_t fields and maps them to HostInfo.
|
||||
func cHostConfigToModel(hc *C.xce_hostconfig_t) *models.HostInfo {
|
||||
return rawHostConfigToModel(rawHostConfigData{
|
||||
name: goString(hc.name),
|
||||
hostmodel: goString(hc.hostmodel),
|
||||
hosttype: goString(hc.hosttype),
|
||||
mxj: int(hc.mxj),
|
||||
})
|
||||
}
|
||||
|
||||
// cClusterConfHostConfigs extracts host config models from a cluster_config_t.
|
||||
func cClusterConfHostConfigs(conf *C.cluster_config_t) []models.HostInfo {
|
||||
n := int(conf.nhconfigs)
|
||||
if n == 0 || conf.hconfigs == nil {
|
||||
return nil
|
||||
}
|
||||
hps := unsafe.Slice(conf.hconfigs, n)
|
||||
out := make([]models.HostInfo, 0, n)
|
||||
for _, hp := range hps {
|
||||
if hp != nil {
|
||||
out = append(out, *cHostConfigToModel(hp))
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// cClusterConfToClusterInfo extracts C cluster_config_t cluster-level fields and maps them to ClusterInfo.
|
||||
// Returns nil when clustername is empty so dispatchConfigPush skips the OnClusterUpdated call.
|
||||
// C struct field names are snake_case (clustername, heartbeat_interval, etc.) — not Cap'n Proto names.
|
||||
func cClusterConfToClusterInfo(conf *C.cluster_config_t) *models.ClusterInfo {
|
||||
name := goString(conf.clustername)
|
||||
if name == "" {
|
||||
return nil
|
||||
}
|
||||
return rawClusterToModel(rawClusterData{
|
||||
name: name,
|
||||
heartbeatInterval: int(conf.heartbeat_interval),
|
||||
vcpus: int(conf.vcpus),
|
||||
inactiveHeartbeatCount: int(conf.inactive_heartbeat_count),
|
||||
})
|
||||
}
|
||||
|
||||
// modelJobToSubmit converts a Go JobInfo to C xce_job_submit_t heap structs.
|
||||
// The caller must free all returned C memory by calling freeJobSubmit.
|
||||
func modelJobToSubmit(job *models.JobInfo) (*C.xce_job_submit_t, *C.job_submit_data_t, *C.job_startinfo_t) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue