@@ -299,12 +299,8 @@ type RateEntry = {key: Text, windowStart: Timestamp, count: Int}
299*seqCounter : Timestamp
299*seqCounter : Timestamp
300-- Bumped by send/heartbeat to wake all blocked /poll holders.
300-- Bumped by send/heartbeat to wake all blocked /poll holders.
301*pollWakeup : Timestamp
301*pollWakeup : Timestamp
302−-- Wall time of the last completed prune sweep (gates /ready).
303−*lastPrunedAt : Timestamp
304-- Wall time of the last self-presence refresh broadcast to peers.
302-- Wall time of the last self-presence refresh broadcast to peers.
305*lastPresenceRefresh : Timestamp
303*lastPresenceRefresh : Timestamp
306−-- Wall time of process start; gates /ready (must be ≤ lastPrunedAt).
307−*startedAt : Timestamp
309-- ============================================
305-- ============================================
@@ -786,7 +782,6 @@ forwardQueuedToServer = \pubkey server -> atomic (do
786-- locally-expired keys, retry pending forwards, and (occasionally) refresh
782-- locally-expired keys, retry pending forwards, and (occasionally) refresh
787-- local presence so peers don't see us drop off.
783-- local presence so peers don't see us drop off.
788pruneAndRetry = \t -> do
784pruneAndRetry = \t -> do
790 expiredLocal <- pruneExpired t
785 expiredLocal <- pruneExpired t
791 fork (broadcastOfflineGossip expiredLocal)
786 fork (broadcastOfflineGossip expiredLocal)
792 when federationEnabled (do
787 when federationEnabled (do
@@ -1199,13 +1194,11 @@ handleFederationBatchForward = \forwards _ -> do
1199-- Readiness handlers
1194-- Readiness handlers
1200-- ============================================
1195-- ============================================
1202−-- GET /ready: signals readiness once the first background prune has run
1203−-- (load-balancer / orchestrator probe).
1197+-- GET /ready: liveness probe (load-balancer / orchestrator). The process runs
1198+-- a synchronous prune sweep before opening the listener, so any response at
1199+-- all means housekeeping has already happened.
1204−handleReady : IO {r *lastPrunedAt, r *startedAt} (Result HttpError {ready: Bool})
1200+handleReady : IO {} (Result HttpError {ready: Bool})
1205−handleReady = do
1201+handleReady = yield (Ok {value: {ready: True}})
1207− lastPrune <- *lastPrunedAt
1208− yield (Ok {value: {ready: lastPrune > 0 && lastPrune >= sa}})
1210-- ============================================
1203-- ============================================
1211-- Dispatch
1204-- Dispatch
@@ -1235,12 +1228,14 @@ api = serve Api where
1235-- holders unblock and return an empty heartbeat response, keeping connections
1228-- holders unblock and return an empty heartbeat response, keeping connections
1236-- fresh.
1229-- fresh.
1238−-- Endless tick: every `backgroundPruneInterval` run `pruneAndRetry`.
1231+-- Endless tick: prune immediately on first call, then every
1232+-- `backgroundPruneInterval`. The startup prune clears stale rows persisted
1233+-- by the previous process before the next interval elapses.
1239−backgroundPrune : IO {rw *challenges, rw *forwardFailures, r *forwards, rw *lastPresenceRefresh, rw *lastPrunedAt, rw *messages, rw *presence, rw *sessions, clock} a
1234+backgroundPrune : IO {rw *challenges, rw *forwardFailures, r *forwards, rw *lastPresenceRefresh, rw *messages, rw *presence, rw *sessions, clock} a
1240backgroundPrune = do
1235backgroundPrune = do
1241− sleep backgroundPruneInterval
1242 t <- now
1236 t <- now
1243 pruneAndRetry t
1237 pruneAndRetry t
1238+ sleep backgroundPruneInterval
1244 backgroundPrune
1239 backgroundPrune
1246-- Endless tick that bumps `pollWakeup` every `pollTimeoutMs` so any blocked
1241-- Endless tick that bumps `pollWakeup` every `pollTimeoutMs` so any blocked
@@ -1255,14 +1250,10 @@ pollHeartbeat = do
1255-- ============================================
1250-- ============================================
1256-- Entry Point
1251-- Entry Point
1257-- ============================================
1252-- ============================================
1258−-- Stamp `startedAt`, spawn the two background loops, and start the listener.
1253+-- Fork the background loops (the prune loop runs an immediate sweep on its
1260−-- Entry point: stamp startup metadata, fork the background loops, and start
1261−-- the HTTP listener.
1254+-- first tick) and start the HTTP listener.
1262main : IO _ {}
1255main : IO _ {}
1263main = do
1256main = do
1265− atomic (do *startedAt = t)
1266 logInfo ("Skrepka relay server starting on " ++ bindHost ++ ":" ++ show listenPort ++ " ...")
1257 logInfo ("Skrepka relay server starting on " ++ bindHost ++ ":" ++ show listenPort ++ " ...")
1267 logInfo (" federation: " ++ (if federationEnabled then "enabled" else "disabled"))
1258 logInfo (" federation: " ++ (if federationEnabled then "enabled" else "disabled"))
1268 fork backgroundPrune
1259 fork backgroundPrune