arolariu.Backend.Domain.Invoices.Brokers.DatabaseBroker
arolariu.Backend.Domain.Invoices
arolariu.Backend.Domain.Invoices.Brokers.DatabaseBroker Namespace
Interfaces
IInvoiceNoSqlBroker Interface
Low-level (broker) persistence contract for invoice and merchant aggregates backed by Azure Cosmos DB (NoSQL).
public interface IInvoiceNoSqlBroker
Derived
↳ InvoiceNoSqlBroker
Remarks
Role (The Standard): A broker is a thin abstraction over an external dependency (Cosmos DB). It exposes primitive CRUD / query operations with minimal translation. It MUST NOT implement domain validation, cross-aggregate orchestration, authorization, business workflow branching, or exception classification beyond direct dependency errors.
Responsibilities:
- Persist (create / upsert) invoice and merchant aggregates.
- Retrieve single or multiple aggregates (optionally partition-scoped for RU efficiency).
- Apply soft delete semantics for invoices (and future merchants) by flagging rather than removing.
Exclusions: No invariant checking, no ownership / tenancy authorization, no retry / circuit breaker policy (to be added via delegating handlers or higher resilience layer), no pagination abstraction, no projection shaping (callers handle filtering / shaping).
Partitioning: Invoices partitioned by UserIdentifier; merchants by ParentCompanyId. Overloads lacking an explicit
partition key perform cross-partition (fan-out) operations and SHOULD be reserved for administrative / analytical scenarios due to higher RU cost.
Soft Delete (Invoices): Implemented via IsSoftDeleted flags on invoice and contained products. Broker read methods return only
non-soft-deleted documents. Bulk hard-deletion is intentionally avoided for audit and recovery concerns (future backlog: retention policy enforcement).
Idempotency:
- Create operations are NOT idempotent (duplicate IDs depend on upstream id assignment strategy).
- Soft-delete operations are idempotent (repeated calls yield same terminal state).
- Read operations are naturally idempotent.
Concurrency: No optimistic concurrency (ETag) handling is implemented yet (backlog: introduce access conditions to prevent lost updates).
Performance Notes: Prefer partition-aware overloads. Cross-partition queries should be monitored (add RU telemetry in higher layers). Upsert patterns may incur additional RU vs targeted replace (evaluate once concurrency tokens introduced).
Thread Safety: Implementations (e.g., EF Core DbContext wrapper) are typically NOT thread-safe; consumers should scope instances per unit-of-work.
Cancellation: All async methods accept an optional CancellationToken to support request abort and timeouts.
Backlog: Pagination / continuation tokens, optimistic concurrency, projection queries (selective field retrieval), bulk operations (transactional batch for co-partitioned items), telemetry hooks, and soft-delete for merchants.
Methods
IInvoiceNoSqlBroker.CreateInvoiceAsync(Invoice, CancellationToken) Method
Persists a new invoice document.
System.Threading.Tasks.ValueTask<arolariu.Backend.Domain.Invoices.DDD.AggregatorRoots.Invoices.Invoice> CreateInvoiceAsync(arolariu.Backend.Domain.Invoices.DDD.AggregatorRoots.Invoices.Invoice invoice, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
invoice Invoice
Fully populated invoice aggregate (identity may be reassigned by upstream factory prior to call).
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask<Invoice>
The persisted invoice including any storage-generated metadata.
Exceptions
System.ArgumentNullException
Thrown if invoice is null.
System.OperationCanceledException
Thrown if the operation is cancelled.
Remarks
Asynchronous I/O-bound single write operation. Assumes the invoice aggregate has been fully validated upstream.
IInvoiceNoSqlBroker.CreateMerchantAsync(Merchant, CancellationToken) Method
Persists a new merchant entity.
System.Threading.Tasks.ValueTask<arolariu.Backend.Domain.Invoices.DDD.Entities.Merchants.Merchant> CreateMerchantAsync(arolariu.Backend.Domain.Invoices.DDD.Entities.Merchants.Merchant merchant, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
merchant Merchant
Merchant entity to persist.
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask<Merchant>
The persisted merchant.
Exceptions
System.ArgumentNullException
Thrown if merchant is null.
System.OperationCanceledException
Thrown if the operation is cancelled.
Remarks
Performs a single write operation. Caller must ensure uniqueness and upstream validation of fields.
IInvoiceNoSqlBroker.DeleteInvoiceAsync(Guid, Nullable<Guid>, CancellationToken) Method
Soft-deletes an invoice by identifier within a known partition.
System.Threading.Tasks.ValueTask DeleteInvoiceAsync(System.Guid invoiceIdentifier, System.Nullable<System.Guid> userIdentifier=null, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
invoiceIdentifier System.Guid
Invoice identity.
userIdentifier System.Nullable<System.Guid>
Partition (owner) identity.
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask
Exceptions
System.OperationCanceledException
Thrown if the operation is cancelled.
Remarks
More efficient than cross-partition delete variant. Marks invoice and contained products as soft-deleted.
IInvoiceNoSqlBroker.DeleteInvoicesAsync(Guid, CancellationToken) Method
Soft-deletes all invoices for a given user partition.
System.Threading.Tasks.ValueTask DeleteInvoicesAsync(System.Guid userIdentifier, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
userIdentifier System.Guid
Partition (owner) identity whose invoices will be soft-deleted.
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask
Exceptions
System.OperationCanceledException
Thrown if the operation is cancelled.
Remarks
Iterates all partition documents; may incur significant RU charges for large partitions.
IInvoiceNoSqlBroker.DeleteMerchantAsync(Guid, Nullable<Guid>, CancellationToken) Method
Soft-deletes (or physically replaces) a merchant by identifier via cross-partition search.
System.Threading.Tasks.ValueTask DeleteMerchantAsync(System.Guid merchantIdentifier, System.Nullable<System.Guid> parentCompanyId=null, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
merchantIdentifier System.Guid
Merchant identity.
parentCompanyId System.Nullable<System.Guid>
The parent company identifier.
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask
Exceptions
System.OperationCanceledException
Thrown if the operation is cancelled.
Remarks
Current implementation performs a greedy query. If soft-delete is later introduced for merchants, implementation should mark a flag rather than remove.
IInvoiceNoSqlBroker.ReadInvoiceAsync(Guid, Nullable<Guid>, CancellationToken) Method
Retrieves a single invoice by identifier using either a single point read or a cross-partition (greedy) lookup.
System.Threading.Tasks.ValueTask<arolariu.Backend.Domain.Invoices.DDD.AggregatorRoots.Invoices.Invoice?> ReadInvoiceAsync(System.Guid invoiceIdentifier, System.Nullable<System.Guid> userIdentifier=null, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
invoiceIdentifier System.Guid
Invoice aggregate identity (GUID).
userIdentifier System.Nullable<System.Guid>
Optional partition key for efficient point read.
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask<Invoice>
The matching invoice or null.
Exceptions
System.OperationCanceledException
Thrown if the operation is cancelled.
Remarks
Performs a non-partition-scoped query (higher RU cost). Use the partition-aware overload when the user / owner identifier is available.
Returns null when not found or soft-deleted.
IInvoiceNoSqlBroker.ReadInvoicesAsync(Guid, CancellationToken) Method
Lists all non soft-deleted invoices for a specific user/partition.
System.Threading.Tasks.ValueTask<System.Collections.Generic.IEnumerable<arolariu.Backend.Domain.Invoices.DDD.AggregatorRoots.Invoices.Invoice>> ReadInvoicesAsync(System.Guid userIdentifier, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
userIdentifier System.Guid
Partition key / owner identity.
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask<System.Collections.Generic.IEnumerable<Invoice>>
An enumerable of invoices (may be empty).
Exceptions
System.OperationCanceledException
Thrown if the operation is cancelled.
IInvoiceNoSqlBroker.ReadMerchantAsync(Guid, Nullable<Guid>, CancellationToken) Method
Retrieves a merchant by identifier via cross-partition (greedy) search.
System.Threading.Tasks.ValueTask<arolariu.Backend.Domain.Invoices.DDD.Entities.Merchants.Merchant?> ReadMerchantAsync(System.Guid merchantIdentifier, System.Nullable<System.Guid> parentCompanyId=null, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
merchantIdentifier System.Guid
Merchant identity.
parentCompanyId System.Nullable<System.Guid>
The parent company identifier.
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask<Merchant>
The merchant or null if not found or soft-deleted (if soft-delete introduced later).
Exceptions
System.OperationCanceledException
Thrown if the operation is cancelled.
Remarks
Use partition-aware read patterns (parent company id) where possible to reduce RU consumption.
IInvoiceNoSqlBroker.ReadMerchantsAsync(Guid, CancellationToken) Method
Lists merchants filtered by parent company partition.
System.Threading.Tasks.ValueTask<System.Collections.Generic.IEnumerable<arolariu.Backend.Domain.Invoices.DDD.Entities.Merchants.Merchant>> ReadMerchantsAsync(System.Guid parentCompanyId, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
parentCompanyId System.Guid
Partition key representing the parent company identifier.
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask<System.Collections.Generic.IEnumerable<Merchant>>
An enumerable of merchants (may be empty).
Exceptions
System.OperationCanceledException
Thrown if the operation is cancelled.
IInvoiceNoSqlBroker.UpdateInvoiceAsync(Invoice, Invoice, CancellationToken) Method
Replaces (upserts) an invoice using current and updated aggregate snapshots.
System.Threading.Tasks.ValueTask<arolariu.Backend.Domain.Invoices.DDD.AggregatorRoots.Invoices.Invoice> UpdateInvoiceAsync(arolariu.Backend.Domain.Invoices.DDD.AggregatorRoots.Invoices.Invoice currentInvoice, arolariu.Backend.Domain.Invoices.DDD.AggregatorRoots.Invoices.Invoice updatedInvoice, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
currentInvoice Invoice
Current persisted invoice snapshot (not validated here).
updatedInvoice Invoice
Updated invoice aggregate snapshot.
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask<Invoice>
The persisted invoice after update.
Exceptions
System.ArgumentNullException
Thrown if currentInvoice or updatedInvoice is null.
System.OperationCanceledException
Thrown if the operation is cancelled.
Remarks
currentInvoice is not modified; only updatedInvoice is persisted. No optimistic concurrency token applied.
IInvoiceNoSqlBroker.UpdateInvoiceAsync(Guid, Invoice, CancellationToken) Method
Replaces (upserts) an invoice by identifier (partition inferred from updatedInvoice).
System.Threading.Tasks.ValueTask<arolariu.Backend.Domain.Invoices.DDD.AggregatorRoots.Invoices.Invoice> UpdateInvoiceAsync(System.Guid invoiceIdentifier, arolariu.Backend.Domain.Invoices.DDD.AggregatorRoots.Invoices.Invoice updatedInvoice, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
invoiceIdentifier System.Guid
Target invoice identity.
updatedInvoice Invoice
Updated invoice aggregate snapshot.
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask<Invoice>
The persisted invoice after update.
Exceptions
System.ArgumentNullException
Thrown if updatedInvoice is null.
System.OperationCanceledException
Thrown if the operation is cancelled.
Remarks
Assumes updatedInvoice carries the correct UserIdentifier. Does not perform concurrency (ETag) checks.
IInvoiceNoSqlBroker.UpdateMerchantAsync(Merchant, Merchant, CancellationToken) Method
Replaces (upserts) a merchant using its current and updated snapshots.
System.Threading.Tasks.ValueTask<arolariu.Backend.Domain.Invoices.DDD.Entities.Merchants.Merchant> UpdateMerchantAsync(arolariu.Backend.Domain.Invoices.DDD.Entities.Merchants.Merchant currentMerchant, arolariu.Backend.Domain.Invoices.DDD.Entities.Merchants.Merchant updatedMerchant, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
currentMerchant Merchant
Current persisted merchant (not modified).
updatedMerchant Merchant
Updated merchant snapshot to persist.
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask<Merchant>
The persisted merchant.
Exceptions
System.ArgumentNullException
Thrown if currentMerchant or updatedMerchant is null.
System.OperationCanceledException
Thrown if the operation is cancelled.
IInvoiceNoSqlBroker.UpdateMerchantAsync(Guid, Merchant, CancellationToken) Method
Replaces (upserts) a merchant by identifier (partition inferred via existing document lookup).
System.Threading.Tasks.ValueTask<arolariu.Backend.Domain.Invoices.DDD.Entities.Merchants.Merchant> UpdateMerchantAsync(System.Guid merchantIdentifier, arolariu.Backend.Domain.Invoices.DDD.Entities.Merchants.Merchant updatedMerchant, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters
merchantIdentifier System.Guid
Merchant identity.
updatedMerchant Merchant
Updated merchant snapshot.
cancellationToken System.Threading.CancellationToken
Optional cancellation token to abort the operation.
Returns
System.Threading.Tasks.ValueTask<Merchant>
The persisted merchant.
Exceptions
System.ArgumentNullException
Thrown if updatedMerchant is null.
System.OperationCanceledException
Thrown if the operation is cancelled.