docs(oes): Egil.Orleans.Messaging API design & project scaffold#33
Draft
egil wants to merge 15 commits into
Draft
docs(oes): Egil.Orleans.Messaging API design & project scaffold#33egil wants to merge 15 commits into
egil wants to merge 15 commits into
Conversation
Comprehensive API design document covering all 8 design sections: - §0: Scope, packaging (one NuGet, split-ready), name settled as Egil.Orleans.Messaging - §1: IStateManager<T> atomic writes with in-flight recovery - §2: Outbox<T> storage placement (co-located on grain state) - §3: Outbox<T> sealed class shape, epoch semantics, fingerprint equality, configurable max depth - §3a: VersionedState<TSelf> for ImmutableArray equality trap - §4: MessageTracker sealed class, dual-dictionary dedup - §5: StreamManager fluent builder facade - §6: Opinionated functional-grain pattern (guidance, not enforced) - §7: OutboxProcessor<T> grain-scoped timer+reminder dispatch with callback-based postmen, per-attempt error tracking - §8: Naming (flat namespace), serialization ([Alias] with fully qualified prefix, sequential [Id]), telemetry conventions All decisions settled via structured grilling sessions. Directory still named Egil.Orleans.CQRS — rename deferred to project scaffold. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ationale IStateManager<T> keeps its wrapper design — the committed-state fence is the real value, not just recovery logic. Extension methods cannot hide IPersistentState<T>.State from [AlwaysInterleave] read methods. Settled decisions: - AsStateManager() extension method factory on IPersistentState<T> - No DI registration needed for v1 - Future: IStateManagerFactory in DI for provider-specific overrides - Interface + monolithic default StateManager<T>, provider-specific implementations as opt-in separate packages later - Updated §6 to reference committed-state fence for safe interleaved reads Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
InProcessTestCluster for all tests (no mocks). Coverage targets: 100% branch on core types (Outbox, MessageTracker, StateManager, VersionedState, OutboxProcessor), 95% on supporting types. Test grains per behavior: write recovery, outbox drain, dedup, interleaved reads, stuck postman, multi-reminder. Serialization round-trip tests for all [GenerateSerializer] types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
All serializable types get [JsonConverter] attributes — STJ discovers converters automatically, zero user registration needed. Custom JsonConverter<T> for types with private fields (Outbox<T>, MessageTracker, envelopes, tokens). JsonConverterFactory for open generic types. [JsonInclude] for VersionedState.Version (internal set). Newtonsoft.Json not supported — documented as known limitation. Updated §9 test strategy to include STJ round-trip tests alongside Orleans serialization tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Belt-and-suspenders: service-reference fields like TimeProvider _time get [NonSerialized] + [JsonIgnore] in addition to having no [Id]. Prevents accidental serialization across Orleans, STJ, and reflection- based serializers. Custom converters also skip them explicitly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ry detail Restored full content from original design doc: - Custom EH adapter pattern for EnrichedEventHubSequenceToken with code sample showing UseDataAdapter wiring - OpenTelemetry trace correlation: ActivityLinks (not parent chaining), producer stashes traceparent, consumer parses + links - Expanded telemetry section with full metric descriptions including end-to-end lag via EnrichedEventHubSequenceToken Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename directory from Egil.Orleans.CQRS to Egil.Orleans.Messaging. Add solution file, Directory.Packages.props, version.json, global.json, src csproj (library), and test csproj. Package description: toolbox of composable building blocks — not a framework. Pick what you need, leave the rest. [skip notes] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Stub IStateManager<T>, VersionedState, WritePolicy, OutboxSequenceToken, OutboxMessageEnvelope<T>, and StateManagerExtensions with thorough XML documentation covering constraints, threading semantics, recovery behavior, serialization requirements, and usage examples. VersionedState is non-generic only — recovery path uses pattern matching and direct Version comparison, not Equals, so the generic CRTP layer was removed as unnecessary. IStateManager<T> docs include two-tier deep immutability requirement: required with [AlwaysInterleave], strongly recommended without. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Stub all public types and interfaces for Egil.Orleans.Messaging with detailed XML documentation covering behavior, constraints, and usage patterns. Types include: - Outbox<T> — immutable outbox collection with O(1) fingerprint equality - MessageTracker — idempotent stream + outbox dedup with eviction - StreamManager/StreamManagerBuilder — fluent stream subscription facade - StreamCursor — (StreamId, token) wrapper with TryGetEnqueuedTime - OutboxProcessor<T> — timer/reminder-driven outbox dispatch - OutboxProcessorOptions<T> — callback-based postman registration - IOutboxGrain — marker interface with IRemindable DIM - EnrichedEventHubSequenceToken — EventHubSequenceTokenV2 + EnqueuedTime - NoPostmanRegisteredException — diagnostic exception for unmatched items - OutboxProcessorExtensions — InitializeOutboxProcessor DI method Also updates api-design.md §3a to reflect removal of the generic VersionedState<TSelf> layer (broken compiler-generated Equals). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add EnrichedEventHubAdapter (public, not sealed) that subclasses EventHubDataAdapter to produce EnrichedEventHubSequenceToken instances carrying broker-side EnqueuedTime and StreamProviderName. - EnrichedEventHubSequenceToken gains StreamProviderName property for provider-aware dedup and edge case handling - UseEnrichedDataAdapter extension on IEventHubStreamConfigurator for one-line registration of the library adapter - StreamCursor gains TryGetStreamProviderName() alongside existing TryGetEnqueuedTime() - Adapter is public/unsealed for users needing custom stream adapters; they register via UseDataAdapter directly Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add internal implementation stubs: - StateManager<T>: core IStateManager<T> impl with committed-state fence, version stamping, and write recovery. Thorough XML docs covering recovery matrix and concurrency model. - OutboxJsonConverterFactory: STJ factory for Outbox<T> - OutboxMessageEnvelopeJsonConverterFactory: STJ factory for envelope - MessageTrackerJsonConverter: STJ converter for MessageTracker - OutboxSequenceTokenJsonConverter: STJ converter for OutboxSequenceToken - StreamCursorJsonConverter: STJ converter for StreamCursor with polymorphic token support All converters registered via [JsonConverter] attribute on their respective public types (attributes still commented out — converters not yet implemented). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
aacdc53 to
2e10b28
Compare
Implement Outbox<T> mutation and O(1) equality behavior according to the design contract. Add behavior tests covering sequence assignment, FIFO removal, metadata preservation, and sequence-window equality. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.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.
Egil.Orleans.Messaging — API Design & Project Scaffold
A toolbox of composable building blocks for Orleans grains that need atomic state writes, transactional outbox, receiver-side dedup, and stream subscription management. Pick what you need, leave the rest.
What's in this PR
API design document (
api-design.md) — comprehensive design covering all settled decisions:IStateManager<T>— atomic writes with in-flight recovery, committed-state fenceOutbox<T>— sealed class, O(1) fingerprint equality, epoch semanticsVersionedState<TSelf>— version-based equality immune toImmutableArraytrapsMessageTracker— receiver-side dedup for streams + outboxStreamManager— fluent subscribe/resume/error facade, EH adapter, OTel trace correlationOutboxProcessor<T>— timer + reminder driven dispatch with postmenProject scaffold — solution, csproj files, Directory.Packages.props, version.json, global.json.
Status
Design document for review. Public type stubs (with XML doc comments) coming next as a sanity check before implementation.