Files
twenty/packages/twenty-apps/public/last-contact/package.json
T
martmull 6f361a9bf2 refactor(last-contact): drive backfill with enqueued jobs (#23646)
## What

Reworks the last-contact backfill, which previously ran an orchestrator
that called its own HTTP route in a recursive loop with blocking
`sleep`s, into a single upfront fan-out of enqueued jobs.

On install, `backfill-last-contact` counts people, opportunities and
companies, then enqueues one job per record batch (`ceil(count /
batchSize)`) for each. Each batch job receives its `batchId` in its
payload and processes the matching record window via offset pagination
(`first`/`offset` with a stable `createdAt, id` ordering). No
self-calling loop, no blocking sleeps, no per-batch chaining, no kv
progress state.

Phases don't need to run in sequence: each phase recomputes last-contact
from source interactions (message and calendar participants), not from
the person's stored field, so the jobs are independent and safe to run
concurrently.

## Changes

- `backfill-last-contact` (post-install): counts each phase and fans out
all batch jobs via `enqueueJob`; timeout raised to 300s. Enqueues are
concurrency-limited and staggered with `delayMs` (from
`LAST_CONTACT_BACKFILL_SLEEP_MS`) so thousands of jobs don't all become
eligible at once.
- `src/utils/enqueue-backfill-jobs.ts` (new): counts a phase via the
connection `totalCount`, builds the batch plan, and enqueues the jobs.
- `src/utils/backfill-batch-args.ts` (new): `first`/`offset`/`orderBy`
window for a given `batchId`, ordered by `createdAt, id` so offsets stay
stable while the backfill runs.
- `backfill-{people,opportunities,companies}-last-contact`: handlers now
take `{ batchId }`, query their offset window, process it, and return `{
batchId, count }`. No HTTP route triggers, no cursor/kv state.
- Removed the chaining util (`advance-backfill.ts`) and the
now-purposeless kv-state debug helper (`backfill-get-state.ts`).
- Bumped `twenty-sdk`/`twenty-client-sdk` to `^2.26.0` (first published
version exporting `enqueueJob`), app version to `1.2.3`, plus changelog.
Updated the server-variable copy.

## Testing

- `yarn typecheck` clean
- `yarn lint` clean (0 warnings, 0 errors)
- `yarn test:unit` green (38 passed)
2026-07-31 15:53:14 +00:00

38 lines
961 B
JSON

{
"name": "@twentyhq/last-contact",
"version": "1.2.3",
"license": "MIT",
"engines": {
"node": "^24.5.0",
"npm": "please-use-yarn",
"yarn": ">=4.0.2",
"twenty": ">=2.26.0"
},
"keywords": [
"twenty-app"
],
"packageManager": "yarn@4.9.2",
"scripts": {
"twenty": "twenty",
"lint": "oxlint -c .oxlintrc.json .",
"lint:fix": "oxlint --fix -c .oxlintrc.json .",
"typecheck": "tsgo --noEmit -p tsconfig.spec.json",
"test": "vitest run",
"test:watch": "vitest",
"test:unit": "vitest run --config vitest.unit.config.ts"
},
"devDependencies": {
"@types/node": "^24.7.2",
"@types/react": "^19.0.0",
"@typescript/native-preview": "^7.0.0-dev.20260116.1",
"oxlint": "^0.16.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"twenty-client-sdk": "^2.26.0",
"twenty-sdk": "^2.26.0",
"typescript": "^5.9.3",
"vite-tsconfig-paths": "^4.2.1",
"vitest": "^4.0.0"
}
}