Skip to content

Release v22.106.0

Choose a tag to compare

@github-actions github-actions released this 15 Oct 20:29
3cd4688

Read protection for commands on Chronicle: a read model a command or its validator takes as a parameter can now guard the command's write, so a decision based on state that changed before the commit writes nothing and asks the caller to submit again. It is off by default and is turned on per assembly or command, with a Measure mode for rolling it out safely.

Added

  • Read protection modes Off, Measure and On, set with [assembly: ReadProtection(...)], [ReadProtection(...)] on a command or the MSBuild property <CratisReadProtection>. ReadProtection:MaximumMode lowers the mode at runtime and logs a warning at startup (#3268)
  • Under On, read-model parameters of Handle() and of a CommandValidator<T> constructor are read fresh from the event log and guard the command's append. If one changed before the commit, nothing from the command is written and the caller gets a 400 saying which read model changed and to submit again (#3268)
  • [Unprotected("why")] marks a read-model parameter, type or method body as context that does not guard the write (#3268)
  • [LookUpBy(nameof(Command.Property))] names the command property that is the key of a read-model parameter when it is not the event source id (#3268)
  • Under On, reads that cannot be protected are refused with a message that says why and what to do instead, including raw collection reads, filtered or constructor-dependent reducers, immediate appends and shared validator instances (#3268)
  • Measure leaves behaviour unchanged and reports which reads On would guard, refuse or find changed, through startup warnings, periodic log summaries and telemetry (#3268)
  • Read models declared with [EventStream<TSource>(stream)] can be plain parameters of a command or validator: Arc reads them from the stream the command's route points to, so a monthly limit is guarded by that month only (#3306)
  • Analyzers ARCCHR0024, ARCCHR0028 and ARCCHR0033 to ARCCHR0038 report reads that cannot be protected, aggregates and reads on the same source, unprotected method bodies, early aggregate commits, unproven exact scopes, read-model streams that are not on the command route and stream guards that widen (#3268) (#3306)
  • A guide to keeping command decisions correct: choosing a mechanism, getting started, adopting with Measure, protected and advisory reads, validators, refusals, how guards are derived, and scenarios from a single entity to per-stream limits and processes (#3268)

Changed

  • new CommandScenario<T>() enables decision reads automatically when the command needs them; UseDecisionReads() is no longer needed (#3276)
  • Commands routed through event source definitions pass their declared routing to Chronicle under On, so the append is checked against the definition's concurrency (#3283)
  • ARCCHR0002, ARCCHR0011, ARCCHR0012 and ARCCHR0013 follow the read-protection rules, and [LookUpBy] lookups are checked against the command a validator belongs to (#3268)
  • Requires Chronicle 19.71.0 or later (#3268)