Repository navigation
feat: add prefix method to publisher, rate limiter, and lock adapters - #2332
Conversation
Adapters with a `prefix` option now have a `prefix()` method that returns a new adapter with the given prefix appended, sharing the same client, so it is cheap to create per request or tenant. Memory adapters do not have it.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
orpc | 4064a06 | Commit Preview URL Branch Preview URL |
Oct 24 2026, 01:58 PM |
More templates
@orpc/ai-sdk
@orpc/arktype
@orpc/bun
@orpc/client
@orpc/cloudflare
@orpc/contract
@orpc/effect
@orpc/evlog
@orpc/hibernation
@orpc/json-schema
@orpc/experimental-lock
@orpc/mcp
@orpc/msw
@orpc/nest
@orpc/next
@orpc/node
@orpc/openapi
@orpc/opentelemetry
@orpc/pinia-colada
@orpc/pino
@orpc/publisher
@orpc/ratelimit
@orpc/server
@orpc/shared
@orpc/swr
@orpc/tanstack-query
@orpc/trpc
@orpc/valibot
@orpc/zod
commit: |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Merging this PR will not alter performance1 warning
Comparing Footnotes
|
Upstash integration tests are skipped in CI without credentials, so test prefix() against a fake client instead.
There was a problem hiding this comment.
ℹ️ No critical issues — one minor docs wording nit inline.
Reviewed changes
prefix()on every Redis/Upstash/Bun/Cloudflare adapter — publisher, rate limiter, and lock adapters gain aprefix(prefix)method returning a new instance with the prefix appended while sharing the original's client / binding / namespace.- Shared subscriber for prefixed publishers —
RedisPublishernow keeps a singleerrorlistener per subscriber via a module-levelsubscriberOnErrorsWeakMap, andBunRedisPublisherhands itsonce-wrappedgetSubscriberandonErrorsto prefixed instances, so per-requestprefix()calls don't accumulate listeners. - Protected field rename —
BaseRedisLocker/BaseRedisRateLimiter'sprefixbecomeskeyPrefixandBaseRedisPublisher's becomeseventPrefix(Cloudflare adapters likewise); documented in the PR body as breaking for custom subclasses, which is fine on the2.0.0-beta.xline. - Tests and docs — each adapter has a "shares ... with ... created by prefix" test, plus a
prefix()example per adapter in the helper docs.
I verified the diff end-to-end and independently traced the shared-subscriber refactor (listener count, error fan-out, and unsubscribe scope) without finding a defect; tsc -b for publisher/lock/ratelimit/bun, the root tsc --noEmit, and eslint on the changed files all pass. The Redis/Upstash/Bun suites are credential/runtime-gated here, so CI is their first run.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
ℹ️ No new issues in the follow-up commit — the earlier docs-wording suggestion is still open (the docs weren't touched here).
Reviewed changes (since 76bde9d)
- Upstash
prefix()tests moved from integration to unit tests (c989404) — the three credential-gated Upstash integration tests forprefix()are replaced with always-run unit tests that use a mocked client and assert the appended key/channel (app:tenant:key,tenant:event) and client reuse, so CI now exercisesprefix()for Upstash without credentials. - Verified locally: the three new tests pass (
3 passed | 36 skipped),eslintis clean on the changed files, and the roottsc --noEmitpasses.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
The Upstash publisher tests have been failing since #2332 renamed the protected `prefix` field to `eventPrefix`. The tests still read `prefix`, which now returns the new `prefix()` method, so they looked up the wrong Redis keys and channels. ## Fixes - "supports custom serializers and custom prefixes" finds its stream key again. - "does not crash if teardown runs after internal maps were already pruned" finds its subscription and cleans it up, so the suite-wide `afterAll` cleanup check passes again. ## Testing - Publisher, rate limiter, and lock Upstash suites pass locally against a real Upstash server (39/39).

Publisher, rate limiter, and lock adapters that take a
prefixoption now also have aprefix()method. It returns a new adapter with the given prefix appended that shares the original's client, so scoping per request or tenant is cheap:limiter.prefix(`tenant:${id}:`).Changes
prefix()onRedisPublisherandBunRedisPublisherreuse the original subscriber connection and add no extraerrorlistener to it, so creating one per request doesn't leak.prefix()call.Notes
prefixfield ofBaseRedisLocker,BaseRedisRateLimiter, andBaseRedisPublisheris nowkeyPrefix/eventPrefix, to make room for the method. Only custom subclasses that read it are affected.Testing