mirror of
https://github.com/logos-messaging/logos-delivery.git
synced 2026-07-22 12:39:30 +00:00
Two defects the send-service seam had once admission actually enforces, both fixed by a single DeliveryTask.firstAdmittedTime field: - The retry loop gated admission on firstPropagatedTime.isNone(), so a task that failed to propagate (e.g. no peers) was re-admitted on every 1s tick, re-charging the epoch budget and — with the shipped default of one message per epoch — starving all other traffic. Admission is now gated on firstAdmittedTime.isNone(): a task charges one slot / draws one nonce for its lifetime, and retries reuse it. - reportTaskResult reaped any never-propagated task older than MaxTimeInCache (60s) measured from message creation, so an over-budget task parked for a 600s epoch was hard-failed with a misleading "Unable to send within retry time window" long before the epoch could roll (issue #4049). The reaper now runs only for admitted tasks and measures from admission, so a task waiting for epoch budget is exempt and gets a full delivery window once it is finally admitted. The RLN-rejection branch in both processors resets firstAdmittedTime along with clearing the proof, so the regenerated proof's fresh nonce is re-admitted rather than sent uncharged. The reap decision is extracted to DeliveryTask.isDeliveryTimedOut and unit-tested (tests/messaging/test_delivery_task_reaping.nim); a scheduler-level integration test of park-and-release is a follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
40 lines
1.7 KiB
Nim
40 lines
1.7 KiB
Nim
{.used.}
|
|
|
|
import results, chronos, testutils/unittests
|
|
|
|
import logos_delivery/messaging/delivery_service/send_service/delivery_task
|
|
|
|
const MaxTime = chronos.minutes(1)
|
|
|
|
proc taskWith(admitted, propagated: Opt[Moment]): DeliveryTask =
|
|
## Builds a DeliveryTask directly (bypassing `new`, which needs a broker) with
|
|
## only the fields the reaping predicate reads.
|
|
DeliveryTask(firstAdmittedTime: admitted, firstPropagatedTime: propagated)
|
|
|
|
suite "DeliveryTask - delivery-timeout reaping":
|
|
test "a task parked for budget (never admitted) is exempt, however old":
|
|
## The #4049 fix: budget-parked tasks must survive to the epoch roll instead
|
|
## of being aged out with a misleading failure.
|
|
let task = taskWith(Opt.none(Moment), Opt.none(Moment))
|
|
check not task.isDeliveryTimedOut(MaxTime)
|
|
|
|
test "an admitted, never-propagated task past the window times out":
|
|
let task = taskWith(Opt.some(Moment.now() - chronos.minutes(2)), Opt.none(Moment))
|
|
check task.isDeliveryTimedOut(MaxTime)
|
|
|
|
test "an admitted task still within the window does not time out":
|
|
let task = taskWith(Opt.some(Moment.now()), Opt.none(Moment))
|
|
check not task.isDeliveryTimedOut(MaxTime)
|
|
|
|
test "a propagated task is never timed out here (store validation owns it)":
|
|
let task =
|
|
taskWith(Opt.some(Moment.now() - chronos.minutes(2)), Opt.some(Moment.now()))
|
|
check not task.isDeliveryTimedOut(MaxTime)
|
|
|
|
test "the timeout clock runs from admission, not message creation":
|
|
## A task that waited a long time for budget then just got admitted has a
|
|
## fresh clock — it is not reaped immediately on admission.
|
|
let task = taskWith(Opt.some(Moment.now()), Opt.none(Moment))
|
|
check task.admissionAge() < MaxTime
|
|
check not task.isDeliveryTimedOut(MaxTime)
|