Development¶
Adding a command¶
- Add an input type in
.DomainModeland a*Validatorin.DomainModel.Impl/Validators. - Add the method to
ISubscriptionsProcessorand implement inDefaultSubscriptionsProcessor(mutate theSubscriptionaggregate, publish events viaIEventBus). - Expose it: add an operation to
ISubscriptionManagementService(ServiceModel), implement in the REST controller and theGrpc*adapter so both adapters stay at parity. - Add unit + acceptance tests.
Reacting to another context¶
Cross-context reactions are sagas, not public endpoints:
- Add an inbound stub in
MessagingModel/Inbound/mapped to the source topic. - Add/extend a state machine in
FlowModel.MassTransit/that calls a reaction hook (ReactTo...Async) on the processor. - Keep handlers idempotent (see resiliency).
Aggregate invariants¶
Billing enforces one aggregate root (ISubscription) - the architecture test will fail if another IAggregateRoot<> appears in EntityModel. Keep invoice/payment as events, not aggregates (docs/out-of-scope.md).
Working with the base template¶
Shared infrastructure lives in the base-template/ submodule. The minimal-host feature matrix (build/DisableMicrosoftExtensionsStackForMinimalHost.BillingHost.props) controls which optional stacks are on (MassTransit, Orleans, NHibernate, Hangfire, Redis, OpenTelemetry) vs off. See template layering and reuse.