@klok-integration/cli 0.7.300 → 0.7.309

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,7 +15,10 @@ it as the source does.
15
15
  | Tenant | An organisation on the platform, and its security boundary; every topic, ODL object and GitLab group belongs to one tenant |
16
16
  | Domain | A business area inside a tenant. `common` is shared by the tenant's domains, `public` is open to anyone |
17
17
  | Route, route id | One Camel route per Java class (except a `KlokRestApi`, one per operation, and a `KlokRuntimeInstanceRoute`, one per instance `<RouteId>#<instanceKey>`). Its id is `<TENANTSHORT><NNN><LEG><seq>_<Description>`, for example `KLK007T1_PublishKlokStandard`; the class name is the id |
18
- | Leg | The letter in a route id: I ingress (onramp, brings data in), P processing, E egress (offramp, delivers data out), A API, S sub route, T timer |
18
+ | Leg | The letter in a route id: I ingress, P processing, E egress, A API, S sub route, T timer |
19
+ | Ingress, egress | An ingress is a route that takes a message from outside the platform onto the broker; an egress takes a message off the broker to the outside. An ingress is an onramp or a channel adapter, an egress an offramp or a channel adapter. As a word for a service (`klok-postmark-ingress`) it says what the service is, never a permission |
20
+ | Onramp, offramp | An onramp is an ingress with mapping: the system's own format (class X) becomes a platform model (class A, B or C) before it reaches the broker. An offramp is an egress that maps a platform model to the receiving system's format at the last moment |
21
+ | Channel adapter | An ingress or egress that only converts the protocol (HTTP to the broker, the broker to SFTP); the payload stays as it was received. Good design when it is motivated, for example receiving with minimal handling so that no call is lost while a later leg maps; a system's format put on the broker without such a reason is an anti-pattern |
19
22
  | Tenant short name | `TENANTSHORT`, three upper case letters that start every solution and route id of a tenant: the first three consonants of the tenant's name (`KLK` for klok, `DGR` for degerfors), decided by the platform |
20
23
  | Solution | The business flow a set of routes implements; its id is the route id's prefix, for example `KLK007`. The id is allocated once, by a merge request in the tenant's `integration-solutions` registry, and never reused; a solution is reserved, active or retired |
21
24
  | Solution document | The `README.md` of a solution in the tenant's `integration-solutions` registry: its services, legs and flows, kept true to what is built |
@@ -12,9 +12,20 @@ documentation or the dependency catalog can give you.
12
12
  possible by hand in GitLab.
13
13
  * Systems talk to the broker, never to each other. Point-to-point calls, a shared database or a shared file system
14
14
  between systems are not a Klok design.
15
- * Transform at the edge. When data from one system is to reach other systems or domains, the ingress transforms
16
- it from the system's format to a class C or B model, and the egress transforms it to the receiving system's
15
+ * Ingress and egress are the routes that take messages from outside onto the broker and off the broker to the
16
+ outside. An ingress is an **onramp** (with mapping: system format X to a platform model A, B or C) or a
17
+ **channel adapter** (protocol conversion only, the payload stays as received); an egress is an offramp or a sink
18
+ channel adapter.
19
+ * Transform at the edge. When data from one system is to reach other systems or domains, the onramp transforms
20
+ it from the system's format to a class C or B model, and the offramp transforms it to the receiving system's
17
21
  format at the last moment. Replacing a system then changes only its own ingress and egress.
22
+ * A channel adapter that puts a system's format on the broker is good design when it is motivated: you receive
23
+ with as little handling as possible so that no call from the system is lost, the message waits safely on the
24
+ topic (it can be processed again, or wait for a receiving system that is down), and a later processing leg or
25
+ egress maps it. The solution document says why, which leg maps, and that no other system or domain reads the X
26
+ topic. Example: Postmark inbound mail in KLK006, received by a channel adapter in `klok-postmark-ingress` so that a support mail never bounces while a product is redeployed. Letting class X onto the broker carelessly and without such a
27
+ reason is an anti-pattern and breaks Klok best practice; ask of every ingress "onramp or channel adapter, and
28
+ why?" (https://docs.klok.dev/klok-integration-strategy-and-tactics/platform-2-0/ingress-and-egress/).
18
29
  * Prefer fact events (the whole object) over notifications (an id only).
