Skip to content

Commit 601aac0

Browse files
committed
Updated readme and docs
1 parent c2b7daf commit 601aac0

File tree

5 files changed

+130
-40
lines changed

5 files changed

+130
-40
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ await using var handle = await locker.AcquireAsync("resource-key");
6262
| [Redis](https://github.com/FoundatioFx/Foundatio.Redis) ||||||
6363
| [Azure Storage](https://github.com/FoundatioFx/Foundatio.AzureStorage) | || || |
6464
| [Azure Service Bus](https://github.com/FoundatioFx/Foundatio.AzureServiceBus) | ||| | |
65-
| [AWS (S3/SQS)](https://github.com/FoundatioFx/Foundatio.AWS) | || || |
65+
| [AWS (S3/SQS/SNS)](https://github.com/FoundatioFx/Foundatio.AWS) | || || |
6666
| [RabbitMQ](https://github.com/FoundatioFx/Foundatio.RabbitMQ) | | || | |
6767
| [Kafka](https://github.com/FoundatioFx/Foundatio.Kafka) | | || | |
6868
| [Minio](https://github.com/FoundatioFx/Foundatio.Minio) | | | || |

docs/.vitepress/config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ export default defineConfig({
8080
{ text: 'Foundatio.CommandQuery', link: 'https://github.com/FoundatioFx/Foundatio.CommandQuery' },
8181
{ text: 'Foundatio.Lucene', link: 'https://lucene.foundatio.dev' },
8282
{ text: 'Foundatio.Mediator', link: 'https://mediator.foundatio.dev' },
83-
{ text: 'Foundatio.Parsers', link: 'https://github.com/FoundatioFx/Foundatio.Parsers' },
84-
{ text: 'Foundatio.Repositories', link: 'https://github.com/FoundatioFx/Foundatio.Repositories' }
83+
{ text: 'Foundatio.Parsers', link: 'https://parsers.foundatio.dev' },
84+
{ text: 'Foundatio.Repositories', link: 'https://repositories.foundatio.dev' }
8585
]
8686
}
8787
]

docs/guide/implementations/aws.md

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
# Foundatio.AWS
22

3-
Foundatio provides AWS implementations for file storage and queuing using Amazon S3 and Amazon SQS. [View source on GitHub →](https://github.com/FoundatioFx/Foundatio.AWS)
3+
Foundatio provides AWS implementations for file storage, queuing, and messaging using Amazon S3, Amazon SQS, and Amazon SNS. [View source on GitHub →](https://github.com/FoundatioFx/Foundatio.AWS)
44

55
## Overview
66

77
| Implementation | Interface | Package |
88
|----------------|-----------|---------|
99
| `S3FileStorage` | `IFileStorage` | Foundatio.AWS |
10+
| `SQSMessageBus` | `IMessageBus` | Foundatio.AWS |
1011
| `SQSQueue<T>` | `IQueue<T>` | Foundatio.AWS |
1112

1213
## Installation
@@ -43,9 +44,75 @@ await storage.SaveFileAsync("documents/report.pdf", pdfStream);
4344

4445
For additional options, see [S3FileStorageOptions source](https://github.com/FoundatioFx/Foundatio.AWS/blob/main/src/Foundatio.AWS/Storage/S3FileStorageOptions.cs).
4546

47+
## SQSMessageBus
48+
49+
AWS SNS/SQS message bus for pub/sub messaging using the SNS fan-out pattern.
50+
51+
```csharp
52+
using Foundatio.Messaging;
53+
54+
var messageBus = new SQSMessageBus(o =>
55+
{
56+
o.ConnectionString = connectionString;
57+
o.Topic = "events";
58+
// Optional: Specify queue name for durable subscriptions
59+
// o.SubscriptionQueueName = "my-service-queue";
60+
});
61+
62+
await messageBus.SubscribeAsync<OrderCreated>(async order =>
63+
{
64+
Console.WriteLine($"Order created: {order.OrderId}");
65+
});
66+
67+
await messageBus.PublishAsync(new OrderCreated { OrderId = 123 });
68+
```
69+
70+
### Configuration
71+
72+
| Option | Type | Required | Default | Description |
73+
|--------|------|----------|---------|-------------|
74+
| `Topic` | `string` || | SNS topic name for publishing |
75+
| `ConnectionString` | `string` | | | Connection string |
76+
| `Credentials` | `AWSCredentials` | | | AWS credentials |
77+
| `Region` | `RegionEndpoint` | | | AWS region |
78+
| `ServiceUrl` | `string` | | | Custom endpoint (LocalStack) |
79+
| `CanCreateTopic` | `bool` | | `true` | Auto-create SNS topic if missing |
80+
| `SubscriptionQueueName` | `string` | | Random | SQS queue name (use for durable subscriptions) |
81+
| `SubscriptionQueueAutoDelete` | `bool` | | `true` | Auto-delete queue on dispose (set `false` for durable) |
82+
| `ReadQueueTimeout` | `TimeSpan` | | 20s | Long polling timeout |
83+
| `DequeueInterval` | `TimeSpan` | | 1s | Interval between dequeue attempts |
84+
| `MessageVisibilityTimeout` | `TimeSpan?` | | 30s (SQS) | Message visibility timeout |
85+
| `SqsManagedSseEnabled` | `bool` | | `false` | Enable SQS managed encryption (SSE-SQS) |
86+
| `KmsMasterKeyId` | `string` | | | KMS key ID for encryption (SSE-KMS) |
87+
| `KmsDataKeyReusePeriodSeconds` | `int` | | 300 | KMS key reuse period |
88+
| `TopicResolver` | `Func<Type, string>` | | | Route message types to different topics |
89+
90+
For additional options, see [SQSMessageBusOptions source](https://github.com/FoundatioFx/Foundatio.AWS/blob/main/src/Foundatio.AWS/Messaging/SQSMessageBusOptions.cs).
91+
92+
### Architecture
93+
94+
The `SQSMessageBus` uses the SNS fan-out pattern:
95+
96+
- **Publishing**: Messages are published to an SNS topic
97+
- **Subscribing**: Each subscriber gets its own SQS queue subscribed to the SNS topic
98+
- **Durable Subscriptions**: Use `SubscriptionQueueName` and set `SubscriptionQueueAutoDelete = false` to persist queues across restarts
99+
- **Policy Management**: Queue policies are automatically configured to allow SNS to deliver messages
100+
101+
### Durable Subscriptions Example
102+
103+
```csharp
104+
var messageBus = new SQSMessageBus(o =>
105+
{
106+
o.ConnectionString = connectionString;
107+
o.Topic = "events";
108+
o.SubscriptionQueueName = "order-service-events";
109+
o.SubscriptionQueueAutoDelete = false; // Queue persists across restarts
110+
});
111+
```
112+
46113
## SQSQueue
47114

48-
AWS SQS queue implementation.
115+
AWS SQS queue implementation for reliable work item processing.
49116

50117
```csharp
51118
using Foundatio.Queues;
@@ -77,4 +144,5 @@ For additional options, see [SQSQueueOptions source](https://github.com/Foundati
77144

78145
- [File Storage Guide](/guide/storage) - Usage patterns
79146
- [Queues Guide](/guide/queues) - Queue processing patterns
147+
- [Messaging Guide](/guide/messaging) - Pub/sub patterns and best practices
80148
- [Serialization](/guide/serialization) - Configure serialization

docs/guide/messaging.md

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,37 @@ await messageBus.SubscribeAsync<OrderCreated>(async msg =>
4848
await messageBus.PublishAsync(new OrderCreated { OrderId = 123 });
4949
```
5050

51-
### RedisMessageBus
51+
### AzureServiceBusMessageBus
5252

53-
Distributed messaging using Redis pub/sub (separate package):
53+
Messaging using Azure Service Bus (separate package):
5454

55-
[View source](https://github.com/FoundatioFx/Foundatio.Redis/blob/main/src/Foundatio.Redis/Messaging/RedisMessageBus.cs)
55+
[View source](https://github.com/FoundatioFx/Foundatio.AzureServiceBus/blob/main/src/Foundatio.AzureServiceBus/Messaging/AzureServiceBusMessageBus.cs)
5656

5757
```csharp
58-
// dotnet add package Foundatio.Redis
58+
// dotnet add package Foundatio.AzureServiceBus
5959
60-
using Foundatio.Redis.Messaging;
61-
using StackExchange.Redis;
60+
using Foundatio.AzureServiceBus.Messaging;
6261

63-
var redis = await ConnectionMultiplexer.ConnectAsync("localhost:6379");
64-
var messageBus = new RedisMessageBus(o => o.Subscriber = redis.GetSubscriber());
62+
var messageBus = new AzureServiceBusMessageBus(o => {
63+
o.ConnectionString = "...";
64+
o.Topic = "events";
65+
});
66+
```
67+
68+
### KafkaMessageBus
69+
70+
Messaging using Apache Kafka (separate package):
71+
72+
[View source](https://github.com/FoundatioFx/Foundatio.Kafka/blob/main/src/Foundatio.Kafka/Messaging/KafkaMessageBus.cs)
73+
74+
```csharp
75+
// dotnet add package Foundatio.Kafka
76+
77+
using Foundatio.Kafka.Messaging;
78+
79+
var messageBus = new KafkaMessageBus(o => {
80+
o.BootstrapServers = "localhost:9092";
81+
});
6582
```
6683

6784
### RabbitMQMessageBus
@@ -80,36 +97,38 @@ var messageBus = new RabbitMQMessageBus(o => {
8097
});
8198
```
8299

83-
### KafkaMessageBus
100+
### RedisMessageBus
84101

85-
Messaging using Apache Kafka (separate package):
102+
Distributed messaging using Redis pub/sub (separate package):
86103

87-
[View source](https://github.com/FoundatioFx/Foundatio.Kafka/blob/main/src/Foundatio.Kafka/Messaging/KafkaMessageBus.cs)
104+
[View source](https://github.com/FoundatioFx/Foundatio.Redis/blob/main/src/Foundatio.Redis/Messaging/RedisMessageBus.cs)
88105

89106
```csharp
90-
// dotnet add package Foundatio.Kafka
107+
// dotnet add package Foundatio.Redis
91108
92-
using Foundatio.Kafka.Messaging;
109+
using Foundatio.Redis.Messaging;
110+
using StackExchange.Redis;
93111

94-
var messageBus = new KafkaMessageBus(o => {
95-
o.BootstrapServers = "localhost:9092";
96-
});
112+
var redis = await ConnectionMultiplexer.ConnectAsync("localhost:6379");
113+
var messageBus = new RedisMessageBus(o => o.Subscriber = redis.GetSubscriber());
97114
```
98115

99-
### AzureServiceBusMessageBus
116+
### SQSMessageBus
100117

101-
Messaging using Azure Service Bus (separate package):
118+
Messaging using AWS SNS/SQS (separate package):
102119

103-
[View source](https://github.com/FoundatioFx/Foundatio.AzureServiceBus/blob/main/src/Foundatio.AzureServiceBus/Messaging/AzureServiceBusMessageBus.cs)
120+
[View source](https://github.com/FoundatioFx/Foundatio.AWS/blob/master/src/Foundatio.AWS/Messaging/SQSMessageBus.cs)
104121

105122
```csharp
106-
// dotnet add package Foundatio.AzureServiceBus
123+
// dotnet add package Foundatio.AWS
107124
108-
using Foundatio.AzureServiceBus.Messaging;
125+
using Foundatio.Messaging;
109126

110-
var messageBus = new AzureServiceBusMessageBus(o => {
111-
o.ConnectionString = "...";
127+
var messageBus = new SQSMessageBus(o => {
128+
o.ConnectionString = connectionString;
112129
o.Topic = "events";
130+
// Optional: Specify queue name for durable subscriptions
131+
// o.SubscriptionQueueName = "my-service-queue";
113132
});
114133
```
115134

@@ -461,10 +480,11 @@ Different providers handle delayed delivery differently:
461480
| Provider | Implementation | Persistence | Survives Restart |
462481
|----------|---------------|-------------|------------------|
463482
| **InMemoryMessageBus** | In-memory timer | None | No |
464-
| **RedisMessageBus** | In-memory timer | None | No |
465-
| **RabbitMQMessageBus** | Plugin or fallback | Plugin: Yes, Fallback: No | Plugin: Yes, Fallback: No |
466-
| **KafkaMessageBus** | In-memory timer | None | No |
467483
| **AzureServiceBusMessageBus** | Native `ScheduledEnqueueTime` | Azure | Yes |
484+
| **KafkaMessageBus** | In-memory timer | None | No |
485+
| **RabbitMQMessageBus** | Plugin or fallback | Plugin: Yes, Fallback: No | Plugin: Yes, Fallback: No |
486+
| **RedisMessageBus** | In-memory timer | None | No |
487+
| **SQSMessageBus** | In-memory timer | None | No |
468488

469489
### Native vs Fallback Implementation
470490

@@ -690,10 +710,11 @@ await messageBus.SubscribeAsync<OrderCreated>(async order =>
690710
| Provider | Publish Errors | Subscriber Errors | Redelivery on Failure |
691711
|----------|---------------|-------------------|----------------------|
692712
| **InMemoryMessageBus** | Throws `MessageBusException` | Logged, swallowed | No |
693-
| **RedisMessageBus** | Throws `MessageBusException` | Logged, swallowed | No (pub/sub has no ack) |
694-
| **RabbitMQMessageBus** | Throws `MessageBusException` | Logged, nack/requeue | Yes (`DeliveryLimit`) |
695-
| **KafkaMessageBus** | Fire-and-forget with callback | Logged, offset not committed | Yes (redelivered) |
696713
| **AzureServiceBusMessageBus** | Throws `MessageBusException` | Logged, SDK handles | Yes (`MaxDeliveryCount`) |
714+
| **KafkaMessageBus** | Fire-and-forget with callback | Logged, offset not committed | Yes (redelivered) |
715+
| **RabbitMQMessageBus** | Throws `MessageBusException` | Logged, nack/requeue | Yes (`DeliveryLimit`) |
716+
| **RedisMessageBus** | Throws `MessageBusException` | Logged, swallowed | No (pub/sub has no ack) |
717+
| **SQSMessageBus** | Throws `MessageBusException` | Logged, message not deleted | Yes (redelivered) |
697718

698719
::: tip Logging
699720
All errors are logged at `Error` level. Subscriber errors are logged exactly once by the base class.
@@ -819,10 +840,11 @@ Different message bus implementations have different size limits. Understanding
819840
| Provider | Max Message Size | Notes |
820841
|----------|------------------|-------|
821842
| InMemoryMessageBus | Limited by available memory | No practical limit |
822-
| RedisMessageBus | 512 MB (Redis limit) | Recommended: < 1 MB for performance |
823-
| RabbitMQMessageBus | 128 MB (default) | Configurable, but keep small |
824-
| KafkaMessageBus | 1 MB (default) | Configurable via `message.max.bytes` |
825843
| AzureServiceBusMessageBus | 256 KB (Standard) / 100 MB (Premium) | Use claim check for large payloads |
844+
| KafkaMessageBus | 1 MB (default) | Configurable via `message.max.bytes` |
845+
| RabbitMQMessageBus | 128 MB (default) | Configurable, but keep small |
846+
| RedisMessageBus | 512 MB (Redis limit) | Recommended: < 1 MB for performance |
847+
| SQSMessageBus | 256 KB | Use claim check for large payloads |
826848

827849
### Claim Check Pattern for Large Payloads
828850

docs/index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ When building several large cloud applications we found a lack of great solution
163163
| Provider | Caching | Queues | Messaging | Locks | Storage |
164164
|----------|---------|--------|-----------|-------|---------|
165165
| [Aliyun](./guide/implementations/aliyun) | | | | ||
166-
| [AWS](./guide/implementations/aws) | || | ||
166+
| [AWS](./guide/implementations/aws) | || | ||
167167
| [Azure ServiceBus](./guide/implementations/azure) | ||| | |
168168
| [Azure Storage](./guide/implementations/azure) | || | ||
169169
| [In-Memory](./guide/implementations/in-memory) ||||||
@@ -178,5 +178,5 @@ When building several large cloud applications we found a lack of great solution
178178
- [**Foundatio.CommandQuery**](https://github.com/FoundatioFx/Foundatio.CommandQuery) - CQRS framework with Entity Framework Core and MongoDB support, built on Foundatio.Mediator.
179179
- [**Foundatio.Lucene**](https://lucene.foundatio.dev) - Lucene-style query parser with AST, visitor pattern, Entity Framework Core integration, and Elasticsearch Query DSL generation.
180180
- [**Foundatio.Mediator**](https://mediator.foundatio.dev) - Blazingly fast, convention-based C# mediator powered by source generators and interceptors. Near-direct call performance with zero runtime reflection.
181-
- [**Foundatio.Parsers**](https://github.com/FoundatioFx/Foundatio.Parsers) - Extensible Lucene-style query syntax parser with Elasticsearch integration.
182-
- [**Foundatio.Repositories**](https://github.com/FoundatioFx/Foundatio.Repositories) - Generic repository pattern implementation with Elasticsearch support, caching, and message bus integration.
181+
- [**Foundatio.Parsers**](https://parsers.foundatio.dev) - Extensible Lucene-style query syntax parser with Elasticsearch integration, field aliases, query includes, and validation.
182+
- [**Foundatio.Repositories**](https://repositories.foundatio.dev) - Production-grade repository pattern implementation with Elasticsearch support, caching, messaging, soft deletes, and document versioning.

0 commit comments

Comments
 (0)