diff options
| author | Chia <Chia@93.nz> | 2026-08-05 22:01:29 +1200 |
|---|---|---|
| committer | Chia <Chia@93.nz> | 2026-08-05 22:07:50 +1200 |
| commit | eadb2ffe85c43cf6fc741c9823cd28eedb4a844c (patch) | |
| tree | 1aba2536d57360da403aa35c9ced58b615c7064e /internal/controlplane/manager.go | |
| parent | cd0dd91ab93653631904f2ea0e574ccde6d60339 (diff) | |
feat: harden prepaid billing and commercial operations
Diffstat (limited to '')
| -rw-r--r-- | internal/controlplane/manager.go | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/internal/controlplane/manager.go b/internal/controlplane/manager.go index b6be748..212963b 100644 --- a/internal/controlplane/manager.go +++ b/internal/controlplane/manager.go @@ -28,16 +28,19 @@ type policyReplacer interface { } type Manager struct { - store managerStore - catalog *catalog.Catalog - authenticator *auth.StaticAuthenticator - logger *slog.Logger - pollInterval time.Duration - generation atomic.Int64 - redisConnected atomic.Bool - reloadMu sync.Mutex - broadcasts chan ChangeEvent - policyTarget policyReplacer + store managerStore + catalog *catalog.Catalog + authenticator *auth.StaticAuthenticator + logger *slog.Logger + pollInterval time.Duration + generation atomic.Int64 + redisConnected atomic.Bool + loaded atomic.Bool + lastReloadUnix atomic.Int64 + lastHealthyUnix atomic.Int64 + reloadMu sync.Mutex + broadcasts chan ChangeEvent + policyTarget policyReplacer } func NewManager(store managerStore, modelCatalog *catalog.Catalog, authenticator *auth.StaticAuthenticator, logger *slog.Logger, pollInterval time.Duration, policyTargets ...policyReplacer) *Manager { @@ -67,10 +70,30 @@ func (m *Manager) Reload(ctx context.Context) (int64, error) { m.policyTarget.ReplacePolicies(snapshot.Limits) } m.generation.Store(snapshot.Generation) + m.loaded.Store(true) + m.lastReloadUnix.Store(time.Now().UTC().Unix()) + m.lastHealthyUnix.Store(time.Now().UTC().Unix()) m.logger.Info("control_plane_reloaded", "generation", snapshot.Generation, "models", len(snapshot.Models), "api_keys", len(snapshot.APIKeys)) return snapshot.Generation, nil } +func (m *Manager) Loaded() bool { return m.loaded.Load() } +func (m *Manager) LastReloadAt() time.Time { + value := m.lastReloadUnix.Load() + if value == 0 { + return time.Time{} + } + return time.Unix(value, 0).UTC() +} + +func (m *Manager) LastHealthyAt() time.Time { + value := m.lastHealthyUnix.Load() + if value == 0 { + return time.Time{} + } + return time.Unix(value, 0).UTC() +} + func (m *Manager) AfterMutation(ctx context.Context, generation int64, resource, id string) error { loadedGeneration, err := m.Reload(ctx) if err != nil { @@ -135,6 +158,7 @@ func (m *Manager) runPolling(ctx context.Context) { m.logger.Warn("control_plane_generation_check_failed", "error", err) continue } + m.lastHealthyUnix.Store(time.Now().UTC().Unix()) if generation > m.generation.Load() { if _, err := m.Reload(ctx); err != nil { m.logger.Error("control_plane_reload_failed", "source", "postgres", "error", err) |
