docs(api): correct cooldownLimiter doc for its OTP reuse
cooldownLimiter began as the wake-only throttle; the OTP-start hardening reused it via the atomic reserve/release. Its type comment still called it a per-server wake limiter and justified the per-replica behaviour as "acceptable because the operator reconcile is idempotent" -- true for wake, false for OTP, whose every admitted send is a non-idempotent email. Rewrite the comment to describe the shared per-key limiter and record the honest KNOWN-LIMITATION: the atomic reserve/release closes the intra-replica concurrent burst, but the in-memory map throttles per replica, so cross-replica bounding still needs a shared store. No behaviour change.
This commit is contained in:
1 file changed
+12
-4
+12
-4
@@ -379,11 +379,19 @@ func principalFromContext(ctx context.Context) *Principal {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- wake cooldown ----
|
// ---- per-key cooldown (wake + OTP) ----
|
||||||
|
|
||||||
// cooldownLimiter is an in-memory per-server rate limiter for the wake lever.
|
// cooldownLimiter is an in-memory per-key cooldown. It backs two throttles with
|
||||||
// It is process-local; with multiple api replicas the effective cooldown is
|
// separate keyspaces: the wake lever (key = server name, via allowed/record) and
|
||||||
// per-replica, which is acceptable because the operator reconcile is idempotent.
|
// the email-OTP start (keys = principal and recipient, via the atomic
|
||||||
|
// reserve/release). It is process-local, so with multiple api replicas the
|
||||||
|
// effective cooldown is per-replica. For wake that is acceptable — the operator
|
||||||
|
// reconcile is idempotent, so a burst slipping through is harmless. For OTP it is a
|
||||||
|
// real KNOWN-LIMITATION: each admitted send is a non-idempotent email, so across N
|
||||||
|
// replicas a determined caller could draw up to N codes per window. The atomic
|
||||||
|
// reserve/release pair closes the intra-replica concurrent burst (the bug fixed in
|
||||||
|
// #35); cross-replica bounding would need a shared store (out of scope for the
|
||||||
|
// single-replica demo).
|
||||||
type cooldownLimiter struct {
|
type cooldownLimiter struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
now func() time.Time
|
now func() time.Time
|
||||||
|
|||||||
Reference in new issue
Block a user