Skip to content

Fix: 4 issues (#83, #84, #85, #86) - #132

Merged
victorisiguzoruzoma874 merged 3 commits into
SynapsVault:mainfrom
Kaselchumfa:simple/83-84-85-86
Oct 18, 2026
Merged

victorisiguzoruzoma874 merged 3 commits into
SynapsVault:mainfrom
Kaselchumfa:simple/83-84-85-86

Conversation

@Kaselchumfa

Copy link
Copy Markdown
Contributor

Closes #83
Closes #84
Closes #85
Closes #86

Issues

#83 Retry worker never marks a resource failed when the existence check keeps erroring

Where

src/workers/retryPendingWorker.ts (retryResource catch uses retryCounts.get(id) ?? 1).

Problem

If resourceExists() throws on every tick, the counter never reaches the limit. The resource stays pending and is retried forever.

Expected

Count each attempt before any RPC call. Mark the resource failed when attempts are exhausted, whatever the error.

Acceptance criteria

  • A test where resourceExists rejects four times ends with status failed.

#84 Retry attempt counts live in memory and reset on every restart

Where

src/workers/retryPendingWorker.ts (retryCounts Map).

Problem

Each deploy resets the attempt budget, so a resource that always fails is retried indefinitely across deploys.

Expected

Persist attempts in an onchain_attempts column.

Acceptance criteria

  • The count survives a worker restart in a test.
  • The limit is enforced across restarts.

#85 Retry worker ticks can overlap and process an unbounded backlog one by one

Where

src/workers/retryPendingWorker.ts (tick has no in-flight guard and no batch limit).

Problem

A slow RPC makes a tick run into the next one. A large backlog makes each tick very long.

Expected

Add an in-flight flag, a batch LIMIT, and a per-item timeout.

Acceptance criteria

  • Two overlapping tick calls run only one batch.
  • The batch size is configurable.

#86 Payment is recorded before the file is delivered, with no delivery status

Where

src/routes/resources.ts (GET /resources/:id inserts into payments, then calls downloadFile).

Problem

If the storage download fails after the insert, the buyer has paid and received nothing, and the payment row gives no sign of that.

Expected

Fetch the content before recording the payment, or record a delivery status and expose a reconciliation path.

Acceptance criteria

  • A test where downloadFile throws leaves the payment marked undelivered.
  • An error is logged for reconciliation.

Summary

The migration file drizzle/0011_onchain_attempts.sql already exists but is empty; fill it in rather than creating a new migration. Use an atomic SQL increment for onchain_attempts to avoid races between overlapping ticks. The in-flight guard should be reset in a finally block so a thrown error cannot permanently wedge the worker. For #86, prefer fetching content before inserting the payment; if the payment must be inserted first for other reasons, set delivery_status='undelivered' on failure and log at error level with resourceId and paymentId. Add tests: resourceExists rejects four times -> status 'failed' (#83); worker restart preserves count and enforces limit (#84); two overlapping ticks run one batch and batch size is configurable (#85); downloadFile throws -> payment marked undelivered and error logged (#86).

Changes

  • Add an onchainAttempts integer column to the resources table (name onchain_attempts, not null, default 0) so retry attempt counts persist across worker restarts. Also add a deliveryStatus text column to the payments table (name delivery_status, not null, default 'delivered') so undelivered payments can be marked and reconciled. Export both in the Drizzle schema. (src/db/schema.ts)
  • Create the Drizzle migration SQL for the new columns: ALTER TABLE resources ADD COLUMN onchain_attempts integer NOT NULL DEFAULT 0; and ALTER TABLE payments ADD COLUMN delivery_status text NOT NULL DEFAULT 'delivered';. This backs the persisted attempt counter (Retry attempt counts live in memory and reset on every restart #84) and the payment delivery status (Payment is recorded before the file is delivered, with no delivery status #86). (drizzle/0011_onchain_attempts.sql)
  • Add worker configuration to the env schema: RETRY_WORKER_BATCH_SIZE (coerced number, default e.g. 25) and RETRY_WORKER_ITEM_TIMEOUT_MS (coerced number, default e.g. 30_000), so the retry worker's batch limit and per-item timeout are configurable (Retry worker ticks can overlap and process an unbounded backlog one by one #85). (src/config.ts)
  • Rework the retry worker to fix all three retry issues. (Retry worker never marks a resource failed when the existence check keeps erroring #83) Increment and persist onchainAttempts in the DB before any RPC call (atomic UPDATE ... SET onchain_attempts = onchain_attempts + 1 RETURNING onchain_attempts), and in the catch path mark the resource failed when the persisted count exceeds MAX_RETRY_ATTEMPTS, regardless of which call threw — so a resourceExists that rejects four times ends with status failed. (Retry attempt counts live in memory and reset on every restart #84) Remove the in-memory retryCounts Map entirely; read and enforce the limit from the persisted onchain_attempts column so counts and the limit survive a worker restart. (Retry worker ticks can overlap and process an unbounded backlog one by one #85) Add a module-level in-flight boolean guard so overlapping tick calls run only one batch, apply a configurable LIMIT (from config.RETRY_WORKER_BATCH_SIZE) to the pending-resources query, and wrap each item's retryResource call in a per-item timeout (config.RETRY_WORKER_ITEM_TIMEOUT_MS) so a slow RPC cannot stall the batch. (src/workers/retryPendingWorker.ts)
  • Fix the download route so a storage failure does not leave a silently undelivered payment (Payment is recorded before the file is delivered, with no delivery status #86). Fetch the file content via downloadFile before inserting the payment row (for file resources); if downloadFile throws, record the payment with deliveryStatus: 'undelivered' (or skip recording and log), log an error with resource and payment identifiers for reconciliation, and return an error to the buyer. When delivery succeeds, record the payment with deliveryStatus: 'delivered'. Keep the link-resource path recording payments as delivered. (src/routes/resources.ts)

Co-authored-by: Simple Agent <agent@simple.dev>
@vercel

vercel Bot commented Oct 18, 2026

Copy link
Copy Markdown

@Kaselchumfa is attempting to deploy a commit to the work Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Oct 18, 2026

Copy link
Copy Markdown

@Kaselchumfa Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

- src/db/schema.ts: merged [markers] — model resolved the conflict markers
- src/workers/retryPendingWorker.ts: merged [markers] — model resolved the conflict markers

Co-authored-by: Simple Agent <agent@simple.dev>
- src/db/schema.ts: merged [markers] — model resolved the conflict markers

Co-authored-by: Simple Agent <agent@simple.dev>
@victorisiguzoruzoma874
victorisiguzoruzoma874 merged commit ac35562 into SynapsVault:main Oct 18, 2026
1 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants