MemoryStore.Retrieve skipped any entry that still carried a LeaseID, with no check of whether that lease had expired. The only release path was PurgeExpired, run on the server's 30s ticker. On the default in-memory backend an un-ACKed message could not be redelivered until lease (30s) + one purge tick (30s) = 60s, despite a documented 30s lease. Postgres already releases inline via leaseexpiresat IS NULL OR leaseexpiresat <= now.
The repo github.com/<project>-dev/<project> was already at the fix commit (fcec908, fix in b120ed7). I located the root cause, verified it, and wrote the solution to ~/DF-CRIER-33-inline-lease-expiry.md.
RetrieveMemoryStore.Retrieve skipped any entry that still carried a LeaseID, with no check of whether that lease had expired. The only release path was PurgeExpired, run on the server's 30s ticker. On the default in-memory backend an un-ACKed message could not be redelivered until lease (30s) + one purge tick (30s) = 60s, despite a documented 30s lease. Postgres already releases inline via lease_expires_at IS NULL OR lease_expires_at <= now.
Fix: mirror the purge-loop expiry-release inside Retrieve. If LeasedAt + LeaseDuration is before now, clear LeasedAt/LeaseID/LeaseDuration and fall through to the leasing path in the same call. PurgeExpired remains the backstop.
internal/registry/memory_store.go → (*MemoryStore).Retrieve (bug/backstop PurgeExpired)internal/registry/postgres_store.go → (*PostgresStore).Retrieve (inline-release precedent)internal/registry/handler.go:619 → 30 * time.Secondcmd/server/main.go → time.NewTicker(30 * time.Second)Pre-fix:
// Skip already leased messages (lease still active).
if entry.LeasedAt != nil && entry.LeaseID != "" {
continue
}
Time is never consulted; only PurgeExpired clears leases. Worst-case redelivery = 30s lease + up to 30s until next tick = 60s.
if entry.LeasedAt != nil && entry.LeaseID != "" {
leaseDuration := entry.LeaseDuration
if leaseDuration == 0 {
leaseDuration = 30 * time.Second
}
if entry.LeasedAt.Add(leaseDuration).Before(now) {
// Lease expired: release inline and treat as available.
entry.LeasedAt = nil
entry.LeaseID = ""
entry.LeaseDuration = 0
} else {
continue
}
}
The stored per-entry LeaseDuration (the lease in force) drives the expiry check; the function parameter drives the new lease. This matches commit b120ed7.
TestRetrieve_LeaseExpiryReleasedInline uses a 100ms lease, never calls PurgeExpired, and asserts: first retrieve returns the message, a retrieve inside the window returns none, and after sleeping 150ms Retrieve returns the message with a new leaseID. Full test source is in the saved markdown.
RED before the fix (worktree at b120ed7^, test hunk only):
memory_store_test.go:127: second retrieve returned 0 message(s), want 1 (msg-1 redelivered)
--- FAIL: TestRetrieve_LeaseExpiryReleasedInline (0.15s)
GREEN after:
--- PASS: TestRetrieve_LeaseExpiryReleasedInline (0.15s)
ok github.com/<project>-dev/<project>/internal/registry 0.154s
No regressions:
ok github.com/<project>-dev/<project>/internal/registry 2.046s
In-memory redelivery now occurs at the documented lease boundary (30s) rather than 60s, matching Postgres. PurgeExpired is unchanged and still reclaims leases for never-retrieved messages and removes TTL-expired entries. The short-lease unit test is deterministic and DB/ticker-independent (RED pre-fix, GREEN post-fix).
# Evidence - Problem class: go-inmemory-store-inline-lease-expiry-release - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-13T10:40:42.814Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "<project> DF-CRIER-33: in-memory store Retrieve skipped leased entries with no inline expiry check, so redelivery waited lease + one purge tick (60s for a documented 30s lease) while the Postgres backend released inline. Fix: mirror the purge loop expiry-release inside Retrieve \u2014 if LeasedAt+LeaseDuration (default 30s) before now, clear LeasedAt/LeaseID/LeaseDuration and fall through to re-lease in the same call. Prove with a short-lease unit test that never calls PurgeExpired and is RED before the fix.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-inmemory-store-inline-lease-expiry-release", "provider": "openrouter", "solved_at": "2026-09-13T10:40:42.814Z", "version": ""}The repo github.com/<project>-dev/<project> was already at the fix commit (fcec908, fix in b120ed7). I located the root cause, verified it, and wrote the solution to ~/DF-CRIER-33-inline-lease-expiry.md.
RetrieveMemoryStore.Retrieve skipped any entry that still carried a LeaseID, with no check of whether that lease had expired. The only release path was PurgeExpired, run on the server's 30s ticker. On the default in-memory backend an un-ACKed message could not be redelivered until lease (30s) + one purge tick (30s) = 60s, despite a documented 30s lease. Postgres already releases inline via lease_expires_at IS NULL OR lease_expires_at <= now.
Fix: mirror the purge-loop expiry-release inside Retrieve. If LeasedAt + LeaseDuration is before now, clear LeasedAt/LeaseID/LeaseDuration and fall through to the leasing path in the same call. PurgeExpired remains the backstop.
internal/registry/memory_store.go → (*MemoryStore).Retrieve (bug/backstop PurgeExpired)internal/registry/postgres_store.go → (*PostgresStore).Retrieve (inline-release precedent)internal/registry/handler.go:619 → 30 * time.Secondcmd/server/main.go → time.NewTicker(30 * time.Second)Pre-fix:
// Skip already leased messages (lease still active).
if entry.LeasedAt != nil && entry.LeaseID != "" {
continue
}
Time is never consulted; only PurgeExpired clears leases. Worst-case redelivery = 30s lease + up to 30s until next tick = 60s.
if entry.LeasedAt != nil && entry.LeaseID != "" {
leaseDuration := entry.LeaseDuration
if leaseDuration == 0 {
leaseDuration = 30 * time.Second
}
if entry.LeasedAt.Add(leaseDuration).Before(now) {
// Lease expired: release inline and treat as available.
entry.LeasedAt = nil
entry.LeaseID = ""
entry.LeaseDuration = 0
} else {
continue
}
}
The stored per-entry LeaseDuration (the lease in force) drives the expiry check; the function parameter drives the new lease. This matches commit b120ed7.
TestRetrieve_LeaseExpiryReleasedInline uses a 100ms lease, never calls PurgeExpired, and asserts: first retrieve returns the message, a retrieve inside the window returns none, and after sleeping 150ms Retrieve returns the message with a new leaseID. Full test source is in the saved markdown.
RED before the fix (worktree at b120ed7^, test hunk only):
memory_store_test.go:127: second retrieve returned 0 message(s), want 1 (msg-1 redelivered)
--- FAIL: TestRetrieve_LeaseExpiryReleasedInline (0.15s)
GREEN after:
--- PASS: TestRetrieve_LeaseExpiryReleasedInline (0.15s)
ok github.com/<project>-dev/<project>/internal/registry 0.154s
No regressions:
ok github.com/<project>-dev/<project>/internal/registry 2.046s
In-memory redelivery now occurs at the documented lease boundary (30s) rather than 60s, matching Postgres. PurgeExpired is unchanged and still reclaims leases for never-retrieved messages and removes TTL-expired entries. The short-lease unit test is deterministic and DB/ticker-independent (RED pre-fix, GREEN post-fix).
# Evidence - Problem class: go-inmemory-store-inline-lease-expiry-release - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-13T10:40:42.814Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "<project> DF-CRIER-33: in-memory store Retrieve skipped leased entries with no inline expiry check, so redelivery waited lease + one purge tick (60s for a documented 30s lease) while the Postgres backend released inline. Fix: mirror the purge loop expiry-release inside Retrieve \u2014 if LeasedAt+LeaseDuration (default 30s) before now, clear LeasedAt/LeaseID/LeaseDuration and fall through to re-lease in the same call. Prove with a short-lease unit test that never calls PurgeExpired and is RED before the fix.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-inmemory-store-inline-lease-expiry-release", "provider": "openrouter", "solved_at": "2026-09-13T10:40:42.814Z", "version": ""}