Files
moeka-project/apps/server/drizzle/0010_sudden_bastion.sql
T
RainbowBird f8d1fa7a64 refactor(server): drop redis stream + worker role (#1792)
The Redis Stream `billing-events` + `worker` Railway role +
advisory-lock poller layered together didn't actually buy us reliability
— `debitFlux` swallowed XADD failures, leaving the door open to "balance
updated, ledger row never written". Collapse the whole thing back to:
`creditFlux` and `debitFlux` write `flux_transaction` ledger rows inline
within the same DB transaction that mutates `user_flux`, and `(user_id,
request_id)` remains the partial unique index that keeps retries safe.

Concrete changes:
- Inline ledger inserts in `BillingService.{debitFlux, creditFlux,
creditFluxFromStripeCheckout, creditFluxFromInvoice}`; drop `billingMq`
and `publishEvent` plumbing entirely.
- `routes/openai/v1` writes `llm_request_log` synchronously via the
existing `requestLogService`; the duplicate `llm-request-log.ts` service
module is removed.
- `bin/run-worker.ts`, `libs/mq/*`,
`services/billing/billing-events.ts`,
`services/billing/billing-consumer-handler.ts`, and matching tests are
deleted. CLI now exposes only `api`.
- `BILLING_EVENTS_*` env vars and the `DEFAULT_BILLING_EVENTS_STREAM`
helper are dropped; `docker-compose.yml` no longer ships a worker
service.
- `docs/ai-context/{workers-and-runtime, billing-architecture,
redis-boundaries-and-pubsub, data-model-and-state,
architecture-overview, README}.md`, `CLAUDE.md`, and the existing
verification docs are updated to describe the single-process synchronous
pipeline.

Tests: 29 files / 247 cases pass. Production deployments need to drop
the worker Railway service after this lands.
2026-05-08 21:14:01 +08:00

31 lines
1.4 KiB
SQL

CREATE TABLE "flux_grant_batch" (
"id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"type" text NOT NULL,
"amount" bigint NOT NULL,
"description" text,
"status" text NOT NULL,
"created_by_user_id" text NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"started_at" timestamp,
"completed_at" timestamp
);
--> statement-breakpoint
CREATE TABLE "flux_grant_batch_recipient" (
"id" text PRIMARY KEY NOT NULL,
"batch_id" text NOT NULL,
"input_email" text NOT NULL,
"user_id" text,
"status" text NOT NULL,
"error_reason" text,
"flux_transaction_id" text,
"attempt_count" integer DEFAULT 0 NOT NULL,
"last_attempted_at" timestamp,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE INDEX "flux_grant_batch_status_idx" ON "flux_grant_batch" USING btree ("status");--> statement-breakpoint
CREATE INDEX "flux_grant_batch_created_by_idx" ON "flux_grant_batch" USING btree ("created_by_user_id");--> statement-breakpoint
CREATE INDEX "flux_grant_batch_recipient_batch_status_idx" ON "flux_grant_batch_recipient" USING btree ("batch_id","status");--> statement-breakpoint
CREATE INDEX "flux_grant_batch_recipient_pending_idx" ON "flux_grant_batch_recipient" USING btree ("status","last_attempted_at") WHERE status = 'pending';--> statement-breakpoint
CREATE UNIQUE INDEX "flux_grant_batch_recipient_batch_email_uniq" ON "flux_grant_batch_recipient" USING btree ("batch_id","input_email");