@cratis/pi 7.75.0 → 7.76.0
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.
- package/package/corpus/harnesses/copilot/instructions/vertical-slices.instructions.md +6 -4
- package/package/corpus/product-sync.json +14 -14
- package/package/corpus/rules/vertical-slices.md +6 -4
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authorization.md +9 -0
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/observable-emission-guards.md +12 -3
- package/package/corpus/skills/cratis-arc-command/references/decisions-and-routing.md +11 -0
- package/package/corpus/skills/cratis-arc-command-execution/SKILL.md +3 -0
- package/package/corpus/skills/cratis-arc-command-execution/references/occurrence-commands.md +78 -0
- package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +10 -36
- package/package/corpus/skills/cratis-arc-command-validation/references/input-binding.md +49 -0
- package/package/corpus/skills/cratis-arc-command-validation/references/read-model-resolution.md +25 -0
- package/package/corpus/skills/cratis-arc-command-validation/references/validation-severity.md +21 -0
- package/package/corpus/skills/cratis-arc-ef-core-migration/SKILL.md +7 -1
- package/package/corpus/skills/cratis-arc-hosting/SKILL.md +3 -0
- package/package/corpus/skills/cratis-arc-hosting/references/connection-resolution.md +61 -0
- package/package/corpus/skills/cratis-arc-query-paging/SKILL.md +4 -2
- package/package/corpus/skills/cratis-arc-react-page/references/queries-and-commands.md +14 -1
- package/package/corpus/skills/cratis-chronicle-client-dotnet/SKILL.md +5 -0
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/immediate-append-refusal.md +40 -0
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/lifecycle.md +4 -0
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/occurrences.md +89 -0
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/pinned-generation-delivery.md +33 -3
- package/package/corpus/skills/cratis-chronicle-decision-reads/SKILL.md +5 -2
- package/package/corpus/skills/cratis-chronicle-decision-reads/references/admission-and-ownership.md +18 -1
- package/package/corpus/skills/cratis-chronicle-event-type-migration/references/pinned-generations.md +6 -0
- package/package/corpus/skills/cratis-chronicle-hosting/SKILL.md +3 -0
- package/package/corpus/skills/cratis-chronicle-hosting/references/operations.md +26 -0
- package/package/corpus/skills/cratis-chronicle-hosting/references/storage-resolution.md +55 -0
- package/package/corpus/skills/cratis-chronicle-multi-tenancy/SKILL.md +3 -0
- package/package/corpus/skills/cratis-chronicle-multi-tenancy/references/remove-namespace.md +38 -0
- package/package/corpus/skills/cratis-chronicle-projection/references/definition-changes.md +26 -0
- package/package/corpus/skills/cratis-chronicle-projection/references/model-bound-attributes.md +8 -0
- package/package/corpus/skills/cratis-chronicle-reactor/SKILL.md +5 -22
- package/package/corpus/skills/cratis-chronicle-reactor/references/starting-and-replaying.md +33 -0
- package/package/corpus/skills/cratis-chronicle-read-model/SKILL.md +9 -2
- package/package/corpus/skills/cratis-chronicle-read-model/references/queries.md +9 -4
- package/package/corpus/skills/cratis-chronicle-reducer/SKILL.md +4 -0
- package/package/corpus/skills/cratis-multi-service-architecture/SKILL.md +9 -3
- package/package/corpus/skills/cratis-performance-review/SKILL.md +4 -1
- package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +2 -2
- package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/realization-and-gap-fill.md +10 -2
- package/package/corpus/skills/cratis-screenplay-captures-and-reactions/SKILL.md +9 -9
- package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/atomic-batches-and-source-mappings.md +2 -2
- package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +11 -11
- package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-tools.md +9 -0
- package/package/corpus/skills/cratis-screenplay-model-authoring/references/model-notes.md +41 -23
- package/package/corpus/skills/cratis-screenplay-model-authoring/verification.json +8 -3
- package/package/corpus/skills/cratis-screenplay-projections/SKILL.md +19 -12
- package/package/corpus/skills/cratis-screenplay-projections/references/pdl-grammar.md +37 -2
- package/package/corpus/skills/cratis-screenplay-projections/verification.json +11 -0
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +37 -40
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/gap-fill-handoff.md +3 -2
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +1 -1
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/verification.json +4 -2
- package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/coverage-matrix.md +9 -0
- package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +13 -30
- package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +39 -6
- package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +5 -2
- package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +15 -5
- package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +7 -4
- package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +12 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/verification.json +9 -2
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +38 -56
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +23 -13
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/date-comparisons.md +44 -0
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md +8 -2
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/sandbox-and-specrunner.md +59 -8
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/verification.json +7 -3
- package/package.json +1 -1
|
@@ -43,6 +43,18 @@ function**:
|
|
|
43
43
|
The underlying hooks live in `@cratis/arc.react/queries` if you need them
|
|
44
44
|
directly.
|
|
45
45
|
|
|
46
|
+
Requires Arc 22.112.1 for optional-argument changes to refetch snapshot queries
|
|
47
|
+
and for concurrent same-key readers to settle together. Requires Arc 22.113.1
|
|
48
|
+
for cancellation/unmount scope cleanup. Requires Arc 22.116.1 for observable
|
|
49
|
+
page/size/sort changes to resubscribe and for query hooks to stop showing the
|
|
50
|
+
previous key's data or status after arguments, paging or sorting change. Check
|
|
51
|
+
`npm ls @cratis/arc.react`; upgrade older clients rather than relying on these
|
|
52
|
+
state transitions.
|
|
53
|
+
|
|
54
|
+
Each key includes arguments, page, size and sorting. A changed key shows that
|
|
55
|
+
key's cached result, or an initial not-ready result, never the old key's rows.
|
|
56
|
+
Two different pages must not share one request or subscription.
|
|
57
|
+
|
|
46
58
|
### The result object
|
|
47
59
|
|
|
48
60
|
Every query hook returns a result carrying:
|
|
@@ -69,7 +81,8 @@ states separately instead of collapsing them into "loaded or not":
|
|
|
69
81
|
| Converged, empty | `hasData` with an empty `data` and no recent command | the designed empty state |
|
|
70
82
|
| Converged, populated | `hasData` with items | the content |
|
|
71
83
|
| Failed | `!isSuccess` / `hasExceptions` / `!isAuthorized` | the matching error affordance |
|
|
72
|
-
|
|
|
84
|
+
| Same-key refresh | `isPerforming` while `data` still holds that key's previous result | keep that content, indicate refresh |
|
|
85
|
+
| Changed arguments/page/sort | new key's cached result, or initial not-ready state | show only the new key's content or a skeleton |
|
|
73
86
|
|
|
74
87
|
Two consequences. After a create command, take the **window action on the
|
|
75
88
|
command's success** (close the dialog, navigate to the new id) and let the list
|
|
@@ -28,6 +28,11 @@ Source: `Cratis/Chronicle`.
|
|
|
28
28
|
|
|
29
29
|
Take the version from nuget.org, not the placeholder version in the source.
|
|
30
30
|
|
|
31
|
+
Read references/occurrences.md when recording durable triggers, implementing
|
|
32
|
+
occurrence handlers, or choosing startup/shutdown activation and retry semantics.
|
|
33
|
+
Read references/immediate-append-refusal.md when a unit must prevent immediate
|
|
34
|
+
appends from escaping its atomic receipt boundary before transport.
|
|
35
|
+
|
|
31
36
|
## Lifecycle
|
|
32
37
|
|
|
33
38
|
Read [references/lifecycle.md](references/lifecycle.md) when waiting for registration (`WaitForRegistration`, not polling `IsConnected`), diagnosing quiet observers (keepalive loss fails silently, not with an exception), or disposing the client.
|
package/package/corpus/skills/cratis-chronicle-client-dotnet/references/immediate-append-refusal.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<!-- Copyright (c) Cratis. All rights reserved. -->
|
|
2
|
+
<!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
|
|
3
|
+
|
|
4
|
+
# Refuse immediate appends before transport
|
|
5
|
+
|
|
6
|
+
Requires Chronicle 19.81.0. Check with `dotnet list package`; older clients cannot
|
|
7
|
+
prevent an escaped immediate append with this API. Return events or stage them
|
|
8
|
+
transactionally instead; detecting an immediate append after it committed is
|
|
9
|
+
not a retry-safe boundary.
|
|
10
|
+
|
|
11
|
+
`IUnitOfWork.RefuseImmediateAppends()` returns a disposable frame. While its first
|
|
12
|
+
frame is alive, native immediate append entry points in the current flow throw
|
|
13
|
+
before transport, including captured sequence references and references to a
|
|
14
|
+
different store. Transactional appends still enroll in the unit. This does not
|
|
15
|
+
enable read protection or change read admission.
|
|
16
|
+
|
|
17
|
+
## Who completes
|
|
18
|
+
|
|
19
|
+
- With no existing completion owner and no enforced read protection, the first
|
|
20
|
+
frame owns completion. Use that frame's asynchronous `Commit` or `Rollback`.
|
|
21
|
+
- Inside an ASP.NET-owned unit, or an enforcing read-protected unit, the frame is
|
|
22
|
+
refusal-only. Its `Commit` and `Rollback` throw
|
|
23
|
+
`ImmediateAppendRefusalRequiresOwner`; completion stays with the existing owner.
|
|
24
|
+
- Nested frames borrow the refusal scope; they do not acquire completion rights.
|
|
25
|
+
Refusal lasts until the first frame is disposed, even if it already committed.
|
|
26
|
+
- Replacing the ambient unit with `Begin` or `SetCurrent` while the frame lives
|
|
27
|
+
is refused. Dispose the frame at the boundary rather than trying to escape it.
|
|
28
|
+
|
|
29
|
+
This prevents immediate Chronicle writes, not external I/O. Use it around a
|
|
30
|
+
custom unit that must commit atomically with a receipt, and handle the ordinary
|
|
31
|
+
commit result. Do not assume Arc's occurrence executor installs this frame.
|
|
32
|
+
|
|
33
|
+
## Verify
|
|
34
|
+
|
|
35
|
+
In a spec, attempt an immediate append through both the current event log and a
|
|
36
|
+
previously captured reference; assert that neither reaches transport. Assert
|
|
37
|
+
that transactional work commits with its receipt, that an unsupported kernel
|
|
38
|
+
fails closed, and that borrowed frames cannot complete another owner's unit.
|
|
39
|
+
Run `dotnet test` on the owning project. In-process proof is not a substitute for
|
|
40
|
+
integration coverage of the storage provider's transaction boundary.
|
|
@@ -31,6 +31,10 @@ This reference holds registration wiring, the registration wait, keepalive and w
|
|
|
31
31
|
falls more than 5 seconds behind is treated as a lost connection, with
|
|
32
32
|
reconnect backoff capped at 30 seconds. **The failure mode is silence, not an
|
|
33
33
|
exception** — appends keep working while observers go quiet.
|
|
34
|
+
- Requires Chronicle 19.72.1 for reactor/reducer `ClientIsNotConnected` stream
|
|
35
|
+
failures to reconnect the whole client with a fresh connection id and register
|
|
36
|
+
all observers again. Older clients can retry a stale registration indefinitely;
|
|
37
|
+
check `dotnet list package` before diagnosing that as a quiet handler.
|
|
34
38
|
- `Dispose()` disposes read model reactors for created stores, cancels the owned
|
|
35
39
|
connection, and disposes the connection
|
|
36
40
|
(`Source/Clients/DotNET/ChronicleClient.cs`, `Dispose`).
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<!-- Copyright (c) Cratis. All rights reserved. -->
|
|
2
|
+
<!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
|
|
3
|
+
|
|
4
|
+
# Durable application occurrences
|
|
5
|
+
|
|
6
|
+
Requires Chronicle 19.77.0 for the .NET occurrence client and testing surface.
|
|
7
|
+
Check with `dotnet list package`; older clients need an upgrade, not an event
|
|
8
|
+
appended just to wake a reactor. The kernel must advertise `occurrences` and,
|
|
9
|
+
for receipted effects, `effect-receipts`; absent or unknown support fails closed.
|
|
10
|
+
|
|
11
|
+
## Record and handle
|
|
12
|
+
|
|
13
|
+
Occurrences are a durable work queue, not domain events or a compliance store.
|
|
14
|
+
Trigger payloads are plaintext: never put personal data or operational secrets
|
|
15
|
+
in them. Compliance-marked trigger schemas are refused. Keep a stable reference
|
|
16
|
+
and resolve protected information through its owning service instead.
|
|
17
|
+
|
|
18
|
+
```csharp
|
|
19
|
+
using Cratis.Chronicle.Occurrences;
|
|
20
|
+
|
|
21
|
+
[Trigger("refresh-catalog")]
|
|
22
|
+
public record RefreshCatalog(string Catalog);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Implement `IOccurrenceHandler<RefreshCatalog>` with the signature
|
|
26
|
+
`Task Handle(RefreshCatalog trigger, OccurrenceContext context,
|
|
27
|
+
CancellationToken cancellationToken)`. Handlers are discovered like reactors. Record
|
|
28
|
+
with `eventStore.Occurrences.Record(trigger, idempotencyId)` using a stable
|
|
29
|
+
idempotency id. Inspect `Recorded`, `AlreadyRecorded`, `OccurrenceIdConflict`
|
|
30
|
+
and `OccurrencePayloadInvalid`; a reused id with different content is not a
|
|
31
|
+
successful retry.
|
|
32
|
+
|
|
33
|
+
The client claims due work and renews its fenced lease while the handler runs.
|
|
34
|
+
Failure backs off and eventually quarantines that occurrence without blocking
|
|
35
|
+
later work. A stale lease epoch cannot renew, complete or fail another worker's
|
|
36
|
+
lease. Delivery can repeat after a crash: a lease is not exactly-once execution.
|
|
37
|
+
|
|
38
|
+
## Receipt boundary
|
|
39
|
+
|
|
40
|
+
Use `context.EffectKey(effectName)` for one stable effect name within an
|
|
41
|
+
occurrence. `IUnitOfWork.UseEffectReceipt(key, response)` commits the receipt
|
|
42
|
+
atomically with transactional events. Zero-event units can also be receipted;
|
|
43
|
+
protected reads still have to validate. A repeated effect returns its stored
|
|
44
|
+
outcome instead of appending again. Unknown commit results are settled by receipt
|
|
45
|
+
lookup, or fail retryably rather than inventing success.
|
|
46
|
+
|
|
47
|
+
Do not put secrets in a receipt response: it is stored data. An external system
|
|
48
|
+
must accept the effect key as its own idempotency key if its effect must survive
|
|
49
|
+
redelivery. A Chronicle receipt cannot make arbitrary network I/O atomic.
|
|
50
|
+
|
|
51
|
+
Read references/immediate-append-refusal.md when a custom receipt boundary must
|
|
52
|
+
prevent immediate appends before transport. In Arc, use the
|
|
53
|
+
**cratis-arc-command-execution** occurrence executor instead of hand-building the
|
|
54
|
+
command's authorization and receipt boundary.
|
|
55
|
+
|
|
56
|
+
## Startup and shutdown
|
|
57
|
+
|
|
58
|
+
`Startup` and `Shutdown` are built-in triggers. Set `ChronicleOptions.ActivationId`
|
|
59
|
+
to the stable logical deployment activation, not a random id on every restart.
|
|
60
|
+
`ActivationScope.PerProcess` instead selects one activation per process.
|
|
61
|
+
`LifecycleScope.Application` is the default; `AllNamespaces` durably fans out
|
|
62
|
+
over a fixed namespace snapshot, so a crash resumes that fan-out without duplicates.
|
|
63
|
+
|
|
64
|
+
A logical shutdown is recorded by `IOccurrences.EndActivation(id)`; stopping one
|
|
65
|
+
pod is not a logical activation ending. Per-process host shutdown is bounded,
|
|
66
|
+
not guaranteed to run during a kill or crash. ASP.NET Core and generic hosts wire
|
|
67
|
+
the lifecycle service automatically; standalone clients own their lifecycle.
|
|
68
|
+
|
|
69
|
+
## Specify retries explicitly
|
|
70
|
+
|
|
71
|
+
`OccurrenceScenario<THandler>` in `Cratis.Chronicle.Testing.Occurrences` drives
|
|
72
|
+
a handler through in-process ingress, claims, receipts and completion:
|
|
73
|
+
|
|
74
|
+
- `Record(trigger, idempotencyId)` records without delivering.
|
|
75
|
+
- `DeliverNext()` claims and invokes; advancing `Time` alone delivers nothing.
|
|
76
|
+
- `DeliverWithoutCompleting()` simulates loss after work but before acknowledgement.
|
|
77
|
+
- `Replies` can drop a committed append's reply; `Capabilities` on the testing
|
|
78
|
+
store can model current, old or unknown kernel support.
|
|
79
|
+
- Register real constructor dependencies in `Services` before the first operation.
|
|
80
|
+
Assert durable events and receipts as well as the delivery outcome.
|
|
81
|
+
|
|
82
|
+
There are no background workers, automatic lease renewals or reminders in this
|
|
83
|
+
scenario; it does not prove behavior in a real multi-node cluster. Run
|
|
84
|
+
`dotnet test` on the owning spec project and assert duplicate ingress, redelivery,
|
|
85
|
+
terminal refusal, lost reply and unsupported-capability paths.
|
|
86
|
+
|
|
87
|
+
Requires Chronicle 19.78.0 for `Defaults` and `EventStoreForTesting` constructors
|
|
88
|
+
accepting an `EventStoreName` and `EventStoreNamespaceName`. Scenarios built from
|
|
89
|
+
such defaults inherit that identity; old constructors retain `testing`/`default`.
|
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
# Pin event generations before connecting
|
|
5
5
|
|
|
6
|
+
## Contents
|
|
7
|
+
|
|
8
|
+
- Standalone client
|
|
9
|
+
- Host integration
|
|
10
|
+
- Scope and registration
|
|
11
|
+
- Event-store subscription pins
|
|
12
|
+
- Product sources
|
|
13
|
+
|
|
6
14
|
Requires Chronicle **19.41.0+** for client reactors/reducers and **19.48.0+** for
|
|
7
15
|
typed materialized projections. Upgrade every kernel silo before enabling the
|
|
8
16
|
option. `Compatibility` remains the default; adding a generation alone does not
|
|
@@ -72,13 +80,35 @@ builder.AddCratisChronicle(options =>
|
|
|
72
80
|
submitted as both wildcard and `Pinned` is unsupported and rejected by the
|
|
73
81
|
kernel with `EventGenerationDeliveryNotSupported`; the option does not make
|
|
74
82
|
wildcard pinning work.
|
|
75
|
-
- Ad-hoc queries/event reads are not opted in.
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
- Ad-hoc queries/event reads, webhooks and captures are not opted in. Event-store
|
|
84
|
+
subscriptions have their own builder opt-in below; the client-wide setting
|
|
85
|
+
does not enable it.
|
|
78
86
|
|
|
79
87
|
For delivery-time migration, persisted PDL pins, and testing limits, read
|
|
80
88
|
[the migration reference](../../cratis-chronicle-event-type-migration/references/pinned-generations.md).
|
|
81
89
|
|
|
90
|
+
## Event-store subscription pins
|
|
91
|
+
|
|
92
|
+
Requires Chronicle 19.66.0 on client and kernel. Check `dotnet list package`
|
|
93
|
+
and the deployed kernel tag; older builders may throw
|
|
94
|
+
`EventStoreSubscriptionGenerationDeliveryNotSupported`. Compatibility remains
|
|
95
|
+
the default.
|
|
96
|
+
|
|
97
|
+
On `eventStore.Subscriptions.Subscribe(id, sourceStore, configure)`, configure
|
|
98
|
+
`WithGenerationDelivery(EventGenerationDelivery.Pinned)` and either
|
|
99
|
+
`WithEventType<TEvent>()` for that CLR type's declared generation or
|
|
100
|
+
`WithEventType(eventTypeId, generation)` for an explicit pin. This selects the
|
|
101
|
+
generation forwarded into the target inbox during live delivery, catch-up,
|
|
102
|
+
replay and partition retries; it is separate from the inbox observer's own pin.
|
|
103
|
+
|
|
104
|
+
Both stores must register the generation. Registration refuses a missing
|
|
105
|
+
source/target generation or two generations of the same identifier. If the
|
|
106
|
+
target loses its pin at forwarding time, the failing batch appends nothing and
|
|
107
|
+
does not advance past the failing event; earlier acknowledged events stay
|
|
108
|
+
acknowledged. Changing only a pin or delivery mode rebinds the subscription in
|
|
109
|
+
place, without an unsubscribe. Verify migration and protected-value release
|
|
110
|
+
through real-client integration, not just a handler fed the desired CLR type.
|
|
111
|
+
|
|
82
112
|
## Product sources
|
|
83
113
|
|
|
84
114
|
Source: `Cratis/Chronicle`:
|
|
@@ -143,8 +143,11 @@ command protection, caching and enrollment; older Arc refuses them.
|
|
|
143
143
|
Enroll the read **before** staging its decision's events through
|
|
144
144
|
`EventLog.Transactional` and let the owning unit of work commit. Inspect
|
|
145
145
|
`IsSuccess`, append errors/constraint violations/concurrency violations and
|
|
146
|
-
`GetDecisionConflicts()
|
|
147
|
-
|
|
146
|
+
`GetDecisionConflicts()`. Requires Chronicle 19.76.0 for the nullable
|
|
147
|
+
`ConflictingEventTypeId` and `ConflictingEventSequenceNumber` on decision conflicts
|
|
148
|
+
and concurrency violations. They name the first event matching the failed guard;
|
|
149
|
+
older kernels leave both null. Conflict JSON contains the read-model identifier,
|
|
150
|
+
not its CLR type. Check with `dotnet list package` before asserting these fields. On a kernel whose append validators accept an empty batch
|
|
148
151
|
(a kernel that does so when a scope carries an actual boundary or expects no matching event), a checked empty
|
|
149
152
|
append validates its scope and writes nothing; a kernel that rejects it surfaces
|
|
150
153
|
`DecisionReadValidateOnlyNotSupported`, which fails closed. Do not mistake "no
|
package/package/corpus/skills/cratis-chronicle-decision-reads/references/admission-and-ownership.md
CHANGED
|
@@ -21,7 +21,7 @@ an adapter for arbitrary read-model storage:
|
|
|
21
21
|
| OpenEndedEventTypes / Derivatives / FromEventProperty | all-events, FromEvery, or event-property routing |
|
|
22
22
|
| NotEventSourceKeyed / KeyConversion | keys not convertible to the admitted raw source key |
|
|
23
23
|
| NoEventTypes / UnsupportedEventTypeId | no finite guarded type set or unsupported encoded type ids |
|
|
24
|
-
| InvalidKey / FoldIncomplete / DefinitionMismatch | runtime key, fold or client/kernel definition disagreement |
|
|
24
|
+
| InvalidKey / FoldIncomplete / DefinitionMissing / DefinitionMismatch | runtime key, fold, missing kernel definition or client/kernel definition disagreement |
|
|
25
25
|
| StreamKeyRequiresStreamScope | stream-keyed model read without a stream scope |
|
|
26
26
|
| StreamScopeNotSupported / AllStreamsNotSupported / StreamKeyRequiresExplicitStreamId | unsupported stream reader or incomplete stream selection |
|
|
27
27
|
|
|
@@ -35,6 +35,12 @@ Do not silently replace a refused decision read with a materialized sink read.
|
|
|
35
35
|
Redesign the decision model as a focused admitted projection only when the
|
|
36
36
|
contract permits it, or surface the missing capability.
|
|
37
37
|
|
|
38
|
+
Requires Chronicle 19.75.0 for `DefinitionMissing` to be distinct from
|
|
39
|
+
`DefinitionMismatch`. Refusals are not cached, a read checks definitions once
|
|
40
|
+
more before refusing, and agreement is invalidated on connect/disconnect. A
|
|
41
|
+
matching definition can therefore recover after restart without restarting the
|
|
42
|
+
application. Check `dotnet list package`; older clients can retain a refusal.
|
|
43
|
+
|
|
38
44
|
## Completion is owned
|
|
39
45
|
|
|
40
46
|
`IUnitOfWork.HasEnrolledDecisionReads` is sticky: it remains true after commit,
|
|
@@ -53,6 +59,17 @@ all late staging. Protected work and owner completion checks remain enforced;
|
|
|
53
59
|
`UnitOfWorkIsCompleting` must not be caught and interpreted as success. An
|
|
54
60
|
in-flight commit cannot be undone by a competing rollback.
|
|
55
61
|
|
|
62
|
+
Requires Chronicle 19.76.0 for `IUnitOfWork.SuspendReadRegions()`: nested hosts
|
|
63
|
+
can suspend inherited regions and restore them by disposing the scope. This is
|
|
64
|
+
not permission to bypass a guarded decision. Arc uses it from 22.113.0;
|
|
65
|
+
read-model injection outside the command decision under `On` is refused unless
|
|
66
|
+
the model is deliberately `[Unprotected("why")]`.
|
|
67
|
+
|
|
68
|
+
Requires Chronicle 19.81.0 for `RefuseImmediateAppends()`, which changes immediate
|
|
69
|
+
write admission, not read admission. Read
|
|
70
|
+
**cratis-chronicle-client-dotnet**'s immediate-append refusal reference before
|
|
71
|
+
claiming completion rights for its returned frame.
|
|
72
|
+
|
|
56
73
|
Keep read, decision, enrollment and completion inside one ambient async context.
|
|
57
74
|
If a commit rejects the read, start a new read/decision attempt rather than
|
|
58
75
|
reusing the stale protected instance or appending its events without the guard.
|
package/package/corpus/skills/cratis-chronicle-event-type-migration/references/pinned-generations.md
CHANGED
|
@@ -51,6 +51,12 @@ client and kernel registration exception names. Changing a reactor/reducer's
|
|
|
51
51
|
pin or delivery mode does not itself trigger replay; request replay when prior
|
|
52
52
|
state needs rebuilding.
|
|
53
53
|
|
|
54
|
+
Requires Chronicle 19.66.0 for generation-pinned event-store subscriptions.
|
|
55
|
+
Their builder opts in separately with `WithGenerationDelivery(Pinned)` and
|
|
56
|
+
explicit or typed event pins; the global observer option does not opt them in.
|
|
57
|
+
Both source and target stores must register the generation. Read the client
|
|
58
|
+
reference above for registration and forwarding failure behavior.
|
|
59
|
+
|
|
54
60
|
## PDL pins are resolved once, when saved
|
|
55
61
|
|
|
56
62
|
For a PDL definition saved with `GenerationDelivery = Pinned`, a bare reference
|
|
@@ -48,6 +48,9 @@ operator/kernel surface, not an application-profile layout rule.
|
|
|
48
48
|
development database ports on loopback only; a host application needing MongoDB
|
|
49
49
|
must be able to reach port 27017. Do not expose unauthenticated MongoDB.
|
|
50
50
|
|
|
51
|
+
Read references/storage-resolution.md when choosing per-namespace destinations,
|
|
52
|
+
separate schema/runtime identities, SQL schemas, or disabling automatic creation.
|
|
53
|
+
|
|
51
54
|
## Supply certificates before starting production
|
|
52
55
|
|
|
53
56
|
Default TLS needs a PFX certificate with a private key:
|
|
@@ -65,6 +65,32 @@ on every silo and resume from the last durable position after a failed window.
|
|
|
65
65
|
Check the kernel version and shutdown logs; neither guarantee makes an interrupted
|
|
66
66
|
external effect exactly once.
|
|
67
67
|
|
|
68
|
+
Requires Chronicle 19.77.4 for an observer replaced by a newer connected client
|
|
69
|
+
to hand over to a still-connected older client when the newer one disconnects.
|
|
70
|
+
The newest registration wins while both are connected; the older handler does
|
|
71
|
+
not receive event types only the departed client handled. Check the kernel tag;
|
|
72
|
+
older kernels can leave that observer stopped.
|
|
73
|
+
|
|
74
|
+
### Job acceptance and bounded recovery
|
|
75
|
+
|
|
76
|
+
Requires Chronicle 19.80.0 for `IJobs.Stop` and `IJobs.Resume` to return
|
|
77
|
+
`JobCommandResult` with `Accepted` and a refusal reason. A completed RPC is not
|
|
78
|
+
an accepted operation: inspect the result. `RetryFailedPartitions` retries
|
|
79
|
+
partitions through bounded per-partition jobs without reopening a concluded
|
|
80
|
+
replay. Do not invent a CLI flag for this contract operation.
|
|
81
|
+
|
|
82
|
+
Timed-out job steps retry up to five attempts. Replay work has at most 16
|
|
83
|
+
partition steps active, but projection replay/catch-up still use the single
|
|
84
|
+
ordered step above; do not generalize partition parallelism to projections.
|
|
85
|
+
Running jobs whose steps concluded over two minutes ago are reconciled, and
|
|
86
|
+
replay-complete notifications retry. These recovery paths do not clear quarantine or
|
|
87
|
+
prove historical completeness. Check the kernel/client version before relying
|
|
88
|
+
on acceptance results; older clients do not expose them.
|
|
89
|
+
|
|
90
|
+
Requires Chronicle 19.77.2 for stopped/deactivated catch-up and replay steps to
|
|
91
|
+
drain within the job-step stop timeout and resume from their durable checkpoint.
|
|
92
|
+
This does not make external effects exactly once.
|
|
93
|
+
|
|
68
94
|
### Next-event lookup failures
|
|
69
95
|
|
|
70
96
|
Routing keeps the saved position and defers observation when
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<!-- Copyright (c) Cratis. All rights reserved. -->
|
|
2
|
+
<!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
|
|
3
|
+
|
|
4
|
+
# Resolve kernel storage destinations and identities
|
|
5
|
+
|
|
6
|
+
Requires Chronicle 19.74.0 for storage connection resolution.
|
|
7
|
+
Requires Chronicle 19.74.2 for the kernel startup fix; the first two patches
|
|
8
|
+
of this feature fail startup. Check the deployed image tag before changing configuration. Without resolution, configured storage
|
|
9
|
+
behavior stays unchanged.
|
|
10
|
+
|
|
11
|
+
## Scope and purpose
|
|
12
|
+
|
|
13
|
+
`storage.connectionResolution` uses Arc's connection contract with `Connection`
|
|
14
|
+
then `Identity` slots. Choose `Default`, `Template`, `Http`, or `Custom` for an
|
|
15
|
+
in-process kernel. The HTTP request scope includes `kind`, `eventStore` and
|
|
16
|
+
`namespace`. A resolver may supply connection string, database, schema or
|
|
17
|
+
identity independently. Supply credentials through approved configuration or
|
|
18
|
+
the trusted resolver, never source files or logs.
|
|
19
|
+
|
|
20
|
+
Resolution covers event-store, namespace and read-model databases on SQL and
|
|
21
|
+
MongoDB. A resolved connection string or database is used as given, without
|
|
22
|
+
name derivation or a `DatabaseNames` binding. Moving the resolved destination
|
|
23
|
+
is not a data migration. Existing data, schema and permissions must be prepared
|
|
24
|
+
at the intended location before traffic is moved.
|
|
25
|
+
|
|
26
|
+
The cluster database's location stays on `storage.connectionDetails`; its
|
|
27
|
+
identity can resolve for `Schema` work. Schema creation, migrations, table
|
|
28
|
+
migrations and replay swaps use `Schema`; data access uses `Runtime`. Do not
|
|
29
|
+
assume namespace job storage and cluster storage use the same purpose or scope.
|
|
30
|
+
|
|
31
|
+
## Schema and provisioning
|
|
32
|
+
|
|
33
|
+
`storage.createIfMissing = false` makes a missing database or schema fail with
|
|
34
|
+
`DatabaseDoesNotExist` or `SchemaDoesNotExist` instead of creating it.
|
|
35
|
+
`storage.schema` selects Chronicle's SQL schema. PostgreSQL puts it first on
|
|
36
|
+
the search path; SQL Server requires the database user's default schema to
|
|
37
|
+
match or migration fails with `DefaultSchemaMismatch`. Schema discovery only
|
|
38
|
+
considers that schema, not a same-named table elsewhere in a shared database.
|
|
39
|
+
|
|
40
|
+
## Identity rotation
|
|
41
|
+
|
|
42
|
+
SQL resolves identities each time a connection opens, including refreshed
|
|
43
|
+
passwords or tokens. A failed login drops the cached resolution before retry.
|
|
44
|
+
MongoDB separates clients with different credentials and supports MONGODB-OIDC
|
|
45
|
+
access tokens refreshed through resolution. Password-based MongoDB clients do
|
|
46
|
+
not acquire a new password merely because configuration changes; restart them
|
|
47
|
+
when rotating that credential.
|
|
48
|
+
|
|
49
|
+
## Verify
|
|
50
|
+
|
|
51
|
+
Use the real target provider in integration specs: resolve two namespace
|
|
52
|
+
destinations, verify data isolation, run schema-purpose migration with its own
|
|
53
|
+
identity, and assert missing schema/database failure when creation is disabled.
|
|
54
|
+
Exercise expiry and failed-login invalidation without printing the resolved
|
|
55
|
+
credentials. A healthy process alone does not prove the selected destination.
|
|
@@ -28,6 +28,9 @@ Sources:
|
|
|
28
28
|
|
|
29
29
|
Reverify product sources before claiming support for another version.
|
|
30
30
|
|
|
31
|
+
Read references/remove-namespace.md when removing a tenant: provider-owned data,
|
|
32
|
+
application read models, reminders and reconnect behavior have different boundaries.
|
|
33
|
+
|
|
31
34
|
## The concept
|
|
32
35
|
|
|
33
36
|
| Term | Meaning |
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<!-- Copyright (c) Cratis. All rights reserved. -->
|
|
2
|
+
<!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
|
|
3
|
+
|
|
4
|
+
# Remove a namespace
|
|
5
|
+
|
|
6
|
+
Requires Chronicle 19.73.0 for `IEventStore.RemoveNamespace`.
|
|
7
|
+
Requires Chronicle 19.75.1 for reminder cleanup.
|
|
8
|
+
Requires Chronicle 19.76.1 for concurrent re-subscription recovery.
|
|
9
|
+
Requires client 19.77.1 for forgetting a removed namespace on reconnect. Check
|
|
10
|
+
with `dotnet list package` and the kernel image tag; older pairs can recreate
|
|
11
|
+
an apparently removed namespace.
|
|
12
|
+
|
|
13
|
+
This is destructive tenant removal, not a way to hide a tenant in the UI.
|
|
14
|
+
Before calling it, confirm the named event store and namespace, the authorized
|
|
15
|
+
scope, backups and application-owned storage disposition. Never target the
|
|
16
|
+
default namespace: its removal is refused. Removing an unknown namespace is a
|
|
17
|
+
no-op, and an interrupted removal can be repeated.
|
|
18
|
+
|
|
19
|
+
Removal first stops listing the namespace, unsubscribes and removes its
|
|
20
|
+
observers and their persistent reminders, then drops provider-owned namespace
|
|
21
|
+
storage and forgets the namespace. Forwarding and pattern observers with no
|
|
22
|
+
saved state are included through their reminders. Re-subscriptions already in
|
|
23
|
+
flight are handled by bounded unsubscribe/remove retries.
|
|
24
|
+
|
|
25
|
+
MongoDB drops its namespace database. SQL and in-memory providers retain their
|
|
26
|
+
namespace data; do not claim removal is erasure in those providers. Application
|
|
27
|
+
read-model databases are not dropped: the application owns that data and its
|
|
28
|
+
separately authorized cleanup.
|
|
29
|
+
|
|
30
|
+
On reconnect a non-default store asks whether its namespace still exists. If
|
|
31
|
+
absent, it releases that store instead of re-registering it; if the kernel
|
|
32
|
+
cannot answer, registration follows the older behavior. Explicitly using the
|
|
33
|
+
namespace again can create it anew. Stop or reroute writers when removal must
|
|
34
|
+
remain final.
|
|
35
|
+
|
|
36
|
+
Verify removal with a matching kernel and provider, including restart and
|
|
37
|
+
reconnect, and separately inspect the disposition of application-owned data.
|
|
38
|
+
Do not create or delete a live tenant merely to test this workflow.
|
|
@@ -23,5 +23,31 @@ history. Sources: `Documentation/projections/registration-lifecycle.md`,
|
|
|
23
23
|
`Documentation/concepts/observers.mdx`, `Observation/Jobs/{CatchUpObserver,ReplayObserver}.cs`
|
|
24
24
|
and `Observation/States/Routing.cs` (under `Source/Kernel/Core/`).
|
|
25
25
|
|
|
26
|
+
## Rolling deployment versions
|
|
27
|
+
|
|
28
|
+
Requires Chronicle 19.79.0 on client and kernel for projection registration's
|
|
29
|
+
`ChronicleOptions.SoftwareVersion`. It defaults to the entry assembly's informational version;
|
|
30
|
+
`Cratis:Chronicle:SoftwareVersion` overrides it, and startup warns on `1.0.0`.
|
|
31
|
+
Check `dotnet list package` and the kernel image tag; older kernels ignore it.
|
|
32
|
+
|
|
33
|
+
The kernel compares semantic-version precedence, including prerelease labels.
|
|
34
|
+
An older definition cannot overwrite a newer stored version, and an older
|
|
35
|
+
full-set registration cannot retire newer projections. Equal, missing or
|
|
36
|
+
unparseable versions retain ordinary registration behavior. An intentional
|
|
37
|
+
rollback must give the older code a software version higher than the stored
|
|
38
|
+
one. Changing only software version does not request a replay; definition
|
|
39
|
+
evolution policy still determines that.
|
|
40
|
+
|
|
41
|
+
## Namespace reconciliation
|
|
42
|
+
|
|
43
|
+
Requires Chronicle 19.81.1 for projections and captures to reconcile subscriptions
|
|
44
|
+
in every namespace, including runtime-created namespaces. Explicit ensure waits
|
|
45
|
+
for healthy subscriptions; implicit first-append creation is reconciled within
|
|
46
|
+
a watchdog interval. A broken definition does not block healthy ones or creation.
|
|
47
|
+
A lost subscription is repaired, but reconciliation never lifts quarantine,
|
|
48
|
+
revives a retired observer, or restarts a stopped/deleted capture. A kernel
|
|
49
|
+
restart or a newly added namespace still ends projection quarantine through a
|
|
50
|
+
fresh subscription; do not interpret ordinary watchdog repair as operator clear.
|
|
51
|
+
|
|
26
52
|
Closing a stream does not erase its events or prevent a projection replay.
|
|
27
53
|
Keep the closing fact as history; see **cratis-chronicle-event-constraints**.
|
package/package/corpus/skills/cratis-chronicle-projection/references/model-bound-attributes.md
CHANGED
|
@@ -59,6 +59,14 @@ pair it with `[NotRewindable]`. `[NotProjected]` excludes a query-assembled memb
|
|
|
59
59
|
from AutoMap and CHR0024. Sources: `Projections/ModelBound/NotProjectedAttribute.cs`,
|
|
60
60
|
`Projections/FromEveryBuilder.cs`, and `Documentation/projections/model-bound/`.
|
|
61
61
|
|
|
62
|
+
Requires Chronicle 19.78.1 for `[FromAll]`/`[FromEvery]` properties under
|
|
63
|
+
`[ChildrenFrom<T>]` or `[Nested]` to be declared on the child itself, including
|
|
64
|
+
the event creating it. Parent all-event mappings are not copied into children.
|
|
65
|
+
Older client definitions with root-declared child mappings work only when the
|
|
66
|
+
root has no property with the same name; otherwise the mapping stays on the
|
|
67
|
+
root until the client is upgraded. Check client/kernel versions and replay
|
|
68
|
+
affected projections to rebuild already materialized child values.
|
|
69
|
+
|
|
62
70
|
## Setting values
|
|
63
71
|
|
|
64
72
|
| Attribute | Arity | Parameters | Targets |
|
|
@@ -133,32 +133,15 @@ re-delivers the event as an ordinary observation, and a `[OnceOnly]` handler run
|
|
|
133
133
|
again. Catch-up and crash redelivery are not replay either; every ordinary
|
|
134
134
|
matching event can run, even on the same source. Keep effects idempotent.
|
|
135
135
|
|
|
136
|
-
**A
|
|
137
|
-
`[
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
observer is replaying or behind: a rebuilding model looks like "never processed".
|
|
142
|
-
Decide from the events or a `[Passive]` model, and specify the replaying case.
|
|
136
|
+
**A new reactor catches up history; `[OnceOnly]` does not stop that.**
|
|
137
|
+
Requires Chronicle 19.70.0 for `[StartAtTail]` to start only its first registration
|
|
138
|
+
at the tail; existing positions remain. Upgrade the server first: older kernels
|
|
139
|
+
ignore it. Read references/starting-and-replaying.md when avoiding pre-registration
|
|
140
|
+
side effects or choosing alternate replay behavior.
|
|
143
141
|
|
|
144
142
|
Analyzer **CHR0022** (warning) requires `[OnceOnly]` on a handler that returns
|
|
145
143
|
event side effects, because a replay would otherwise append duplicates.
|
|
146
144
|
|
|
147
|
-
`Cratis.Chronicle.Reactors.ReplayAttribute` (`[Replay]`) is the other half, and
|
|
148
|
-
targets a method only. Mark a **second** handler for the same event type with it
|
|
149
|
-
when replay needs to do something *different* rather than nothing:
|
|
150
|
-
|
|
151
|
-
```csharp
|
|
152
|
-
public Task <MethodName>(<EventName> @event) => <serviceName>.<Operation>(@event.<Property>);
|
|
153
|
-
|
|
154
|
-
[Replay]
|
|
155
|
-
public Task <MethodName>DuringReplay(<EventName> @event) => Task.CompletedTask;
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
With a `[Replay]` handler present, only it runs during replay. Without one, the
|
|
159
|
-
ordinary handler runs during replay as before. An event type handled *only* by a
|
|
160
|
-
`[Replay]` handler is still subscribed to.
|
|
161
|
-
|
|
162
145
|
## Identity and event sequence
|
|
163
146
|
|
|
164
147
|
`Cratis.Chronicle.Reactors.ReactorAttribute` takes two optional arguments:
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<!-- Copyright (c) Cratis. All rights reserved. -->
|
|
2
|
+
<!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
|
|
3
|
+
|
|
4
|
+
# Start at the tail and distinguish replay
|
|
5
|
+
|
|
6
|
+
Requires Chronicle 19.70.0 for `[StartAtTail]` in
|
|
7
|
+
`Cratis.Chronicle.Reactors`. Upgrade the server before the client: an older
|
|
8
|
+
server ignores the field and catches up from the beginning. Check with
|
|
9
|
+
`dotnet list package` and the kernel image tag.
|
|
10
|
+
|
|
11
|
+
Put `[StartAtTail]` on a side-effect reactor that should observe only future
|
|
12
|
+
events. It changes the **first registration**: an observer already holding a
|
|
13
|
+
position keeps it. Leaving the attribute in place is safe, but adding it is not
|
|
14
|
+
a command to fast-forward an existing observer. Specify that historical facts
|
|
15
|
+
cause no effect on first registration.
|
|
16
|
+
|
|
17
|
+
`[OnceOnly]` excludes replay, not initial catch-up, failed-partition recovery
|
|
18
|
+
or crash redelivery. Keep side effects idempotent. A reconciliation sweep must
|
|
19
|
+
not decide from a model that is replaying or behind: rebuilding state can look
|
|
20
|
+
like "never processed". Decide from events or a passive model and cover that case.
|
|
21
|
+
|
|
22
|
+
## Alternate replay behavior
|
|
23
|
+
|
|
24
|
+
`Cratis.Chronicle.Reactors.ReplayAttribute` targets a method. Mark a second
|
|
25
|
+
handler for the same event type when replay must do different work. With that
|
|
26
|
+
handler present only it runs during replay; without one, the ordinary handler
|
|
27
|
+
runs unless excluded by `[OnceOnly]`. An event type handled only by a `[Replay]`
|
|
28
|
+
handler is still subscribed to.
|
|
29
|
+
|
|
30
|
+
Verify first registration, restart with an existing position, replay and
|
|
31
|
+
failed-partition redelivery separately. Assert the external effect count, not
|
|
32
|
+
only that the handler was invoked. Run `dotnet test` on the owning spec project;
|
|
33
|
+
server-first compatibility and durable positions also need kernel integration.
|
|
@@ -215,8 +215,8 @@ current rather than eventually consistent.
|
|
|
215
215
|
**Passive is fresher, not safer.** A materialized read may lag the log; a passive
|
|
216
216
|
read is current when read. Neither captures a position or enrolls a guard, so
|
|
217
217
|
neither makes a rule hold when two requests race. To guard a decision use a decision
|
|
218
|
-
read over
|
|
219
|
-
|
|
218
|
+
read over an admitted projection or unfiltered dependency-free reducer, a
|
|
219
|
+
constraint for uniqueness, or an aggregate;
|
|
220
220
|
see [choosing how a rule holds](../cratis-chronicle-decision-reads/references/choosing-how-a-rule-holds.md).
|
|
221
221
|
|
|
222
222
|
**`IMongoCollection<T>` reads only the sink.** It cannot compute passive state:
|
|
@@ -227,6 +227,13 @@ read-model parameter injection) when you need its computed state. Do not remove
|
|
|
227
227
|
Keep secret-bearing state on the protected access path; project only safe
|
|
228
228
|
metadata into a separate list/search model.
|
|
229
229
|
|
|
230
|
+
Requires Chronicle 19.77.3 for strongly consistent per-key projections to fold
|
|
231
|
+
from the start on every read: passive, stream-scoped, wildcard-key and session
|
|
232
|
+
reads immediately reflect revisions, redactions and joined-subject erasure.
|
|
233
|
+
Earlier warm reads can retain old content. Each read costs O(key history), not
|
|
234
|
+
an incremental suffix; prefer materialization for frequent long-history reads.
|
|
235
|
+
Check the deployed kernel tag before relying on this freshness.
|
|
236
|
+
|
|
230
237
|
The number of passive types is not itself a performance smell. Review event
|
|
231
238
|
history length, invocation frequency, and the consistency/security requirement;
|
|
232
239
|
repeated reconstruction of large histories on a hot path is the concern.
|
|
@@ -32,10 +32,15 @@ Chronicle extensions — Chronicle declares no `Observe` on `IMongoCollection<T>
|
|
|
32
32
|
|
|
33
33
|
## Discovery rules
|
|
34
34
|
|
|
35
|
-
Arc discovers **public static** methods
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
Arc discovers eligible **public and internal static** methods on `[ReadModel]`
|
|
36
|
+
types. Internal visibility is not an endpoint privacy boundary. Keep helpers
|
|
37
|
+
outside the read model, regardless of their visibility. Use
|
|
38
|
+
`[ReadModel(RequireQueryAttribute = true)]` and `[Query]` on intended endpoints
|
|
39
|
+
when the type also has folds (`Create`/`Reduce`); `[Query]` alone does not hide
|
|
40
|
+
siblings. Requires Arc 22.27.1 for exclusion of private, protected, special-name
|
|
41
|
+
and compiler-generated methods; older versions can expose private statics too.
|
|
42
|
+
Check with `dotnet list package`; on older versions move helpers out rather
|
|
43
|
+
than relying on visibility. ARC0026 checks invalid/ambiguous
|
|
39
44
|
query declarations; ARCCHR0019 warns about fold-like statics exposed by convention.
|
|
40
45
|
Requires Arc 22.90.0 for automatic exclusion of methods taking the model itself,
|
|
41
46
|
including `Reduce(event, current)`; `[Query]` cannot force such a method into an
|