Repository navigation
fix(trogonstack-nats): clarify Core NATS and JetStream channels #115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+841
−329
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
686c755
fix(trogonstack-nats): clarify Core NATS and JetStream channels
yordis 38ef142
fix(trogonstack-nats): validate tagged AsyncAPI channels
yordis 82585c1
fix(trogonstack-nats): use list-valued subject examples
yordis f771f51
feat(trogonstack-nats): document NACK-owned JetStream resources
yordis 2c1ab61
fix(trogonstack-nats): correct subject filters and validate the fixture
yordis ec1c61d
docs(trogonstack-nats): restore the plugin README from main
yordis dc42b3b
docs(trogonstack-nats): validate the documented subject filters
yordis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
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
395 changes: 147 additions & 248 deletions
395
plugins/trogonstack-nats/skills/nats-design-subject/SKILL.md
Large diffs are not rendered by default.
Oops, something went wrong.
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
175 changes: 175 additions & 0 deletions
175
plugins/trogonstack-nats/skills/nats-design-subject/references/channel-contract.md
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,175 @@ | ||
| # NATS Channel Contracts | ||
|
|
||
| A NATS subject is a routing key. Core NATS and JetStream determine how the message is delivered and whether it is stored. Keep those decisions in one channel contract. | ||
|
|
||
| JetStream does not require a separate application subject namespace. A stream captures ordinary subjects. `$JS` subjects are the JetStream control plane and must remain separate from application channels. | ||
|
|
||
| Use [AsyncAPI 3.0](https://www.asyncapi.com/docs/reference/specification/v3.0.0) with the small [channel fragments](gateway-asyncapi-fragments.yaml) to describe application behavior. Its `send` and `receive` operations belong to the application that owns the document. Use [NACK JetStream resources](nack-jetstream.yaml) for Kubernetes-owned streams and optional consumers. Do not put a downstream consumer into a loosely coupled producer contract. A reader can publish its own receive-side contract and own a JetStream consumer separately. | ||
|
|
||
| The NATS-specific examples below use list-valued `subjects`, `request_subjects`, and `reply_subjects` fields, even when one value is present. AsyncAPI keeps its singular `address` field, and JetStream examples keep exact server fields such as `filter_subject`. | ||
|
|
||
| | Concern | Core NATS | JetStream | | ||
| | --- | --- | --- | | ||
| | Delivery | Live publish-subscribe or request-reply | Stream-backed delivery through consumers | | ||
| | Disconnect | A disconnected subscriber misses the message | A durable consumer can resume or replay | | ||
| | Publisher result | Publish has no storage acknowledgement | JetStream publish can return a stream acknowledgement | | ||
| | State | No stream or consumer state | Stream and consumer state must be provisioned and observed | | ||
| | Use | RPC and best-effort live signals | Durable events and work that require replay or retry | | ||
|
|
||
| ## Channel kinds | ||
|
|
||
| ### RPC | ||
|
|
||
| Use Core NATS request-reply when the caller needs one response now: | ||
|
|
||
| ```yaml | ||
| id: gateway.rpc.v1.health | ||
| kind: rpc | ||
| request_subjects: | ||
| - gateway.rpc.v1.health | ||
| reply_subjects: | ||
| - _INBOX.<generated-by-client> | ||
| transport: core | ||
| storage: none | ||
| ``` | ||
|
|
||
| The client creates a unique inbox and sends it as the reply subject. The responder uses that reply subject. A timeout and retry policy are part of the contract. | ||
|
|
||
| ### Live signal | ||
|
|
||
| Use Core NATS publish-subscribe for best-effort notifications: | ||
|
|
||
| ```yaml | ||
| id: gateway.signal.v1.configuration_changed | ||
| kind: live-signal | ||
| subjects: | ||
| - gateway.signal.v1.configuration_changed | ||
| transport: core | ||
| storage: none | ||
| ``` | ||
|
|
||
| A disconnected subscriber misses the message. Do not use this kind for an event that must be replayed. | ||
|
|
||
| ### Durable event | ||
|
|
||
| Use JetStream for a fact that must survive a disconnect or be replayed: | ||
|
|
||
| ```yaml | ||
| id: gateway.ingress.raw.github.v1 | ||
| kind: durable-event | ||
| subjects: | ||
| - gateway.ingress.raw.github.v1.<event> | ||
| transport: jetstream | ||
| stream: GITHUB_PRIMARY | ||
| retention: 7d | ||
| ack: explicit | ||
| ``` | ||
|
|
||
| Core subscribers may observe the same published subject for low-latency reactions. Durable consumers remain the correctness path. | ||
|
|
||
| The publisher must choose its acknowledgement requirement explicitly. A Core publish to a subject captured by a stream does not tell the publisher that storage completed. A JetStream publish acknowledgement is the appropriate contract when the publisher needs that proof. | ||
|
|
||
| Use the same shape for a second ingress source when it has a separate ownership or retention policy: | ||
|
|
||
| ```yaml | ||
| id: gateway.ingress.slack.v1 | ||
| kind: durable-event | ||
| subjects: | ||
| - gateway.ingress.raw.slack.v1.<event> | ||
| transport: jetstream | ||
| stream: SLACK_PRIMARY | ||
| retention: 7d | ||
| ack: explicit | ||
| ``` | ||
|
|
||
| ### Durable work | ||
|
|
||
| Use a JetStream work-queue stream and add a durable consumer only when worker instances need shared, retryable work: | ||
|
|
||
| ```yaml | ||
| id: gateway.work.v1.installation_sync | ||
| kind: durable-work | ||
| subjects: | ||
| - gateway.work.v1.installation_sync | ||
| transport: jetstream | ||
| stream: GATEWAY_WORK | ||
| retention: workqueue | ||
| consumer: installation-sync | ||
| ack: explicit | ||
| ``` | ||
|
|
||
| Set redelivery, backoff, maximum attempts, and dead-letter behavior as part of the work contract. | ||
|
|
||
| The `consumer` field belongs to the worker's receive-side contract. Omit it from a publisher-only event contract. | ||
|
|
||
| ## Gateway example | ||
|
|
||
| ```text | ||
| gateway.ingress.raw.github.v1.pull_request | ||
| gateway.ingress.raw.slack.v1.event_callback | ||
| gateway.events.v1.conversation.message | ||
| gateway.rpc.v1.health | ||
| gateway.work.v1.installation_sync | ||
| ``` | ||
|
|
||
| The GitHub and Slack ingress streams can remain separate when their retention, permissions, or consumers differ. A stream may exist before a reader is deployed. The important rule is that request subjects do not sit under the ingress event wildcard. | ||
|
|
||
| The `nats-subjects` tag marks the examples that the bundled validator reads. The `yaml` language tag keeps the fixture readable as a small data document. Narrative examples use ordinary fences and are not treated as machine-readable contracts. | ||
|
|
||
| ```yaml nats-subjects | ||
| - kind: publish | ||
| subjects: | ||
| - gateway.ingress.raw.github.v1.pull_request | ||
| - kind: subscribe | ||
| subjects: | ||
| - gateway.ingress.raw.github.v1.> | ||
| - kind: stream | ||
| subjects: | ||
| - gateway.ingress.raw.github.v1.> | ||
| # This validates an optional reader filter. It does not provision a consumer. | ||
| - kind: consumer | ||
| subjects: | ||
| - gateway.ingress.raw.github.v1.pull_request | ||
| - kind: publish | ||
| subjects: | ||
| - gateway.ingress.raw.slack.v1.event_callback | ||
| - kind: subscribe | ||
| subjects: | ||
| - gateway.ingress.raw.slack.v1.> | ||
| - kind: publish | ||
| subjects: | ||
| - gateway.rpc.v1.health | ||
| - kind: deliver | ||
| subjects: | ||
| - _INBOX.generated | ||
| ``` | ||
|
|
||
| ## Ownership | ||
|
|
||
| Declare one owner for each stream and consumer. In Kubernetes, NACK owns the JetStream resources: | ||
|
|
||
| ```yaml | ||
| owner: gitops | ||
| provisioner: nack | ||
| publisher: trogon-gateway | ||
| ``` | ||
|
|
||
| The application can validate that a required stream exists. It should not silently create a second definition that competes with NACK. Apply mTLS connection settings to NACK through its Helm values and Kubernetes Secrets, not through application startup code. | ||
|
|
||
| ## Management readback | ||
|
|
||
| Management should expose the same descriptor with desired and observed state. Consumer fields are optional and appear only when a reader owns one: | ||
|
|
||
| ```text | ||
| channel: gateway.ingress.raw.github.v1 | ||
| subjects: | ||
| - gateway.ingress.raw.github.v1.> | ||
| transport: jetstream | ||
| stream: GITHUB_PRIMARY | ||
| stream_state: ready | ||
| consumers: optional, owned by readers | ||
| backlog: 0 | ||
| owner: gitops | ||
| ``` | ||
|
|
||
| Core channels omit stream fields and instead expose responder, queue group, timeout, and authorization status. |
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.