feat(connections): let the subscriber use a different endpoint from the rest - #170
Merged
Conversation
…he rest The API server holds one Redis connection pair built from one options set, and the two halves have opposite requirements. ioRedis carries the express rate limiter, the response cache that does a GET on every request, and alive()'s ping, which is what /healthc returns 500 on and what both the liveness and readiness probes call. ioRedisSub only ever SUBSCRIBEs. Pointing the subscriber at a remote notification source therefore used to mean pointing the rate limiter, the cache and the liveness probe there too: a blip on that path would fail /healthc on every pod and have the kubelet restart them, and writes against a read-only replica would fail outright. REDIS_SUB_HOST now moves the subscriber alone, with each field falling back to its primary counterpart so a different host is usually the only value needed. Unset, both clients share one endpoint and nothing changes, which is what makes this safe to ship ahead of any deployment that uses it.
There was a problem hiding this comment.
Pull request overview
This PR updates the Redis connection wiring so the Pub/Sub subscriber connection (ioRedisSub) can be configured to use a different Redis endpoint than the primary client (ioRedis), avoiding operational coupling between subscription availability and the API’s rate limiting, caching, and health checking behavior.
Changes:
- Add an optional
subscriberconfiguration toRedisConnectionOptionsand constructioRedis/ioRedisSubfrom separate option sets. - Extend
ConnectionManagerto derive a subscriber-specific endpoint fromREDIS_SUB_*environment variables (with fallbacks to the primary Redis settings). - Add tests validating the default shared-endpoint behavior, subscriber-only endpoint override, and subscriber credential separation.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/connections/redis.ts |
Adds subscriber options and factors client creation to allow a separate subscriber endpoint. |
src/connections/redis.test.ts |
Introduces unit tests covering subscriber endpoint override and credential isolation. |
src/connections/manager.ts |
Reads REDIS_SUB_* env vars and passes a derived subscriber config into RedisConnection. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
socket.io-parser 4.2.6 carries a high-severity decoding flaw and is the only resolved copy here, sitting under the socket.io server that publishes the notification namespaces. Lockfile only. socket.io declares ~4.2.4, which already admits the patched 4.2.7, so no package.json moves and no socket.io bump rides along.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
RedisConnectionbuildsioRedisandioRedisSubfrom one options set, and the two halves have opposite requirements.ioRediscarries the express rate limiter (RedisStoreinsrc/api/server.ts), the response cache that does a GET on every request and a SET on miss (expressRedisCache), andalive()'s ping insrc/connections/manager.ts. That ping is what/healthcreturns 500 on, and/healthcis both the liveness and the readiness probe path in the deployment chart.ioRedisSubonly everSUBSCRIBEs.So moving the subscriber to a different instance meant moving the rate limiter, the response cache and the liveness probe with it. A blip on that path fails
/healthcon every pod and the kubelet restarts them; andINCR,PEXPIREandSETagainst a read-only replica fail outright.The concrete case this unblocks: the notification publisher for each chain runs alongside the filler, on a different Kubernetes cluster from the API servers, so the servers subscribe to an instance the publisher never writes to and receive nothing. Fixing that needs the subscriber to reach across, and specifically needs everything else not to.
What changed
REDIS_SUB_HOSTmoves the subscriber alone. Each field falls back to its primary counterpart (REDIS_SUB_PORTtoREDIS_PORT, and likewise for credentials and connection type), so a different host is usually the only value needed.Unset, both clients share one endpoint and behaviour is unchanged. That is deliberate: tagging this image deploys it to every filler and server whose
allowTagsadmits it, all at once, so the code has to be a no-op on arrival and get enabled per environment by configuration afterwards.Validation
check-typesandlintclean. Suite goes 338 to 341 passing, 37 pending unchanged, matching the three cases added.The new tests were mutation-checked rather than assumed: reverting the split so the subscriber is built from the primary options fails exactly two of them, and the restore is byte-identical. They assert that omitting the field leaves both clients on one endpoint, that configuring it moves only the subscriber, and that subscriber credentials do not leak from the primary.
Also carried: socket.io-parser GHSA-2m8v-j782-fhvr
Folded in on request, as its own commit so the history stays separable.
socket.io-parser@4.2.6carries a high-severity decoding flaw (vulnerable>=4.0.0 <4.2.7) and is the only resolved copy here, sitting under the socket.io server that publishes the notification namespaces this PR is ultimately about.Lockfile only:
socket.io@4.8.3declares~4.2.4, which already admits the patched4.2.7, so nopackage.jsonmoves and no socket.io bump rides along.Diff is 4 lines, all belonging to the
socket.io-parserentry including its integrity hash, which matches the artifact taken in the monorepo change for the same advisory.pnpm install --frozen-lockfilesucceeds against the result, which is what proves the lockfile is consistent rather than merely edited. Suite stays at 341 passing withcheck-typesandlintclean.