mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2026-08-31 08:57:14 +02:00
feat(fleet): add service type enum and infra scope
Replace the free-form service_type string with a ServiceType enum (ccms, ccmc, ccb, cces, ccsa, ccnc, ccem). The short code is the canonical value stored in the DB, the config-tree directory name and a NATS discovery subject token; Description() gives the human-readable name. Add a second scope alongside per-node agents: ScopeInfra covers cluster-independent monitoring infrastructure services, which are identified by (hostname, service_type) and carry an empty cluster. InfraRegistry is the ScopeInfra sibling of Registry and shares the same table, state machine and config-revision handshake. It deliberately exposes no StartSweep: MarkStale ages rows by last_heartbeat regardless of scope, so a single sweep goroutine per process covers both scopes. On the repository side ServiceDB gains a Scope column and the two queries the discovery publisher and infra enumeration need, ListActive() and ListByScope(). ResetConnection() now also resets the fleet repository singleton so tests get a fresh handle. Migration 13 is edited in place rather than superseded by a new migration: the service table is unreleased, so no existing deployment has it yet. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
// Copyright (C) NHR@FAU, University Erlangen-Nuremberg.
|
||||
// All rights reserved. This file is part of cc-backend.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fleet
|
||||
|
||||
// ServiceType is the kind of cc-* service a fleet member is. It is a
|
||||
// string-backed enum (mirroring schema.MonitoringState and the local
|
||||
// ScopeCluster/ScopeInfra constants): the short code is the canonical value
|
||||
// stored in the DB, used as the config-tree directory name, and used as a NATS
|
||||
// discovery-subject token. Description() gives the human-readable name.
|
||||
type ServiceType string
|
||||
|
||||
const (
|
||||
ServiceTypeMetricStore ServiceType = "ccms" // cc-metric-store
|
||||
ServiceTypeCollector ServiceType = "ccmc" // cc-metric-collector
|
||||
ServiceTypeBackend ServiceType = "ccb" // cc-backend
|
||||
ServiceTypeEventStore ServiceType = "cces" // cc-event-store
|
||||
ServiceTypeSlurmAdapter ServiceType = "ccsa" // cc-slurm-adapter
|
||||
ServiceTypeNodeController ServiceType = "ccnc" // cc-node-controller
|
||||
ServiceTypeEnergyManager ServiceType = "ccem" // cc-energy-manager
|
||||
)
|
||||
|
||||
// AllServiceTypes lists every valid service type. Order is stable so callers
|
||||
// that iterate (e.g. the discovery publisher) produce deterministic output.
|
||||
var AllServiceTypes = []ServiceType{
|
||||
ServiceTypeMetricStore,
|
||||
ServiceTypeCollector,
|
||||
ServiceTypeBackend,
|
||||
ServiceTypeEventStore,
|
||||
ServiceTypeSlurmAdapter,
|
||||
ServiceTypeNodeController,
|
||||
ServiceTypeEnergyManager,
|
||||
}
|
||||
|
||||
var serviceTypeDescriptions = map[ServiceType]string{
|
||||
ServiceTypeMetricStore: "cc-metric-store",
|
||||
ServiceTypeCollector: "cc-metric-collector",
|
||||
ServiceTypeBackend: "cc-backend",
|
||||
ServiceTypeEventStore: "cc-event-store",
|
||||
ServiceTypeSlurmAdapter: "cc-slurm-adapter",
|
||||
ServiceTypeNodeController: "cc-node-controller",
|
||||
ServiceTypeEnergyManager: "cc-energy-manager",
|
||||
}
|
||||
|
||||
// Valid reports whether t is a known service type.
|
||||
func (t ServiceType) Valid() bool {
|
||||
_, ok := serviceTypeDescriptions[t]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Description returns the full human-readable service name (e.g. "cc-metric-store"),
|
||||
// or the raw code if unknown.
|
||||
func (t ServiceType) Description() string {
|
||||
if d, ok := serviceTypeDescriptions[t]; ok {
|
||||
return d
|
||||
}
|
||||
return string(t)
|
||||
}
|
||||
|
||||
// relevantProviders is the single source of truth for which provider service
|
||||
// types each consumer type needs to discover. Keep it here and edit in one
|
||||
// place.
|
||||
//
|
||||
// Confirmed universal edge: every service must reach cc-backend (ccb) to
|
||||
// register and pull its config, so ccb is relevant to all of them. Richer
|
||||
// peer edges (a collector wanting the metric store, an energy manager wanting
|
||||
// the node controller, …) are left commented for an operator to enable once the
|
||||
// concrete topology is settled — they are intentionally not assumed here.
|
||||
var relevantProviders = map[ServiceType][]ServiceType{
|
||||
ServiceTypeMetricStore: {ServiceTypeBackend},
|
||||
ServiceTypeCollector: {ServiceTypeBackend /*, ServiceTypeMetricStore */},
|
||||
ServiceTypeEventStore: {ServiceTypeBackend},
|
||||
ServiceTypeSlurmAdapter: {ServiceTypeBackend},
|
||||
ServiceTypeNodeController: {ServiceTypeBackend},
|
||||
ServiceTypeEnergyManager: {ServiceTypeBackend /*, ServiceTypeMetricStore, ServiceTypeNodeController */},
|
||||
ServiceTypeBackend: {}, // ccb discovers no peers by default
|
||||
}
|
||||
|
||||
// RelevantProviders returns the provider service types that consumer should
|
||||
// discover. The returned slice must not be mutated by callers.
|
||||
func RelevantProviders(consumer ServiceType) []ServiceType {
|
||||
return relevantProviders[consumer]
|
||||
}
|
||||
Reference in New Issue
Block a user