Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,18 +309,24 @@ services.AddBrighter()
✅ **V10 — current**

```csharp
services.AddBrighter()
.AddProducers(options =>
services.AddConsumers(options =>
{
options.ProducerRegistry = new RmqProducerRegistryFactory(...).Create();
options.Subscriptions = subscriptions;
options.DefaultChannelFactory = new ChannelFactory(...);
})
.AddConsumers(options =>
.AddProducers(options =>
{
options.Subscriptions = subscriptions;
options.ChannelFactory = new ChannelFactory(...);
options.ProducerRegistry = new RmqProducerRegistryFactory(...).Create();
});
```

**The receiver matters and the compiler is the only thing that says so.** `AddConsumers`
extends `IServiceCollection`; `AddProducers`, `UseScheduler`, `Handlers` and
`AutoFromAssemblies` extend the `IBrighterBuilder` it returns. So a consumer registration comes
**first** and everything else chains off it —
`services.AddBrighter().AddProducers(…).AddConsumers(…)` is **`CS1929`**, and an earlier
version of this example had it. `AddBrighter` is the entry point when there are no consumers.

### Complete code blocks

- Every fence carries a language tag: ```` ```csharp ````, ```` ```yaml ````,
Expand Down
8 changes: 6 additions & 2 deletions contents/AgreementDispatcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ registry.RegisterAsync<MyCommand>((request, context) =>
Agreement Dispatcher can be combined with [Dynamic Message Deserialization](DynamicMessageDeserialization.md) for two-level routing:

```csharp
using Paramore.Brighter;
using Paramore.Brighter.Extensions.DependencyInjection;
using Paramore.Brighter.MessagingGateway.Kafka;
using Paramore.Brighter.ServiceActivator.Extensions.DependencyInjection;

// Level 1: Dynamic deserialization (CloudEvents type → Request type)
var subscription = new KafkaSubscription(
new SubscriptionName("paramore.example.orders"),
Expand All @@ -130,8 +135,7 @@ var subscription = new KafkaSubscription(
);

// Level 2: Agreement dispatcher (Request content → Handler)
services.AddBrighter(options => { })
.AddConsumers(options => { options.Subscriptions = new[] { subscription }; })
services.AddConsumers(options => { options.Subscriptions = new[] { subscription }; })
.Handlers(registry =>
{
registry.Register<OrderCreated>((request, context) =>
Expand Down
3 changes: 2 additions & 1 deletion contents/AzureServiceBusConfiguration.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ is `Proactor`.
This is a typical *Subscription* configuration in a Consumer application:

``` csharp
// ...
private static void ConfigureBrighter(HostBuilderContext hostContext, IServiceCollection services)
{
var subscriptions = new Subscription[]
Expand Down Expand Up @@ -192,7 +193,7 @@ private static void ConfigureBrighter(HostBuilderContext hostContext, IServiceCo
builder.Services.AddConsumers(options =>
{
options.Subscriptions = subscriptions;
options.ChannelFactory = new AzureServiceBusChannelFactory(asbConsumerFactory);
options.DefaultChannelFactory = new AzureServiceBusChannelFactory(asbConsumerFactory);

}
```
Expand Down
2 changes: 1 addition & 1 deletion contents/DynamoInbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ private static void ConfigureBrighter(HostBuilderContext hostContext, IServiceCo

services.AddConsumers(opt =>
{
opt.Inbox = new InboxConfiguration(new DynamoDbInbox(dynamoDb, new DynamoDbInboxConfiguration()));
opt.InboxConfiguration = new InboxConfiguration(new DynamoDbInbox(dynamoDb, new DynamoDbInboxConfiguration()));
...
});
}
Expand Down
11 changes: 4 additions & 7 deletions contents/InMemoryInbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,15 @@ The InMemory Inbox provides message deduplication without requiring a database.
// ...
var bus = new InternalBus();

services.AddBrighter(options =>
services.AddConsumers(options =>
{
options.HandlerLifetime = ServiceLifetime.Scoped;
})
.AddConsumers(options =>
{
options.Inbox = new InboxConfiguration(
options.InboxConfiguration = new InboxConfiguration(
new InMemoryInbox(TimeProvider.System),
InboxConfiguration.NoActionOnExists
actionOnExists: OnceOnlyAction.Warn
);
options.Subscriptions = subscriptions;
options.ChannelFactory = new InMemoryChannelFactory(bus);
options.DefaultChannelFactory = new InMemoryChannelFactory(bus, TimeProvider.System);
})
.AutoFromAssemblies();
```
Expand Down
63 changes: 37 additions & 26 deletions contents/InMemoryOptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ For more details on service provider overloads and the Options pattern, see [Ser
Here's a complete example showing how to use multiple InMemory components together:

```csharp
using Microsoft.Extensions.DependencyInjection;
using Paramore.Brighter;
using Paramore.Brighter.Extensions.DependencyInjection;
using Paramore.Brighter.Inbox;
using Paramore.Brighter.Observability;
using Paramore.Brighter.ServiceActivator.Extensions.DependencyInjection;

public class IntegrationTests : IDisposable
{
private readonly ServiceProvider _serviceProvider;
Expand All @@ -95,24 +102,14 @@ public class IntegrationTests : IDisposable
var services = new ServiceCollection();
var internalBus = new InternalBus();

services.AddBrighter(options =>
services.AddConsumers(options =>
{
options.HandlerLifetime = ServiceLifetime.Scoped;
})
.AddProducers(options =>
{
var publication = new Publication() { Topic = new RoutingKey("PersonCreated") };

options.ProducerRegistry = new InMemoryProducerRegistryFactory(_internalBus , new[] { publication }, InstrumentationOptions.All)
.Create();
options.Outbox = new InMemoryOutbox();
})
.AddConsumers(options =>
{
// InMemory Inbox for deduplication
options.Inbox = new InboxConfiguration(
options.InboxConfiguration = new InboxConfiguration(
new InMemoryInbox(TimeProvider.System),
InboxConfiguration.NoActionOnExists
actionOnExists: OnceOnlyAction.Warn
);

options.Subscriptions = new Subscription[]
Expand All @@ -124,7 +121,15 @@ public class IntegrationTests : IDisposable
)
};

options.ChannelFactory = new InMemoryChannelFactory(_internalBus, TimeProvider.System);
options.DefaultChannelFactory = new InMemoryChannelFactory(_internalBus, TimeProvider.System);
})
.AddProducers(options =>
{
var publication = new Publication() { Topic = new RoutingKey("PersonCreated") };

options.ProducerRegistry = new InMemoryProducerRegistryFactory(_internalBus, new[] { publication }, InstrumentationOptions.All)
.Create();
options.Outbox = new InMemoryOutbox(TimeProvider.System);
})
.UseScheduler(new InMemorySchedulerFactory()) // InMemory Scheduler
.UseInMemoryArchiveProvider() // InMemory Archive
Expand Down Expand Up @@ -182,6 +187,15 @@ public class IntegrationTests : IDisposable
Use InMemory components for development/testing, production components elsewhere:

```csharp
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Paramore.Brighter;
using Paramore.Brighter.Extensions.DependencyInjection;
using Paramore.Brighter.Inbox;
using Paramore.Brighter.Observability;
using Paramore.Brighter.ServiceActivator.Extensions.DependencyInjection;

public static class BrighterConfiguration
{
public static IServiceCollection AddBrighterWithEnvironmentConfig(
Expand All @@ -191,22 +205,19 @@ public static class BrighterConfiguration
{
var internalBus = new InternalBus();

services.AddBrighter(options =>
services.AddConsumers(options =>
{
options.HandlerLifetime = ServiceLifetime.Scoped;
options.InboxConfiguration = GetInbox(environment, configuration);
options.Subscriptions = GetSubscriptions();
options.DefaultChannelFactory = GetChannelFactory(environment, configuration, internalBus);
})
.AddProducers(options =>
{
options.ProducerRegistry = GetProducerRegistry(environment, configuration, internalBus);
})
.UseOutbox(GetOutbox(environment, configuration))
.UseScheduler(GetSchedulerFactory(environment, configuration))
.AddConsumers(options =>
{
options.Inbox = GetInbox(environment, configuration);
options.Subscriptions = GetSubscriptions();
options.ChannelFactory = GetChannelFactory(environment, configuration, internalBus);
})
.AutoFromAssemblies();

return services;
Expand All @@ -215,7 +226,7 @@ public static class BrighterConfiguration
private static IAmAProducerRegistry GetProducerRegistry(
IHostEnvironment environment,
IConfiguration configuration,
IAmABus bus)
InternalBus bus)
{
if (environment.IsDevelopment() || environment.IsEnvironment("Testing"))
{
Expand Down Expand Up @@ -263,25 +274,25 @@ public static class BrighterConfiguration
{
return new InboxConfiguration(
new InMemoryInbox(TimeProvider.System),
InboxConfiguration.NoActionOnExists
actionOnExists: OnceOnlyAction.Warn
);
}

// Production: SQL Server, PostgreSQL, MySQL, DynamoDB, etc.
return new InboxConfiguration(
new MsSqlInbox(/* production config */),
InboxConfiguration.NoActionOnExists
actionOnExists: OnceOnlyAction.Warn
);
}

private static IAmAChannelFactory GetChannelFactory(
IHostEnvironment environment,
IConfiguration configuration,
IAmABus bus)
InternalBus bus)
{
if (environment.IsDevelopment() || environment.IsEnvironment("Testing"))
{
return new InMemoryChannelFactory(bus);
return new InMemoryChannelFactory(bus, TimeProvider.System);
}

// Production: RabbitMQ, Kafka, AWS SQS, etc.
Expand Down
38 changes: 17 additions & 21 deletions contents/InMemoryTransport.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,15 @@ services.AddBrighter(options =>

var internalBus = new InternalBus();

services.AddBrighter(options =>
services.AddConsumers(options =>
{
options.HandlerLifetime = ServiceLifetime.Scoped;
})
.AddConsumers(options =>
{
options.Subscriptions = subscriptions;
options.ChannelFactory = new InMemoryChannelFactory(internalBus, TimeProvider.System);
options.DefaultChannelFactory = new InMemoryChannelFactory(internalBus, TimeProvider.System);
})
.AutoFromAssemblies()
.AddHostedService<ServiceActivatorHostedService>();
.AutoFromAssemblies();

services.AddHostedService<ServiceActivatorHostedService>();
```

## InMemory Subscription Options
Expand Down Expand Up @@ -135,19 +133,9 @@ public class Startup
{
var internalBus = new InternalBus();

services.AddBrighter(options =>
services.AddConsumers(options =>
{
options.HandlerLifetime = ServiceLifetime.Scoped;
})
.AddProducers(options =>
{
var publication = new Publication() { Topic = new RoutingKey("GreetingMade") };

options.ProducerRegistry = new InMemoryProducerRegistryFactory(internalBus , new[] { publication }, InstrumentationOptions.All)
.Create();
})
.AddConsumers(options =>
{
options.Subscriptions = new Subscription[]
{
new Subscription<GreetingMade>(
Expand All @@ -156,10 +144,18 @@ public class Startup
new RoutingKey("GreetingMade")
)
};
options.ChannelFactory = new InMemoryChannelFactory(internalBus, TimeProvider.System);
options.DefaultChannelFactory = new InMemoryChannelFactory(internalBus, TimeProvider.System);
})
.AddProducers(options =>
{
var publication = new Publication() { Topic = new RoutingKey("GreetingMade") };

options.ProducerRegistry = new InMemoryProducerRegistryFactory(internalBus, new[] { publication }, InstrumentationOptions.All)
.Create();
})
.AutoFromAssemblies()
.AddHostedService<ServiceActivatorHostedService>();
.AutoFromAssemblies();

services.AddHostedService<ServiceActivatorHostedService>();
}
}
```
Expand Down
6 changes: 4 additions & 2 deletions contents/KafkaConfiguration.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ Reactor rather than the Proactor.
The following example shows how a subscription might be configured:

``` csharp
// ...
private static void ConfigureBrighter(HostBuilderContext hostContext, IServiceCollection services)
{
var subscriptions = new KafkaSubscription[]
Expand All @@ -394,7 +395,7 @@ The following example shows how a subscription might be configured:
services.AddConsumers(options =>
{
options.Subscriptions = subscriptions;
options.ChannelFactory = new ChannelFactory(consumerFactory);
options.DefaultChannelFactory = new ChannelFactory(consumerFactory);
}).AutoFromAssemblies();


Expand All @@ -411,6 +412,7 @@ The **configHook** takes a *delegate* (you can pass a lambda). Your delegate wil
You can use it as follows:

``` csharp
// ...
var subscription = new KafkaSubscription<GreetingEvent>(
subscriptionName: new SubscriptionName("paramore.example.greeting"),
channelName: new ChannelName("greeting.event"),
Expand Down Expand Up @@ -439,7 +441,7 @@ var consumerFactory = new KafkaMessageConsumerFactory(
services.AddConsumers(options =>
{
options.Subscriptions = subscriptions;
options.ChannelFactory = new ChannelFactory(consumerFactory);
options.DefaultChannelFactory = new ChannelFactory(consumerFactory);
}).AutoFromAssemblies();
```

Expand Down
3 changes: 2 additions & 1 deletion contents/MSSQLInbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ For this we will need the *Inbox* packages for the MsSQL *Inbox*.
* **Paramore.Brighter.Inbox.MsSql**

``` csharp
// ...
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices(hostContext, services) =>
Expand All @@ -29,7 +30,7 @@ private static void ConfigureBrighter(HostBuilderContext hostContext, IServiceCo
services.AddConsumers(options =>
{
var configuration = new RelationalDatabaseConfiguration(connectionString, "BrighterTests", inboxTableName: "InboxMessages");
opt.Inbox = new InboxConfiguration(new MsSqlInbox(configuration));
options.InboxConfiguration = new InboxConfiguration(new MsSqlInbox(configuration));
...
});
}
Expand Down
2 changes: 1 addition & 1 deletion contents/PostgreSQLMessageBroker.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ var channelFactory = new PostgresChannelFactory(postgresConfiguration);
services.AddConsumers(options =>
{
options.Subscriptions = subscriptions;
options.ChannelFactory = channelFactory;
options.DefaultChannelFactory = channelFactory;
})
.AutoFromAssemblies();
```
Expand Down
3 changes: 2 additions & 1 deletion contents/RabbitMQConfiguration.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ and supplies four defaults the table cannot: `requestType` is `T`, `subscription
This is a typical *Subscription* configuration in a Consumer application:

``` csharp
// ...
private static void ConfigureBrighter(HostBuilderContext hostContext, IServiceCollection services)
{
var subscriptions = new Subscription[]
Expand Down Expand Up @@ -307,7 +308,7 @@ private static void ConfigureBrighter(HostBuilderContext hostContext, IServiceCo
services.AddConsumers(options =>
{
options.Subscriptions = subscriptions;
options.ChannelFactory = new ChannelFactory(rmqMessageConsumerFactory);
options.DefaultChannelFactory = new ChannelFactory(rmqMessageConsumerFactory);
... //see Basic Configuration
})
```
Expand Down
Loading
Loading