Skip to content

Commit

Permalink
docs on strict ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremydmiller committed Apr 19, 2024
1 parent 11a57f4 commit 2a3fd55
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 8 deletions.
7 changes: 6 additions & 1 deletion docs/guide/durability/sqlserver.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,14 @@ that they are utilizing the transactional inbox and outbox. The Sql Server queue
<!-- snippet: sample_setting_sql_server_queue_to_buffered -->
<a id='snippet-sample_setting_sql_server_queue_to_buffered'></a>
```cs
opts.ListenToPostgresqlQueue("sender").BufferedInMemory();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Persistence/PostgresqlTests/Transport/compliance_tests.cs#L61-L65' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_setting_sql_server_queue_to_buffered' title='Start of snippet'>anchor</a></sup>
<a id='snippet-sample_setting_sql_server_queue_to_buffered-1'></a>
```cs
opts.ListenToSqlServerQueue("sender").BufferedInMemory();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Persistence/SqlServerTests/Transport/compliance_tests.cs#L65-L69' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_setting_sql_server_queue_to_buffered' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Persistence/SqlServerTests/Transport/compliance_tests.cs#L65-L69' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_setting_sql_server_queue_to_buffered-1' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Using this option just means that the Sql Server queues can be used for both sending or receiving with no integration
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/http/endpoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public static OrderShipped Ship(ShipOrder command, Order order)
return new OrderShipped();
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L105-L118' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_emptyresponse' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L106-L119' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_emptyresponse' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## JSON Handling
Expand Down
14 changes: 9 additions & 5 deletions docs/guide/http/marten.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,13 @@ use the new `[Aggregate]` attribute from Wolverine.Http.Marten on endpoint metho
// the [EmptyResponse] attribute
public static OrderShipped Ship(ShipOrder2 command, [Aggregate] Order order)
{
if (order.HasShipped)
throw new InvalidOperationException("This has already shipped!");

return new OrderShipped();
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L120-L132' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_aggregate_attribute_1' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L121-L136' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_aggregate_attribute_1' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Using this version of the "aggregate workflow", you no longer have to supply a command in the request body, so you could
Expand All @@ -114,7 +117,7 @@ public static OrderShipped Ship3([Aggregate] Order order)
return new OrderShipped();
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L134-L146' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_aggregate_attribute_2' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L138-L150' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_aggregate_attribute_2' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

A couple other notes:
Expand Down Expand Up @@ -175,6 +178,7 @@ public class Order
public DateTimeOffset? Shipped { get; private set; }

public Dictionary<string, Item> Items { get; set; } = new();
public bool HasShipped { get; set; }

// These methods are used by Marten to update the aggregate
// from the raw events
Expand All @@ -196,7 +200,7 @@ public class Order
public bool IsShipped() => Shipped.HasValue;
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L11-L72' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_order_aggregate_for_http' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L11-L73' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_order_aggregate_for_http' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

To append a single event to an event stream from an HTTP endpoint, you can use a return value like so:
Expand All @@ -215,7 +219,7 @@ public static OrderShipped Ship(ShipOrder command, Order order)
return new OrderShipped();
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L105-L118' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_emptyresponse' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L106-L119' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_emptyresponse' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Or potentially append multiple events using the `Events` type as a return value like this sample:
Expand Down Expand Up @@ -251,7 +255,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#L196-L226' 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#L200-L230' 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 -->

### Compiled Query Resource Writer Policy
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/http/problemdetails.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,5 @@ public static ProblemDetails Before(IShipOrder command, Order order)
return WolverineContinue.NoProblems;
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L86-L100' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_before_on_http_aggregate' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L87-L101' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_before_on_http_aggregate' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
32 changes: 32 additions & 0 deletions docs/guide/messaging/listeners.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,35 @@ ListeningAgent-->CircuitBreaker: potentially stops the listening
from the messaging transport like a Rabbit MQ broker, and passes that information to Wolverine's message handlers
* `ListeningAgent` is a controller within Wolverine that governs the listener lifecycle including pauses and restarts depending
on load or error conditions

## Strictly Ordered Listeners <Badge type="tip" text="2.3" />

In the case where you need messages from a single endpoint to be processed in strict, global order across the entire application,
you have the `ListenWithStrictOrdering()` option:

<!-- snippet: sample_utilizing_ListenWithStrictOrdering -->
<a id='snippet-sample_utilizing_listenwithstrictordering'></a>
```cs
var host = await Host.CreateDefaultBuilder().UseWolverine(opts =>
{
opts.UseRabbitMq().EnableWolverineControlQueues();
opts.PersistMessagesWithPostgresql(Servers.PostgresConnectionString, "listeners");

opts.ListenToRabbitQueue("ordered")

// This option is available on all types of Wolverine
// endpoints that can be configured to be a listener
.ListenWithStrictOrdering();
}).StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/exclusive_listeners.cs#L33-L47' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_utilizing_listenwithstrictordering' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

This option does a couple things:

* Ensures that Wolverine will *only* listen for messages on this endpoint on a single running node
* Sets any local execution of the listener's internal, local queue to be strictly sequential and only process messages with
a single thread



Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,25 @@ public exclusive_listeners(ITestOutputHelper output)
_output = output;
}

public static async Task documentation_sample()
{
#region sample_utilizing_ListenWithStrictOrdering

var host = await Host.CreateDefaultBuilder().UseWolverine(opts =>
{
opts.UseRabbitMq().EnableWolverineControlQueues();
opts.PersistMessagesWithPostgresql(Servers.PostgresConnectionString, "listeners");
opts.ListenToRabbitQueue("ordered")
// This option is available on all types of Wolverine
// endpoints that can be configured to be a listener
.ListenWithStrictOrdering();
}).StartAsync();

#endregion
}

[Fact]
public async Task exclusive_listeners_are_automatically_started_in_solo_mode()
{
Expand Down

0 comments on commit 2a3fd55

Please sign in to comment.