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
236 changes: 226 additions & 10 deletions docs/guide/durability/marten/event-sourcing.md

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions docs/guide/handlers/persistence.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,15 @@ public enum ValueSource
/// <summary>
/// The value should be sourced by a route argument of an HTTP request
/// </summary>
RouteValue
RouteValue,

/// <summary>
/// The value should be sourced by a query string parameter of an HTTP request
/// </summary>
FromQueryString
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Wolverine/Attributes/ModifyChainAttribute.cs#L17-L37' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_valuesource' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Wolverine/Attributes/ModifyChainAttribute.cs#L17-L42' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_valuesource' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Some other facts to know about `[Entity]` usage:
Expand Down
19 changes: 15 additions & 4 deletions docs/guide/http/marten.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public static Invoice GetSoftDeleted([Document(Required = true, MaybeSoftDeleted
<!-- endSnippet -->


## Marten Aggregate Workflow
## Marten Aggregate Workflow

The http endpoints can play inside the full "critter stack" combination with [Marten](https://martendb.io) with Wolverine's [specific
support for Event Sourcing and CQRS](/guide/durability/marten/event-sourcing). Originally this has been done
Expand All @@ -105,6 +105,17 @@ Wolverine 1.10 added a more HTTP-centric approach using route arguments.

### Using Route Arguments

::: tip
The `[Aggregate]` attribute was originally meant for the "aggregate handler workflow" where Wolverine is interacting with
Marten with the assumption that it will be appending events to Marten streams and getting you ready for versioning assertions.

If all you need is a read only copy of Marten aggregate data, the `[ReadAggregate]` is a lighter weight option.

Also, the `[WriteAggregate]` attribute has the exact same behavior as the older `[Aggregate]`, but is available in both
message handlers and HTTP endpoints. You may want to prefer `[WriteAggregate]` just to be more clear in the code about
what's happening.
:::

To opt into the Wolverine + Marten "aggregate workflow", but use data from route arguments for the aggregate id,
use the new `[Aggregate]` attribute from Wolverine.Http.Marten on endpoint method parameters like shown below:

Expand Down Expand Up @@ -291,7 +302,7 @@ public static (OrderStatus, Events) Post(MarkItemReady command, Order order)
return (new OrderStatus(order.Id, order.IsReadyToShip()), events);
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L213-L243' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_returning_multiple_events_from_http_endpoint' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L227-L257' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_returning_multiple_events_from_http_endpoint' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

### Responding with the Updated Aggregate
Expand All @@ -317,7 +328,7 @@ public static (UpdatedAggregate, Events) ConfirmDifferent(ConfirmOrder command,
);
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L271-L285' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_returning_updated_aggregate_as_response_from_http_endpoint' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L285-L299' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_returning_updated_aggregate_as_response_from_http_endpoint' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## Reading the Latest Version of an Aggregate
Expand All @@ -336,7 +347,7 @@ an HTTP endpoint method, use the `[ReadAggregate]` attribute like this:
[WolverineGet("/orders/latest/{id}")]
public static Order GetLatest(Guid id, [ReadAggregate] Order order) => order;
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L299-L304' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_readaggregate_in_http' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L313-L318' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_readaggregate_in_http' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

If the aggregate doesn't exist, the HTTP request will stop with a 404 status code.
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/http/querystring.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public static class QueryOrdersEndpoint
}
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L310-L350' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_[fromquery]_binding' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L327-L367' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_[fromquery]_binding' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Because we've used the `[FromQuery]` attribute on a parameter argument that's not a simple type, Wolverine is trying to bind
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/messaging/expiration.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public DateTimeOffset? DeliverBy
set => _deliverBy = value?.ToUniversalTime();
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Wolverine/Envelope.cs#L56-L68' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_envelope_deliver_by_property' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Wolverine/Envelope.cs#L57-L69' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_envelope_deliver_by_property' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

At runtime, Wolverine will:
Expand Down
35 changes: 31 additions & 4 deletions docs/guide/messaging/transports/kafka.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ using var host = await Host.CreateDefaultBuilder()

// Override the consumer configuration for only this
// topic
// This is NOT combinatorial with the ConfigureConsumers() call above
// and completely replaces the parent configuration
.ConfigureConsumer(config =>
{
// This will also set the Envelope.GroupId for any
Expand All @@ -102,7 +104,7 @@ using var host = await Host.CreateDefaultBuilder()
opts.Services.AddResourceSetupOnStartup();
}).StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/Kafka/Wolverine.Kafka.Tests/DocumentationSamples.cs#L10-L93' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_bootstrapping_with_kafka' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/Kafka/Wolverine.Kafka.Tests/DocumentationSamples.cs#L10-L95' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_bootstrapping_with_kafka' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

The various `Configure*****()` methods provide quick access to the full API of the Confluent Kafka library for security
Expand Down Expand Up @@ -191,14 +193,39 @@ public static class KafkaInstrumentation
}
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/Kafka/Wolverine.Kafka.Tests/DocumentationSamples.cs#L97-L110' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_kafkainstrumentation_middleware' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/Kafka/Wolverine.Kafka.Tests/DocumentationSamples.cs#L127-L140' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_kafkainstrumentation_middleware' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## Connecting to Multiple Brokers <Badge type="tip" text="4.7" />

Wolverine supports interacting with multiple Kafka brokers within one application like this:

snippet: sample_using_multiple_kafka_brokers
<!-- snippet: sample_using_multiple_kafka_brokers -->
<a id='snippet-sample_using_multiple_kafka_brokers'></a>
```cs
using var host = await Host.CreateDefaultBuilder()
.UseWolverine(opts =>
{
opts.UseKafka("localhost:9092");
opts.AddNamedKafkaBroker(new BrokerName("americas"), "americas-kafka:9092");
opts.AddNamedKafkaBroker(new BrokerName("emea"), "emea-kafka:9092");

// Just publish all messages to Kafka topics
// based on the message type (or message attributes)
// This will get fancier in the near future
opts.PublishAllMessages().ToKafkaTopicsOnNamedBroker(new BrokerName("americas"));

// Or explicitly make subscription rules
opts.PublishMessage<ColorMessage>()
.ToKafkaTopicOnNamedBroker(new BrokerName("emea"), "colors");

// Listen to topics
opts.ListenToKafkaTopicOnNamedBroker(new BrokerName("americas"), "red");
// Other configuration
}).StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/Kafka/Wolverine.Kafka.Tests/DocumentationSamples.cs#L100-L123' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_multiple_kafka_brokers' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Note that the `Uri` scheme within Wolverine for any endpoints from a "named" Kafka broker is the name that you supply
for the broker. So in the example above, you might see `Uri` values for `emea://colors` or `americas://red`.
for the broker. So in the example above, you might see `Uri` values for `emea://colors` or `americas://red`.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ var host = await Host.CreateDefaultBuilder()
.UseConventionalRouting();
}).StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L175-L184' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_conventional_sqs_routing' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L210-L219' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_conventional_sqs_routing' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

