-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmanager_methods.go
More file actions
96 lines (87 loc) · 4.49 KB
/
Copy pathmanager_methods.go
File metadata and controls
96 lines (87 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Proxy methods exposing the Manager's lifecycle and drain API at the
// public package boundary. The Manager type aliases the internal
// implementation; these wrappers exist so external callers see the
// methods directly on the public type and so godoc renders them.
package systemplane
import (
"context"
tmevent "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/event"
)
// OnTenantActivated bootstraps systemplane state for tenantID:
//
// 1. Resolves the tenant's database via the bound tenant-manager
// Postgres Manager.
// 2. Runs idempotent schema DDL (CREATE TABLE IF NOT EXISTS plus the
// NOTIFY trigger function/triggers). Byte-compatible with the
// existing lazy bootstrap in MT mode.
// 3. Seeds every registered key's default value with
// INSERT ON CONFLICT (namespace, key) DO NOTHING. Never overwrites
// operator-set values.
// 4. Warm-loads every registered key into the per-tenant cache.
// 5. Opens the per-tenant LISTEN goroutine on systemplane_changes.
//
// Idempotent. Calling twice in a row is safe: the second call observes
// the existing state and no-ops the parts already done. Order-tolerant:
// calling OnTenantSuspended or OnTenantDeleted before OnTenantActivated
// is fine — both are no-ops for unknown tenants, and a follow-up
// OnTenantActivated rebuilds state.
func (m *Manager) OnTenantActivated(ctx context.Context, tenantID string) error {
return asInternalManager(m).OnTenantActivated(ctx, tenantID)
}
// OnTenantSuspended cancels the LISTEN goroutine for tenantID and marks
// the cache stale. Cache entries are retained so a fast reactivation
// avoids re-warming, but reads after suspension fall through to the
// tenant DB to surface any operator changes made during the suspension
// window. Idempotent.
func (m *Manager) OnTenantSuspended(ctx context.Context, tenantID string) error {
return asInternalManager(m).OnTenantSuspended(ctx, tenantID)
}
// OnTenantDeleted closes the LISTEN goroutine for tenantID and evicts
// the cache. Frees process resources tied to the tenant. Idempotent —
// calling for an unknown tenant is a no-op.
func (m *Manager) OnTenantDeleted(ctx context.Context, tenantID string) error {
return asInternalManager(m).OnTenantDeleted(ctx, tenantID)
}
// OnTenantCredentialsRotated closes the existing LISTEN goroutine,
// evicts per-tenant state, and re-runs the OnTenantActivated sequence
// with refreshed credentials. The tenant-manager Postgres Manager is
// expected to surface the new DSN through its existing config-change
// detection; the systemplane Manager simply asks for the connection
// again and gets the fresh handle.
func (m *Manager) OnTenantCredentialsRotated(ctx context.Context, tenantID string) error {
return asInternalManager(m).OnTenantCredentialsRotated(ctx, tenantID)
}
// Drain closes every active per-tenant LISTEN goroutine for graceful
// shutdown. After Drain returns the Manager rejects subsequent lifecycle
// calls and Gets fall through to the DB-read path. Idempotent.
//
// Drain blocks up to an internal close timeout per goroutine waiting for
// it to exit, but honours ctx cancellation: if the caller's shutdown
// budget expires (ctx.Done fires) before every goroutine has acknowledged
// its cancel signal, Drain returns immediately. The in-flight goroutines
// still observe the per-listen ctx cancellation and will exit on their
// own — Drain just stops waiting for them.
func (m *Manager) Drain(ctx context.Context) error {
return asInternalManager(m).Drain(ctx)
}
// IsClosed reports whether Drain has been called. Useful as a probe in
// shutdown plumbing.
func (m *Manager) IsClosed() bool {
return asInternalManager(m).IsClosed()
}
// HandleTenantLifecycle routes a tenant lifecycle event to the matching On*
// handler, so consumers stop hand-rolling a switch over event.EventType.
// Non-tenant-lifecycle event types are ignored (no-op).
//
// Best-effort: an On* handler error is logged at WARN via the Manager's
// logger and SWALLOWED (returns nil) — a transient LISTEN reconnect failure
// must never wedge the consumer's lifecycle dispatch pipeline.
//
// The signature is intentionally identical to
// github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/event.EventHandler
// so a bound Manager can be registered directly as an event handler.
//
// Nil-receiver safe: calling on a nil Manager is a no-op returning nil.
func (m *Manager) HandleTenantLifecycle(ctx context.Context, event tmevent.TenantLifecycleEvent) error {
return asInternalManager(m).HandleTenantLifecycle(ctx, event)
}