Skip to content

feat(billing): schedule Stripe reconciliation continuously - #579

Draft
seonghobae wants to merge 16 commits into
feat/stripe-reconciliation-dead-letter-recovery-488from
feat/stripe-reconciliation-scheduler-488
Draft

feat(billing): schedule Stripe reconciliation continuously#579
seonghobae wants to merge 16 commits into
feat/stripe-reconciliation-dead-letter-recovery-488from
feat/stripe-reconciliation-scheduler-488

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Buyer/operability objective

Refs #488. This Draft child of #575 makes the durable Stripe reconciliation worker operational in the long-running ScopeWeave API process instead of requiring an external/manual caller. It adds a single-flight polling scheduler, bounded poll configuration, sanitized failure reporting, and bounded graceful SIGINT/SIGTERM shutdown.

Exact current stack

  • protected develop: 2c328875e00e86537df3e965170be80532571cad;
  • exact live parent feat(billing): recover Stripe reconciliation dead letters #575: feat/stripe-reconciliation-dead-letter-recovery-488@e557fbb89b5998a3e3204b1d67125b1c0a010fbb;
  • exact contributor head: 673fde2c10108783ddcc698cbe4c233d118c3ae9;
  • branch: feat/stripe-reconciliation-scheduler-488;
  • state: Draft and mechanically mergeable at the latest refetch;
  • current submitted reviews/inline threads: none.

The parent moved after this child was created. The child had already content-forwarded the parent's three-line Stripe fixture repair, so merge commit 40e2fbfb95193b657ccfc7217513bfe448d71d40 non-destructively reconciled the exact live parent without weakening the child tree. The current bounded delta adds one focused forced-close regression to the prior five scheduler paths, for six changed paths total: package.json, server/server.mjs, server/server_runtime.mjs, server/stripe_reconciliation_scheduler.mjs, tests/unit/stripe-reconciliation-scheduler.test.mjs, and tests/unit/server-runtime-force-close.test.mjs.

Scheduler contract

  • one outstanding timer only; the next poll is armed only after the current reconciliation settles;
  • canonical operator poll interval is 250–60,000 ms, defaulting to 1 second;
  • stop-during-in-flight cannot resurrect the scheduler;
  • provider/runtime failures collapse to stable non-secret operational codes; and
  • SIGINT/SIGTERM stops future provider work before closing the HTTP listener.

Bounded shutdown contract and repair

ScopeWeave has long-lived SSE responses, while Node HTTP documents that server.close() does not close connections actively sending a request or waiting for a response. This slice therefore keeps server.close() first, grants a 10-second graceful drain, then uses server.closeAllConnections() when available so active HTTP/SSE responses cannot keep rollout termination open indefinitely. Synchronous/naturally completed close avoids force termination, shutdown is idempotent, and timer ports are injectable for deterministic coverage.

Fresh current-source inspection found a failure-path defect in that watchdog: if closeAllConnections() itself threw synchronously, its raw exception escaped instead of being collapsed to the runtime's stable non-secret shutdown code. The repair was test-first on the existing branch:

  • RED commits 98142bfc7fdc0b17e197e8ed9e7b3839f858d4bb and 1636b6b6e6d11baeb44f0875c53cfe27bbb83d7f add and canonically register tests/unit/server-runtime-force-close.test.mjs. The regression injects a force-close exception containing a private socket path and requires the watchdog not to throw while reporting only scopeweave_server_shutdown_failed.
  • Hosted Server Tests run 32548602196, job 96971485570, reproduced the failure exactly: the private socket /secret/runtime.sock must not escape exception escaped from forceCloseAfterGrace.
  • GREEN production commit 673fde2c10108783ddcc698cbe4c233d118c3ae9 catches only that force-close boundary and routes it through the existing stable failure-code sink. It does not weaken the graceful-drain window, force-close ordering, or other shutdown semantics.
  • Current Server Tests run 32548689467 is terminal success; unit-and-api job 96971717008 passes the new regression and cloud-e2e job 96971716925 is also terminal success.

The current Server Tests workflow still checks GitHub's synthetic pull-request merge revision rather than proving the contributor checkout itself, so these successful behavioral results are not promoted to exact-head merge authorization before #523's control reaches protected develop.

This ordering follows Node's documented guidance: when closeAllConnections() is used with server.close(), call it after server.close() to avoid a new-connection race.

Parent repair preserved

The child preserves #575's 4 KiB Hono bodyLimit repair and both API regressions for declared-length and streamed oversized dead-letter recovery bodies. The parent repair remains present by ancestry as well as by identical content.

Current evidence boundary

Fresh repository-native runs associated with exact contributor head 673fde2c10108783ddcc698cbe4c233d118c3ae9 are terminal success:

  • Server Tests 32548689467 — success (unit-and-api 96971717008; cloud-e2e 96971716925);
  • Dependency Review 32548689617 — success; and
  • OSV Scanner 32548689764 — success.

This remains non-authorizing evidence for integration. On this stacked PR, Fuzz, Security Scan, SAST Semgrep, and CodeQL Required are absent from the current contributor-head workflow enumeration and are therefore non-passing under the commercial evidence contract. The Server Tests checkout is still synthetic until the repository-wide exact-head control repair in #523 is protected-shipped. Predecessor, absent, skipped-required, synthetic, status-only, model-only, or stale evidence is not transferred. There is no qualifying independent exact-current-head approval.

Primary implementation basis

Remain Draft. Do not integrate independently of #575/#574/#573/#570/#569/#568 and the preceding #488 stack. Before integration, refetch the then-live prerequisite stack and regenerate every applicable exact-head repository/organization deterministic/browser/coverage/CodeQL/SAST/security/dependency/supply-chain/package/provenance/review gate under live governance.

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e650dc01-3775-48a1-adc8-b91aad0979c0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@opencode-agent opencode-agent Bot added priority: medium Normal-priority or P2 work status: draft Draft pull request type: feature New or expanded product capability labels Aug 22, 2026
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: medium Normal-priority or P2 work status: draft Draft pull request type: feature New or expanded product capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant