feat: add coordinatorPlugin with auto-register reply-from + helper decorators#6
Merged
Conversation
…corators
Consumers no longer need a separate `npm i @fastify/reply-from` step plus a
manual `app.register(replyFrom)` and `new Registry(...)` to use the Fastify
helpers. `app.register(coordinatorPlugin, { redis, keyPrefix, ... })` now:
- Registers @fastify/reply-from (idempotently, via hasReplyDecorator check)
- Constructs a Registry from the passed options (or accepts an existing one
via `registry`, in which case the plugin will not close it)
- Decorates the Fastify instance with `coordinator` (renamable via
`decorateAs`), exposing:
- `app.coordinator.registry` (the underlying Registry)
- `app.coordinator.lookupAndProxy(opts)`
- `app.coordinator.lookupLockAndProxy(opts)`
- `app.coordinator.pickAndRegister(opts)`
- `app.coordinator.lookupAndDeregister(opts)`
- `app.coordinator.proxyVia(resolve, opts)`
- Closes the registry on `app.close()` (only when the plugin created it)
The existing standalone helper imports (`lookupAndProxy`, etc.) keep working;
they remain documented as the advanced/manual path.
Also:
- Adds Postgres to docker-compose.yml (host port 15432) so test:deps:up
brings up both Redis and Postgres in one step.
- Updates the storage-db example to register the new coordinatorPlugin
instead of doing reply-from + Registry wiring by hand.
- Updates e2e test defaults to match the new compose ports
(REDIS_URL=:6390, PG_URL=:15432). CI workflow updated accordingly.
- Renames script aliases to test:deps:up / test:deps:down; drops the
now-redundant test:redis:* aliases.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous wait step only checked that /pods returned 200, which happens immediately after the coordinator boots regardless of pod registration. On a slow runner the smoke script could then race ahead and see count=0, returning 503 on the first POST /tenants/<id>. Now we poll until count >= 3. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.
Summary
app.register(coordinatorPlugin, { redis, keyPrefix, strategy })now wires up@fastify/reply-from, constructs theRegistry, and exposes both the registry and the helper route-handler factories onapp.coordinator. The bareimport '@fastify/reply-from'inside the helpers only attaches TypeScript types, so consumers previously had to install and register reply-from separately — a leaky requirement.app.coordinator.lookupAndProxy,lookupLockAndProxy,pickAndRegister,lookupAndDeregister,proxyVia) curry away theregistryargument and remove most of the boilerplate.Motivation
Discovered while wiring
coordinator-demo: withoutapp.register(replyFrom)in the consumer app, the helpers fail at runtime withreply.from is not a function. Documentation mentioned the prereq (README line 187) but the API itself didn't enforce or assist with it. This change removes the leak while keeping the original surface working.What changed
src/plugin.ts— a fastify-plugin-wrapped plugin (name: '@platformatic/coordinator',fastify: '5.x'). Options:RegistryOptions(redis,keyPrefix,strategy,cache,requestTimeout) when no existing registry is passed.registry?: Registry— reuse an existing instance (plugin will not close it).replyFrom?: FastifyReplyFromOptions— forwarded to@fastify/reply-from.decorateAs?: string— defaults tocoordinator.registerReplyFrom?: boolean— opt-out for hosts that already registered it.src/index.tsre-exports the plugin ascoordinatorPluginand the type augmentation addsapp.coordinator: Coordinator.test/plugin.test.tscovers: reply-from registration, decorator wiring, all five helper-as-method paths, existing-registry reuse,decorateAs, opt-out, idempotency.examples/storage-dbswitched to the new plugin; dropped@fastify/reply-fromfrom itsdependencies.docker-compose.ymlgains a Postgres service on host port 15432 (matches CI; avoids the common 5432 clash on dev machines). Renamed scripts totest:deps:up/test:deps:down.test/e2e/storage-db.test.tsdefaults updated to match (REDIS_URL=:6390,PG_URL=:15432). CI workflow updated to map Postgres host port to 15432.Backwards compatibility
lookupAndProxy,lookupLockAndProxy,pickAndRegister,lookupAndDeregister,proxyVia) are unchanged.Registry,Member, strategies,TTLCache,proxyRequestare unchanged.test:redis:up/test:redis:downscript aliases (the docker-compose target is identical totest:deps:up/test:deps:down).Test plan
pnpm test— 73/73 passpnpm test:e2e— 10/10 pass (afterpnpm test:deps:up)pnpm lint— clean🤖 Generated with Claude Code