feat: background job queue, cron recurring billing, and split payments (#952, #918, #917) - #983
Merged
github-actions[bot] merged 1 commit intoSep 28, 2026
Conversation
…martdevs17#917, Smartdevs17#918, Smartdevs17#952) Implements three payment-platform capabilities, each as a self-contained, tested domain module following the existing BaseService/Result + repository conventions, with an HTTP surface and docs. Smartdevs17#952 — background job queue (backend/src/services/job-queue) Retries with configurable exponential back-off (+ optional full jitter), a dead-letter queue with replay, metrics, and lifecycle events. The caller drives the queue, so retry timing is deterministic and testable. Smartdevs17#918 — cron-based recurring billing (backend/src/services/recurring-billing) Schedules validated against cron-parser with IANA timezone checks, run-due invoicing with start/end/maxRuns bounds, pause/resume/cancel/reschedule, and a sweep wired into the existing scheduled-tasks registry. Smartdevs17#917 — split payments (backend/src/services/split-payments) Exact largest-remainder allocation on integer basis points, so platform fee + recipient shares reconcile to the payment down to the minor unit. Plans, execution, preview, per-recipient minimums and analytics. Tests: 66 new unit tests (job queue 16, recurring billing 25, split payments 25), all passing. New/changed files add no tsc errors over the repo baseline and eslint is clean. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
|
@danieloche635-bit 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! 🚀 |
|
@danieloche635-bit is attempting to deploy a commit to the smartdevs17's projects Team on Vercel. A member of the Team first needs to authorize it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Implements the three open issues assigned in this repo, each as a self-contained, tested domain module following the existing
BaseService/Result+ repository conventions, with an HTTP surface and docs.Closes #952
Closes #918
Closes #917
#952 — Background job queue with retries
backend/src/services/job-queue/computeBackoffDelayMs(failedAttempt, policy)growsinitialDelayMs * multiplier ** (attempt - 1), capped atmaxDelayMs, with optional full jitter.maxAttemptscounts the first attempt.requeueDeadLetter(id).metrics()counters plus lifecycle events (job.enqueued,job.started,job.completed,job.failed,job.retrying,job.dead_lettered) through an injectableonEventsink, and structured logging.drain()/processNext(), so retry timing is testable with an injected clock;start(intervalMs)is available for workers. No silent data loss: a job iscompletedonly after its handler resolves./api/v1/job-queue: enqueue, metrics, list, dead-letters, requeue.backend/docs/JOB_QUEUE.md.#918 — Recurring payment schedules with cron-based billing
backend/src/services/recurring-billing/cron-parserwith presets (hourly/daily/weekly/monthly/yearly) or a raw expression, evaluated in a validated IANA timezone (Intl).startAt/endAt/maxRunsbounds; the first run is the first occurrence on/aftermax(startAt, now)(no backfill from a past start).runDue(now)generates a pending invoice per due schedule and advancesnextRunAt, completing the schedule whenmaxRunsis reached or the next run falls afterendAt. On persistence failure the schedule is left untouched and a failure event fires.src/config/scheduled-tasks.ts) as a*/15 * * * *sweep./api/v1/recurring-payments; Docs:backend/docs/RECURRING_BILLING.md.#917 — Split payments between multiple recipients
backend/src/services/split-payments/platformFeeMinor + Σ share.amountMinor === totalMinorandunallocatedMinor === 0. No drifting cents, even at33.33/33.33/33.34or one-cent splits across many recipients.minimumAmountflags skipped shares./api/v1/split-payments; Docs:backend/docs/SPLIT_PAYMENTS.md.Conventions followed
BaseService+Resulterror mapping,asyncHandlerroutes,ServiceError→ HTTP status.firstParam) matching the existing splits route.Verification
Acceptance criteria
JOB_QUEUE.mdsplits.ts//splitsuntouchedNotes for the reviewer
/api/v1/splitspercentage-of-total implementation; it is left untouched. This PR adds the exact-allocation engine at/api/v1/split-payments(noted inSPLIT_PAYMENTS.md).