In this case any outgoing message types that aren't handled locally or have an explicit subscription will be automatically routed
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/messaging/transports/sqs/deadletterqueues.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ var host = await Host.CreateDefaultBuilder()
});
}).StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L189-L210' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_configuring_dead_letter_queue_for_sqs' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L224-L245' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_configuring_dead_letter_queue_for_sqs' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## Disabling All Native Dead Letter Queueing
Expand Down
43 changes: 37 additions & 6 deletions docs/guide/messaging/transports/sqs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var host = await Host.CreateDefaultBuilder()
.AutoPurgeOnStartup();
}).StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L31-L48' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_simplistic_aws_sqs_setup' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L66-L83' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_simplistic_aws_sqs_setup' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down Expand Up @@ -58,7 +58,7 @@ builder.UseWolverine(opts =>
using var host = builder.Build();
await host.StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L53-L78' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_config_aws_sqs_connection' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L88-L113' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_config_aws_sqs_connection' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand All @@ -76,7 +76,7 @@ var host = await Host.CreateDefaultBuilder()
opts.UseAmazonSqsTransportLocally();
}).StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L16-L26' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_connect_to_sqs_and_localstack' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L51-L61' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_connect_to_sqs_and_localstack' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

And lastly, if you want to explicitly supply an access and secret key for your credentials to SQS, you can use this syntax:
Expand Down Expand Up @@ -110,14 +110,45 @@ builder.UseWolverine(opts =>
using var host = builder.Build();
await host.StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L83-L111' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_setting_aws_credentials' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L118-L146' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_setting_aws_credentials' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## Connecting to Multiple Brokers <Badge type="tip" text="4.7" />

Wolverine supports interacting with multiple Amazon SQS brokers within one application like this:

snippet: sample_using_multiple_sqs_brokers
<!-- snippet: sample_using_multiple_sqs_brokers -->
<a id='snippet-sample_using_multiple_sqs_brokers'></a>
```cs
using var host = await Host.CreateDefaultBuilder()
.UseWolverine(opts =>
{
opts.UseAmazonSqsTransport(config =>
{
// Add configuration for connectivity
});

opts.AddNamedAmazonSqsBroker(new BrokerName("americas"), config =>
{
// Add configuration for connectivity
});

opts.AddNamedAmazonSqsBroker(new BrokerName("emea"), config =>
{
// Add configuration for connectivity
});

// Or explicitly make subscription rules
opts.PublishMessage<SenderConfigurationTests.ColorMessage>()
.ToSqsQueueOnNamedBroker(new BrokerName("emea"), "colors");

// Listen to topics
opts.ListenToSqsQueueOnNamedBroker(new BrokerName("americas"), "red");
// Other configuration
}).StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Samples/Bootstrapping.cs#L17-L46' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_multiple_sqs_brokers' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Note that the `Uri` scheme within Wolverine for any endpoints from a "named" Amazon SQS broker is the name that you supply
for the broker. So in the example above, you might see `Uri` values for `emea://colors` or `americas://red`.
for the broker. So in the example above, you might see `Uri` values for `emea://colors` or `americas://red`.
Loading
Loading