19
30
  * Hierarchy: tenant (the security boundary; every topic, ODL object and GitLab group belongs to one), then domain
20
31
  (a business area inside the tenant). Domain `common` is shared by the tenant's domains, `public` is open to
@@ -45,7 +56,8 @@ documentation or the dependency catalog can give you.
45
56
  * out of the platform: `KlokOfframpRoute`, `KlokOfframpRouteSync` (serves requests from the broker),
46
57
  `KlokOfframpRouteWithResult`;
47
58
  * on the broker: `KlokProcessingRoute`, `KlokSchemaUpgradeBridge` / `KlokSchemaDowngradeBridge`;
48
- * protocol only, same payload: `KlokChannelAdapterSourceRoute` / `KlokChannelAdapterSinkRoute`;
59
+ * protocol only, the payload as received (a channel adapter, see the principles): `KlokChannelAdapterSourceRoute`
60
+ / `KlokChannelAdapterSinkRoute`;
49
61
  * APIs: `KlokRestApi` with one `KlokRestApiHandlerRoute` per operation; a SOAP API is a `KlokCustomRoute` with
50
62
  camel-cxf; long-running work is a `KlokAsyncTaskWorkerRoute` behind a 202 with a task reference;
51
63
  * everything else: `KlokCustomRoute`; reusable pieces: `KlokSubRoute`, `KlokEnrichSubRoute`.
@@ -86,7 +86,10 @@ Into the platform:
86
86
  * A webhook sender: `KlokWebhookOnrampRoute`.
87
87
  * The caller needs a full business reply now: `KlokOnrampRouteSync`. Call it coupling and debt, with an aggressive
88
88
  timeout.
89
- * Same payload, protocol only: `KlokChannelAdapterSourceRoute`.
89
+ * Same payload, protocol only: `KlokChannelAdapterSourceRoute`. Either the payload already is the model its readers
90
+ need, or receiving with minimal handling is the point (no call may be lost, the message must wait on the topic
91
+ for a receiver that is down) and a later leg maps. Write the reason in the solution document; a system's format
92
+ let onto the broker without one is the anti-pattern.
90
93
 
91
94
  Out of the platform:
92
95
 
@@ -176,6 +179,13 @@ synchronous bridge, a timeout of about ten seconds, `[TACTICAL]` on the solution
176
179
  the target is down. The strategy-aligned alternative: `KlokOnrampRoute` answering 202 with a task reference, and the
177
180
  front end polling or listening on a websocket. If they keep the bridge, write down the debt and the unwind condition.
178
181
 
182
+ **Postmark inbound mail for five products.** A support mail must not bounce because QuickRace is redeployed or
183
+ down for a day of planned upgrade. Ingress: a channel adapter per account in
184
+ `klok-postmark-ingress` (KLK006): receive the webhook, put the payload on a topic unchanged, answer Postmark once
185
+ the broker has it. An egress per product delivers each message to the right inbox and maps there. The solution
186
+ document names the reason and the mapping leg; no other domain reads the Postmark topic. That is a motivated
187
+ channel adapter, not `[TACTICAL]`.
188
+
179
189
  **"The offramp can just read the CRM database for the e-mail field."** Reject: that couples the offramp to CRM's
180
190
  schema. CRM publishes customer facts; if the e-mail is missing, extend the fact event or add an enricher in
181
191
  processing against a master data API on the platform. No SQL credential crosses a domain boundary.
@@ -30,7 +30,9 @@ Walk it from the top; do not pick a base class from habit.
30
30
  (the egress then owns retries, dead letters and alerts);
31
31
  * a webhook: `KlokWebhookOnrampRoute`;
32
32
  * the caller needs a full business reply now: `KlokOnrampRouteSync`, hard coupling, use rarely;
33
- * the payload already is the model the readers need, protocol only: `KlokChannelAdapterSourceRoute`.
33
+ * protocol only, the payload as received: `KlokChannelAdapterSourceRoute`, when the payload already is the
34
+ model the readers need, or when receiving with minimal handling is the motivated design and a later leg
35
+ maps (see *Channel adapters and APIs*).
34
36
  * Out of the platform:
35
37
  * transform into the target's format: `KlokOfframpRoute`;
36
38
  * same format: `KlokChannelAdapterSinkRoute`;
