Files
accounted/lib/connect/instance/manual-sync-throttle.ts
T
Mattsson ee22c9c7b7 feat(connect): connector status + Synka nu row in Settings -> Abonnemang (PR6b-3) (#2104)
* feat(connect): connector status + Synka nu row in Settings -> Abonnemang (PR6b-3)

Self-host only: shows per-upstream connector mode, key prefix, and the
active company's granted capabilities from GET /api/connector/status,
plus a manual run of the entitlement sync via the new authed
POST /api/connector/sync (requireWrite, 60s cooldown) instead of
waiting for the hourly cron. Hidden on hosted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KAUKbGUGtAmRhpDKfn84F5

* fix(connect): handle sync fetch rejection, count capabilities not rows, not_configured toast

Skeptic findings on the Synka nu flow: a rejected fetch (instance
restarting) was a silent no-op with an unhandled rejection; the success
toast printed grant rows (companies x scopes) as capabilities; a
not_configured outcome claimed the hosted service was unreachable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KAUKbGUGtAmRhpDKfn84F5

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-09-01 11:44:33 +02:00

31 lines
1.0 KiB
TypeScript

/**
* Cooldown for the operator-triggered connector sync (POST /api/connector/sync).
* Every run POSTs the instance's company count to the hosted entitlements
* endpoint, so a click storm in the settings panel must not turn into a
* request storm against the hosted service. Module-level state is enough:
* self-hosted runs as one long-lived process, and the hourly cron is
* unaffected (it never goes through this gate).
*/
export const MANUAL_SYNC_COOLDOWN_MS = 60_000
let inFlight = false
let lastStartedAt = 0
/** Claims the sync slot; false while a sync runs or the cooldown holds. */
export function tryBeginManualSync(now: number = Date.now()): boolean {
if (inFlight || now - lastStartedAt < MANUAL_SYNC_COOLDOWN_MS) return false
inFlight = true
lastStartedAt = now
return true
}
export function endManualSync(): void {
inFlight = false
}
/** Test hook: clears the in-flight flag and the cooldown window. */
export function resetManualSyncThrottle(): void {
inFlight = false
lastStartedAt = 0
}