Skip to content

Commit b8fdd47

Browse files
NinjaRocksclaude
andcommitted
Set up SourceFlow.Cloud.Azure for release (mirror AWS package metadata)
Bring the Azure csproj to parity with SourceFlow.Cloud.AWS for NuGet release: - Full package metadata: Title, Authors/Company (CodeShayk), Description, Copyright, RepositoryUrl/Type, PackageProjectUrl, tags, release notes, AssemblyVersion/FileVersion, EnableNETAnalyzers, GeneratePackageOnBuild. - Pack icon (event-icon.png), LICENSE, and a new packaged readme docs/SourceFlow.Cloud.Azure-README.md. - Multi-target net8.0;net9.0;net10.0 (netstandard2.1 omitted: AesGcm used by AzureKeyVaultMessageEncryption is unavailable there). - Align dependency versions with AWS (Azure SDK 7.18.1/1.12.1; Extensions Hosting/HealthChecks/Caching 9.0.0; Options.ConfigurationExtensions 10.0.0). Verified: builds across all three TFMs, package contains net8/9/10 libs + readme + icon + license, 31 unit tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 3cadbb1 commit b8fdd47

2 files changed

Lines changed: 267 additions & 12 deletions

File tree

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
# SourceFlow.Cloud.Azure
2+
3+
**Azure cloud integration for distributed command and event processing**
4+
5+
[![NuGet](https://img.shields.io/nuget/v/SourceFlow.Cloud.Azure.svg)](https://www.nuget.org/packages/SourceFlow.Cloud.Azure/)
6+
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7+
8+
## Overview
9+
10+
SourceFlow.Cloud.Azure extends the SourceFlow.Net framework with Azure cloud services integration, enabling distributed command and event processing using Azure Service Bus and Azure Key Vault. This package provides production-ready dispatchers, listeners, and configuration for building scalable, cloud-native event-sourced applications. The fluent bus API is identical to the AWS provider — only the backing services change.
11+
12+
**Key Features:**
13+
- 🚀 Azure Service Bus command dispatching with session-based ordering
14+
- 📢 Azure Service Bus topic/subscription event publishing with fan-out
15+
- 🔐 Azure Key Vault envelope encryption for sensitive data
16+
- ⚙️ Fluent bus configuration API
17+
- 🔄 Automatic resource provisioning (queues, topics, subscriptions)
18+
- 📊 Built-in observability and health checks
19+
- 🧪 Service Bus emulator integration for local development
20+
21+
---
22+
23+
## Table of Contents
24+
25+
1. [Installation](#installation)
26+
2. [Quick Start](#quick-start)
27+
3. [Configuration](#configuration)
28+
4. [Azure Services](#azure-services)
29+
5. [Bus Configuration System](#bus-configuration-system)
30+
6. [Message Encryption](#message-encryption)
31+
7. [Idempotency](#idempotency)
32+
8. [Local Development](#local-development)
33+
9. [Monitoring](#monitoring)
34+
10. [Best Practices](#best-practices)
35+
36+
---
37+
38+
## Installation
39+
40+
### NuGet Package
41+
42+
```bash
43+
dotnet add package SourceFlow.Cloud.Azure
44+
```
45+
46+
### Prerequisites
47+
48+
- SourceFlow >= 2.0.0
49+
- Azure SDK for .NET (Service Bus, Identity, Key Vault)
50+
- .NET 8.0, .NET 9.0, or .NET 10.0
51+
52+
---
53+
54+
## Quick Start
55+
56+
```csharp
57+
using SourceFlow.Cloud.Azure;
58+
59+
// Register SourceFlow core
60+
services.UseSourceFlow(typeof(Program).Assembly);
61+
62+
// Configure Azure cloud messaging
63+
services.UseSourceFlowAzure(
64+
options =>
65+
{
66+
options.ServiceBusConnectionString = configuration["Azure:ServiceBus:ConnectionString"];
67+
},
68+
bus => bus
69+
.Send
70+
.Command<CreateOrderCommand>(q => q.Queue("orders"))
71+
.Command<ProcessPaymentCommand>(q => q.Queue("payments"))
72+
.Raise
73+
.Event<OrderCreatedEvent>(t => t.Topic("order-events"))
74+
.Event<PaymentProcessedEvent>(t => t.Topic("payment-events"))
75+
.Listen.To
76+
.CommandQueue("orders")
77+
.CommandQueue("payments")
78+
.Subscribe.To
79+
.Topic("order-events")
80+
.Topic("payment-events"));
81+
```
82+
83+
This registers Azure dispatchers, configures routing, starts Service Bus listeners, and automatically provisions queues/topics/subscriptions at startup.
84+
85+
### Passwordless authentication
86+
87+
Instead of a connection string, set `SourceFlow:Azure:ServiceBus:FullyQualifiedNamespace`
88+
(e.g. `myns.servicebus.windows.net`) to authenticate with `DefaultAzureCredential`
89+
(Managed Identity, Azure CLI, Visual Studio, etc.).
90+
91+
---
92+
93+
## Configuration
94+
95+
Connection settings are read from configuration when not supplied via options:
96+
97+
| Key | Description |
98+
| --- | --- |
99+
| `SourceFlow:Azure:ServiceBus:ConnectionString` | Service Bus connection string |
100+
| `SourceFlow:Azure:ServiceBus:FullyQualifiedNamespace` | Namespace for Managed Identity auth |
101+
102+
| Option | Type | Default | Description |
103+
| --- | --- | --- | --- |
104+
| `ServiceBusConnectionString` | string | null | Service Bus connection string |
105+
| `EnableCommandRouting` | bool | true | Enable command dispatching to queues |
106+
| `EnableEventRouting` | bool | true | Enable event publishing to topics |
107+
| `EnableCommandListener` | bool | true | Enable queue command processors |
108+
| `EnableEventListener` | bool | true | Enable topic subscription processors |
109+
110+
---
111+
112+
## Azure Services
113+
114+
- **Azure Service Bus queues** — command dispatching with `SessionId` (entity id) for
115+
strict FIFO ordering per entity, optional duplicate detection, and dead-letter queues.
116+
- **Azure Service Bus topics/subscriptions** — event publishing with fan-out to multiple
117+
subscriptions; subscriptions forward to the listening command queue.
118+
- **Azure Key Vault** — envelope encryption keys for message payload protection.
119+
120+
---
121+
122+
## Bus Configuration System
123+
124+
The fluent `BusConfigurationBuilder` is shared with the rest of SourceFlow.Net:
125+
126+
```csharp
127+
bus => bus
128+
.Send.Command<CreateOrderCommand>(q => q.Queue("orders"))
129+
.Raise.Event<OrderCreatedEvent>(t => t.Topic("order-events"))
130+
.Listen.To.CommandQueue("orders")
131+
.Subscribe.To.Topic("order-events");
132+
```
133+
134+
---
135+
136+
## Message Encryption
137+
138+
Enable envelope encryption for sensitive message payloads backed by Azure Key Vault:
139+
140+
```csharp
141+
services.AddSingleton<IMessageEncryption>(sp =>
142+
new AzureKeyVaultMessageEncryption(
143+
keyVaultUrl: "https://my-vault.vault.azure.net/",
144+
keyName: "sourceflow-key",
145+
credential: new DefaultAzureCredential()));
146+
147+
services.UseSourceFlowAzure(options => ..., bus => ...);
148+
```
149+
150+
**Encryption flow:** Generate data key → Encrypt message with AES-GCM (data key) →
151+
Wrap data key with the Key Vault master key → Store in the Service Bus message.
152+
153+
---
154+
155+
## Idempotency
156+
157+
- **In-memory (single instance)** — registered by default as a singleton with a background
158+
cleanup service. Suitable for single-instance deployments.
159+
- **SQL-based (multi-instance / production)** — install `SourceFlow.Stores.EntityFramework`
160+
and call `services.AddSourceFlowIdempotency(connectionString, cleanupIntervalMinutes)`
161+
before `UseSourceFlowAzure(...)`.
162+
163+
> ⚠️ Always use SQL-based idempotency for multi-instance deployments — the in-memory store
164+
> lives in a single process and is insufficient for distributed systems.
165+
166+
---
167+
168+
## Local Development
169+
170+
Azurite emulates Blob/Queue/Table storage but **not** Service Bus. For local development and
171+
CI, use the official Azure Service Bus emulator (backed by SQL Edge), declaring your entities
172+
up front in its `Config.json`:
173+
174+
```bash
175+
docker compose -f .github/azure-emulator/docker-compose.yml up -d
176+
177+
export AZURE_SERVICEBUS_CONNECTION_STRING="Endpoint=sb://localhost;\
178+
SharedAccessKeyName=RootManageSharedAccessKey;\
179+
SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true"
180+
```
181+
182+
The emulator serves only entities declared in `Config.json` (no runtime creation) and caps
183+
total queues + topics at 50.
184+
185+
---
186+
187+
## Monitoring
188+
189+
- **Activity Source:** `SourceFlow.Cloud.Azure`
190+
- **Health check:** registered automatically as `azure-servicebus` (tags: `azure`,
191+
`servicebus`, `messaging`), covering namespace connectivity, queue/topic existence, and
192+
Key Vault access when encryption is enabled.
193+
- Trace context is propagated via the Service Bus message `ApplicationProperties`
194+
(`traceparent`) for end-to-end distributed tracing.
195+
196+
---
197+
198+
## Best Practices
199+
200+
- Use sessions for ordered operations (the dispatcher sets `SessionId` = entity id).
201+
- Enable duplicate detection on queues fed by at-least-once producers.
202+
- Group related commands to the same queue (`CreateOrder`, `UpdateOrder`, `CancelOrder``orders`).
203+
- Enable SQL-based idempotency in production.
204+
- Prefer Managed Identity (`FullyQualifiedNamespace` + RBAC) over connection strings.
205+
- Enable Key Vault encryption for PII, financial, or health data.
206+
- Use IaC (Bicep/Terraform) for production resources; the bootstrapper is for dev convenience.
207+
- Monitor health checks and dead-letter queue depth.
208+
209+
---
210+
211+
## License
212+
213+
MIT — see [LICENSE](LICENSE).
Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,72 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
4+
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
7-
<AssemblyTitle>Azure Cloud Extension for SourceFlow.Net</AssemblyTitle>
8-
<AssemblyDescription>Provides Azure Service Bus integration for cloud-based message processing</AssemblyDescription>
9-
<PackageId>SourceFlow.Cloud.Azure</PackageId>
7+
<LangVersion>latest</LangVersion>
108
<Version>2.0.0</Version>
11-
<Authors>BuildwAI Team</Authors>
12-
<Company>BuildwAI</Company>
9+
<AssemblyVersion>2.0.0</AssemblyVersion>
10+
<FileVersion>2.0.0</FileVersion>
11+
<RepositoryUrl>https://github.com/CodeShayk/SourceFlow.Net</RepositoryUrl>
12+
<RepositoryType>git</RepositoryType>
13+
<PackageProjectUrl>https://github.com/CodeShayk/SourceFlow.Net/wiki</PackageProjectUrl>
14+
<Authors>CodeShayk</Authors>
15+
<Company>CodeShayk</Company>
1316
<Product>SourceFlow.Net</Product>
17+
<Title>SourceFlow.Cloud.Azure</Title>
18+
<PackageId>SourceFlow.Cloud.Azure</PackageId>
19+
<AssemblyTitle>Azure Cloud Extension for SourceFlow.Net</AssemblyTitle>
20+
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
21+
<Description>Azure cloud provider for SourceFlow.Net. Implements command dispatching via Azure Service Bus queues (with session-based ordering and duplicate detection) and event publishing via Azure Service Bus topics with full subscription management. Features include automatic bus bootstrapping as an IHostedService, Azure Key Vault envelope encryption, dead letter queue processing, batched message operations, circuit breaker and retry policies, health checks for the Service Bus namespace, and OpenTelemetry tracing. Supports .NET 8.0, 9.0, and 10.0.</Description>
22+
<Copyright>Copyright (c) 2026 CodeShayk</Copyright>
23+
<PackageReadmeFile>\docs\SourceFlow.Cloud.Azure-README.md</PackageReadmeFile>
24+
<PackageIcon>event-icon.png</PackageIcon>
25+
<PackageLicenseFile>LICENSE</PackageLicenseFile>
26+
<IncludeSymbols>True</IncludeSymbols>
27+
<PackageReleaseNotes>
28+
v2.0.0 - Major release with production-ready Azure integration.
29+
- Service Bus command dispatching: queues with session-based ordering and duplicate detection.
30+
- Service Bus event publishing: topic creation, subscription management, and fan-out.
31+
- Bus bootstrapper: IHostedService that auto-provisions queues, topics, and subscriptions at startup.
32+
- Security: Azure Key Vault envelope encryption for messages, sensitive data masking in logs.
33+
- Resilience: circuit breaker, configurable retry policies, and throttling protection.
34+
- Dead letter queues: automatic DLQ handling and failed message reprocessing.
35+
- Health checks: IHealthCheck implementation for the Service Bus namespace.
36+
- Observability: OpenTelemetry distributed tracing across command and event flows.
37+
- Breaking change: depends on SourceFlow.Net 2.0.0 (Cloud.Core consolidated into core).
38+
</PackageReleaseNotes>
39+
<PackageTags>SourceFlow;Azure;ServiceBus;KeyVault;Cloud;Messaging;CQRS;Event-Sourcing;Commands;Events;Pub-Sub;Sessions;Dead-Letter-Queue;Circuit-Breaker;Health-Checks</PackageTags>
40+
<EnableNETAnalyzers>True</EnableNETAnalyzers>
1441
</PropertyGroup>
1542

1643
<ItemGroup>
17-
<PackageReference Include="Azure.Messaging.ServiceBus" Version="7.17.0" />
18-
<PackageReference Include="Azure.Identity" Version="1.10.4" />
44+
<PackageReference Include="Azure.Messaging.ServiceBus" Version="7.18.1" />
45+
<PackageReference Include="Azure.Identity" Version="1.12.1" />
1946
<PackageReference Include="Azure.Security.KeyVault.Keys" Version="4.6.0" />
2047
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.0" />
21-
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
22-
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
23-
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="8.0.0" />
48+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
49+
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.0" />
50+
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="9.0.0" />
2451
</ItemGroup>
2552

2653
<ItemGroup>
2754
<ProjectReference Include="..\SourceFlow\SourceFlow.csproj" />
2855
</ItemGroup>
2956

30-
</Project>
57+
<ItemGroup>
58+
<None Include="..\..\Images\event-icon.png">
59+
<Pack>True</Pack>
60+
<PackagePath>\</PackagePath>
61+
</None>
62+
<None Include="..\..\LICENSE">
63+
<Pack>True</Pack>
64+
<PackagePath>\</PackagePath>
65+
</None>
66+
<None Include="..\..\docs\SourceFlow.Cloud.Azure-README.md">
67+
<Pack>True</Pack>
68+
<PackagePath>\docs</PackagePath>
69+
</None>
70+
</ItemGroup>
71+
72+
</Project>

0 commit comments

Comments
 (0)