@@ -175,8 +177,12 @@ its own `retry.*`, `dlq.*` or `failure.*` keys; configure its caller.
175
177
 
176
178
  ## Channel adapters and APIs
177
179
 
178
- A channel adapter is a dumb pipe: the same payload over another protocol, only `fromUri()` and `toUri()`. As soon as
179
- a field is mapped it is an onramp or an offramp.
180
+ A channel adapter only converts the protocol: the same payload over another protocol, only `fromUri()` and
181
+ `toUri()`. As soon as a field is mapped it is an onramp or an offramp. Use a source channel adapter for a system's
182
+ own format only for a reason the solution document states: you must accept every call without losing a message, so
183
+ the route does as little as possible, the message waits on the topic, and a processing leg or the egress maps it
184
+ later (Postmark inbound mail in KLK006). A system's format on the broker without that reason, read by other domains,
185
+ is the anti-pattern the refusals below describe.
180
186
 
181
187
  `KlokRestApi` declares its operations in `get()`, `post()`, `put()` and `delete()`, one `KlokRestApiHandlerRoute`
182
188
  per operation; an operation's route id is `<ApiRouteId>.<verb><path>`. Errors are answered as JSON
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: klok-route
3
- description: Write or change a Camel route on the Klok Quarkus extension 2.0 (onramp, processing, offramp, REST API handler, async task worker, custom route) with the correct naming, topics and topic purpose, configuration, error handling, tests and klok-docs. Use for any change inside a Klok integration project.
3
+ description: Write or change a Camel route on the Klok Quarkus extension 2.0 (onramp, channel adapter, processing, offramp, REST API handler, async task worker, custom route) with the correct naming, topics and topic purpose, configuration, error handling, tests and klok-docs. Use for any change inside a Klok integration project.
4
4
  ---
5
5
 
6
6
  # Writing a Klok route
@@ -13,8 +13,12 @@ motivates.
13
13
 
14
14
  ## Steps
15
15
 
16
- 1. **Pick the pattern.** Ingress from a system: `KlokOnrampRoute<SYS, DOM>`; transformation between datamodels:
17
- `KlokProcessingRoute<IN, OUT>`; egress to a system: `KlokOfframpRoute<DOM, SYS>`; synchronous request/reply:
16
+ 1. **Pick the pattern.** Ingress from a system: an onramp, `KlokOnrampRoute<SYS, DOM>`, which maps; or a channel
17
+ adapter, `KlokChannelAdapterSourceRoute<MODEL>`, which only converts the protocol, when receiving with minimal
18
+ handling is the motivated design and a later leg maps (the solution document says why; a system's own format
19
+ let onto the broker without a reason is an anti-pattern,
20
+ https://docs.klok.dev/klok-integration-strategy-and-tactics/platform-2-0/ingress-and-egress/); transformation
21
+ between datamodels: `KlokProcessingRoute<IN, OUT>`; egress to a system: `KlokOfframpRoute<DOM, SYS>`; synchronous request/reply:
18
22
  the `Sync` variants; REST: `KlokRestApi` plus one `KlokRestApiHandlerRoute` per operation; long running work:
19
23
  `KlokAsyncTaskWorkerRoute<REQ, RES>`; anything else: `KlokCustomRoute`.
20
24
  2. **Name it.** `<TENANTSHORT><NNN><LEG><seq>_<Description>`, one class per route. `<TENANTSHORT><NNN>` is the id of
@@ -45,7 +45,8 @@ shared platform service) in `klok/integration-solutions`.
45
45
  6. **Classify every service** the solution needs: *new project*, *new routes in an existing project*, *reused,
46
46
  slight change*, *reused as is*, *client change*. Name the repository of each.
47
47
  7. **Map the legs.** For every route: id (`<TENANTSHORT><NNN><LEG><seq>_<Description>`, leg and sequence not used
48
- before — `klok solutions check` reports duplicates), project, pattern base class, topics with their purpose,
48
+ before — `klok solutions check` reports duplicates), project, pattern base class (for an ingress: onramp or
49
+ channel adapter, and why — a channel adapter needs its reason and the leg that maps), topics with their purpose,
49
50
  datamodels and their class, task types, configuration keys, and how the legs interact (diagrams in the flows
50
51
  section). Route configuration and details stay in the project's `klok-docs/`; the solution links there.
51
52
  8. **Choose the technology deliberately.**