项目文件夹

文件
wehub-resource-sync b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:23:53 +08:00

149 行
5.5 KiB
JSON

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "emdash-aggregator",
"main": "./src/index.ts",
"compatibility_date": "2026-02-24",
"compatibility_flags": ["nodejs_compat"],
// Production routes are configured at deploy time. The CDN
// (`cdn.emdashcms.com`) is a separate Worker that we'll add later
// alongside R2. Local development (`wrangler dev`) doesn't need a route
// binding.
"d1_databases": [
{
"binding": "DB",
"database_name": "emdash-aggregator",
// `database_id` intentionally omitted — wrangler auto-provisions
// the D1 instance on first deploy. A placeholder ID would make
// wrangler think the binding is already configured and skip
// provisioning.
"migrations_dir": "./migrations",
},
],
"queues": {
"producers": [
{
"binding": "RECORDS_QUEUE",
"queue": "emdash-aggregator-records",
},
{
// Backfill orchestrator (POST /_admin/backfill) fans
// (DID, collection) pairs onto this queue. Per-pair work
// (resolve PDS → listRecords → sendBatch onto RECORDS_QUEUE)
// fits well within a single consumer invocation's waitUntil,
// solving the 30s wall-clock cap that would otherwise limit
// us to ~15–25 DIDs per backfill POST.
"binding": "BACKFILL_QUEUE",
"queue": "emdash-aggregator-backfill",
},
],
"consumers": [
{
"queue": "emdash-aggregator-records",
"max_batch_size": 25,
"max_batch_timeout": 5,
"max_retries": 5,
"dead_letter_queue": "emdash-aggregator-records-dlq",
},
{
// Drains the DLQ. Today the consumer logs each dead-lettered
// job to Workers logs and writes a `dead_letters` row, then
// acks. On D1 failure the handler calls `message.retry()`
// (configured `max_retries: 3` per below); after that, the
// DLQ has no DLQ-of-DLQ so workerd drops the message. Once
// the reconciliation pass lands it'll replace this with
// retry-from-listRecords.
"queue": "emdash-aggregator-records-dlq",
"max_batch_size": 25,
"max_batch_timeout": 30,
"max_retries": 3,
},
{
// Backfill (DID, collection) consumer. Each job: resolve
// PDS, paginate listRecords for one collection, batch
// results onto RECORDS_QUEUE. `max_batch_size: 1` so each
// pair gets its own consumer invocation — listRecords can
// chain ~15s per page × `MAX_PAGES_PER_COLLECTION`, so
// batching multiple pairs per invocation risks blowing
// the consumer wall-clock budget. Throughput is fine
// because backfill is operator-triggered, not steady-state.
"queue": "emdash-aggregator-backfill",
"max_batch_size": 1,
"max_batch_timeout": 5,
"max_retries": 3,
"dead_letter_queue": "emdash-aggregator-backfill-dlq",
},
{
// Drains the backfill DLQ. Logs each dead-lettered pair
// loud enough that operators tailing logs see it, then
// acks so the DLQ doesn't accumulate unbounded. We don't
// write a forensics row to D1 here (no `backfill_dead_letters`
// table) because the operator's recovery action is
// "re-trigger backfill for the affected DID" — they don't
// need the per-pair payload, just the (did, collection)
// pair, which is on the log line.
"queue": "emdash-aggregator-backfill-dlq",
"max_batch_size": 25,
"max_batch_timeout": 30,
"max_retries": 3,
},
],
},
"durable_objects": {
"bindings": [
{
"name": "RECORDS_DO",
"class_name": "RecordsJetstreamDO",
},
],
},
"migrations": [
{
"tag": "v1",
"new_sqlite_classes": ["RecordsJetstreamDO"],
},
],
"triggers": {
// Liveness ping for the records DO. The DO holds Jetstream open and
// stays alive while the WebSocket is up, but during a Jetstream
// outage it spends time in backoff sleeps with no active connection
// — that's when CF can evict it. The 5-minute cron wakes it back up
// quickly; constructor-time `ingestor.run()` resumes from the
// persisted cursor. Reconciliation work will share this trigger when
// it lands.
"crons": ["*/5 * * * *"],
},
"vars": {
"NODE_OPTIONS": "--max-old-space-size=6144",
// Jetstream endpoint. Override per environment for self-hosted relays
// or staging backends.
"JETSTREAM_URL": "wss://jetstream2.us-east.bsky.network/subscribe",
// Relay base URL implementing `com.atproto.sync.listReposByCollection`,
// used by `/_admin/backfill` to enumerate publishers of our NSIDs at
// cold-start time. Defaults to Bluesky's main relay (the canonical
// atproto relay; same trust orbit as our Jetstream endpoint).
// Override for self-hosted indexers (e.g. Microcosm's Lightrail)
// if/when we want a non-bsky.network discovery path.
"RELAY_URL": "https://bsky.network",
},
// Required secrets, declared in config so `wrangler types` generates the
// typed binding and `wrangler deploy` validates the secret is set on the
// target Worker before publishing. `wrangler dev` warns at startup when a
// required secret isn't in `.env`.
//
// Set in production with `wrangler secret put ADMIN_TOKEN`. Tests bind
// a stub via miniflare in vitest.config.ts. Local dev pulls from
// `.env` (gitignored; see `.env.example`).
//
// The `requireAdminAuth` runtime guard fails closed (503) if the binding
// is somehow empty at request time, so even a misconfigured deploy can't
// leave the admin routes unauth-passable. NOTE: this `secrets` block is
// not inherited by named environments — repeat it under each `env.<name>`
// you add or that env's deploys won't enforce the secret.
"secrets": {
"required": ["ADMIN_TOKEN"],
},
"observability": {
"enabled": true,
},
}