Skip to content

fix(repo): promote the bullmq boot and search fixes to main - #2203

Merged
ankit-yc merged 1 commit into
mainfrom
dev
Aug 15, 2026
Merged

fix(repo): promote the bullmq boot and search fixes to main#2203
ankit-yc merged 1 commit into
mainfrom
dev

Conversation

@ankit-yc

Copy link
Copy Markdown
Contributor

PR Checklist

On the middle box: this is a branch promotion rather than a change of its own. The single commit below arrived through its own reviewed PR.

What is the current behavior?

main currently cannot boot the backend.

The promotion in #2193 carried #2188, which took bullmq 5 to 6. bullmq 6 moved ioredis from a direct dependency to an optional peer, and pnpm's auto-install-peers does not install optional peers, so the Redis driver dropped out of the lockfile entirely. git show origin/main:pnpm-lock.yaml | grep '^ /ioredis@' returns nothing.

apps/backend/src/queues/bull.config.ts passes a plain options object as connection rather than a client instance, so bullmq has to load a driver itself and throws:

BullMQ could not load the optional 'ioredis' package.

initQueues() is awaited in main.ts before app.listen, inside a catch that calls process.exit(1), so the HTTP server never binds.

This has not reached production. Only CD Frontend has run on main since #2193; the production backend is still serving (api.yosemitecrew.com/health returns 200) because it has not been redeployed onto this code. The next backend deploy from main would fail.

main also carries two further defects from the same commit, described below.

What is the new behavior?

main matches dev. One commit, 13 files, all in apps/backend plus one dependabot config entry.

The three defects this clears

1. The backend can boot again. ioredis is now a direct dependency of apps/backend, pinned to ^5.11.1 - the same version main ran before #2188, so nothing changes except the driver being present.

2. Recurring jobs will not double-fire. bullmq 5 never keyed a repeatable by jobId; it keyed by the md5 of name:jobId:endDate:tz:every. upsertJobScheduler keys by the plain id, so carrying the ids across the migration added a second entry beside each old one in the same repeat sorted set, and bullmq 6 still schedules from the legacy shape. Without this, a deploy would have produced duplicate no-show marking, duplicate task reminders to users, duplicate recurring-task generation, and doubled polling against the external lab APIs. initQueues() now prunes the legacy entries before upserting.

3. Hyphenated searches work again. Both search call sites feed their value into Prisma contains, which is an ILIKE pattern rather than a regular expression. The regex escape introduced in #2188 emitted \x2d for a hyphen, which ILIKE reads as the literal text x2d, so Jean-Luc searched for Jeanx2dLuc and matched nothing, silently. It is replaced by a proper LIKE escape, which also closes a pre-existing issue where % and _ in user input acted as wildcards.

Validation

#2194 merged with the full pipeline green: 58 checks, zero failures, zero unresolved review comments, and the SonarCloud gate OK on all of Frontend, Backend and Desktop.

Locally on that branch: pnpm run type-check 17/17, pnpm run lint 10/10, and the backend suite at 257 suites / 4866 tests. Both new files (legacy-repeatables.ts, escape-like.ts) are at 100 percent statements, branches, functions and lines.

Each fix was mutation tested by restoring the exact defect that shipped and confirming the suite went red, then restoring it and confirming green. Defect 1 was additionally verified end to end by constructing a real Queue and observing the driver error before the fix and an ordinary connection attempt after it.

The promotion itself is content-clean in both directions:

  • git diff --name-only origin/main...origin/dev gives 13 files, the changes being promoted
  • git diff --name-only origin/dev...origin/main is empty, so main holds no content this would drop

Related Issue(s)

Promotes #2194. Repairs the defects introduced by #2188 and promoted by #2193.

…ix search escaping (#2194)

Three defects from the bullmq/jwks-rsa/escape-string-regexp majors (#2188).
None reached production: only the frontend redeployed on that commit.

bullmq 6 moved ioredis from a direct dependency to an OPTIONAL peer, and
pnpm's auto-install-peers does not install optional peers, so the driver
dropped out of the lockfile entirely. bull.config.ts passes a plain options
object as `connection`, so bullmq has to require('ioredis') itself and threw
"BullMQ could not load the optional 'ioredis' package". initQueues is awaited
before app.listen inside a catch that exits, so this was a whole-backend
outage on next deploy. ioredis is now a direct dependency, pinned to the
5.11.1 line main already ran.

The scheduler ids carried across the migration unchanged, but that was the
wrong thing to check: bullmq 5 never keyed a repeatable by jobId, it keyed by
the md5 of name:jobId:endDate:tz:every. upsertJobScheduler keys by the plain
id, so the upsert added a second entry beside the old one in the same repeat
zset, and bullmq 6 still schedules from the legacy shape. Every recurring job
would have fired twice, indefinitely: duplicate no-show marking, duplicate
task reminders to users, doubled lab polling. initQueues now prunes the md5
entries before upserting.

The escape helper was replaced by a LIKE escape. Both call sites feed the
value into Prisma `contains`, which is an ILIKE pattern and not a regular
expression, so regex escaping was always wrong. It only looked correct
because a backslash before an ordinary character is a no-op in LIKE. Emitting
\x2d for a hyphen broke that: "Jean-Luc" searched for "Jeanx2dLuc" and matched
nothing. Escaping backslash, percent and underscore instead makes the search
mean exactly what was typed, and stops user input acting as a wildcard.

The scheduler suites mock every queue module, so no real Queue is ever built
and they could not have caught the first two. redis-driver.test.ts checks the
dependency graph itself instead.

Co-authored-by: Ankit Upadhyay <ankit@dunexploration.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@sonarqubecloud

Copy link
Copy Markdown

@sonarqubecloud

Copy link
Copy Markdown

@sonarqubecloud

Copy link
Copy Markdown

@sonarqubecloud

Copy link
Copy Markdown

@ankit-yc
ankit-yc merged commit 657f8f3 into main Aug 15, 2026
108 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant