Architecture¶
Metering is a Layer 3 host on the Base Template layering (template layering and reuse). Layer suffixes are described in solution structure.
Service contracts¶
| Contract | gRPC adapter | REST |
|---|---|---|
IUsageMeterManagementService |
GrpcUsageMeterManagementService |
UsageMetersController @ api/usage-meters |
IUsageMeterQueryService |
GrpcUsageMeterQueryService |
same controller |
REST routes (POST, command/query style): queries/by-tenant-dimension, queries/by-id, commands/record-usage, commands/roll-counter, commands/ensure-provisioned, commands/apply-quota. Management operations: RecordUsageAsync, RollCounterAsync, EnsureProvisionedAsync, ApplyQuotaAsync.
Messaging (publish + consume)¶
Publishes four events (metering.usage.v1.*, metering.counters.v1.*, metering.quota.v1.*) and consumes three inbound topics via sagas (tenant activation, subscription created, entitlements changed). Sagas are registered in MassTransitExtensions.cs with in-memory repositories. One additional saga (UsageMeterQuotaEnforcementStateMachine) exists but its inbound topic is not wired (see features).
Persistence (single table)¶
NHibernate + Fluent mapping on UsageMeterEntityMap; schema ConnectSoft.Saas.Metering; single table UsageMeters with unique index UQ_UsageMeters_Tenant_Dimension on (TenantId, Dimension). Shipped dialect SQL Server; connection string ConnectSoft.Saas.Metering. MicroserviceMigration seeds one row via SampleMeteringSeed. Multitenancy via shared SaasTenantFilter (tenantId). Repository: IUsageMetersRepository / UsageMetersRepository (+ keyed variant).
Concurrency¶
UsageMeterGrain keyed {tenantId}:{dimension} serializes increments per meter.