Skip to content

Commit

Permalink
documentation on the new PostgreSQL messaging transport
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremydmiller committed Apr 19, 2024
1 parent 2a3fd55 commit 07bc2dd
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 7 deletions.
1 change: 1 addition & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ export default withMermaid( {
]},
{text: 'TCP', link: '/guide/messaging/transports/tcp'},
{text: 'Sql Server', link: '/guide/messaging/transports/sqlserver'},
{text: 'PostgreSQL', link: '/guide/messaging/transports/postgresql'},
{text: 'MQTT', link: '/guide/messaging/transports/mqtt'},
{text: 'Kafka', link: '/guide/messaging/transports/kafka'}
]
Expand Down
154 changes: 154 additions & 0 deletions docs/guide/durability/postgresql.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# PostgreSQL Integration

::: info
Wolverine can happily use the PostgreSQL durability options with any mix of Entity Framework Core and/or
Marten as a higher level persistence framework
:::

Wolverine supports a PostgreSQL backed message persistence strategy and even a PostgreSQL backed messaging transport
option. To get started, add the `WolverineFx.Postgresql` dependency to your application:

```bash
dotnet add package WolverineFx.Postgresql
```

## Message Persistence

To enable PostgreSQL to serve as Wolverine's [transactional inbox and outbox](./), you just need to use the `WolverineOptions.PersistMessagesWithPostgresql()`
extension method as shown below in a sample:

<!-- snippet: sample_setup_postgresql_storage -->
<a id='snippet-sample_setup_postgresql_storage'></a>
```cs
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("postgres");

builder.Host.UseWolverine(opts =>
{
// Setting up Postgresql-backed message storage
// This requires a reference to Wolverine.Postgresql
opts.PersistMessagesWithPostgresql(connectionString);

// Other Wolverine configuration
});

// This is rebuilding the persistent storage database schema on startup
// and also clearing any persisted envelope state
builder.Host.UseResourceSetupOnStartup();

var app = builder.Build();

// Other ASP.Net Core configuration...
// Using Oakton opens up command line utilities for managing
// the message storage
return await app.RunOaktonCommands(args);
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Persistence/PersistenceTests/Samples/DocumentationSamples.cs#L163-L189' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_setup_postgresql_storage' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## PostgreSQL Messaging Transport <Badge type="tip" text="2.5" />

::: info
All PostgreSQL queues are built into a *wolverine_queues* schema at this point.
:::

The `WolverineFx.PostgreSQL` Nuget also contains a simple messaging transport that was mostly meant to be usable for teams
who want asynchronous queueing without introducing more specialized infrastructure. To enable this transport in your code,
use this option which *also* activates PostgreSQL backed message persistence:

<!-- snippet: sample_using_postgres_transport -->
<a id='snippet-sample_using_postgres_transport'></a>
```cs
using var host = await Host.CreateDefaultBuilder()
.UseWolverine((context, opts) =>
{
var connectionString = context.Configuration.GetConnectionString("sqlserver");
opts.UseSqlServerPersistenceAndTransport(connectionString, "myapp")

// Tell Wolverine to build out all necessary queue or scheduled message
// tables on demand as needed
.AutoProvision()

// Optional that may be helpful in testing, but probably bad
// in production!
.AutoPurgeOnStartup();

// Use this extension method to create subscriber rules
opts.PublishAllMessages().ToSqlServerQueue("outbound");

// Use this to set up queue listeners
opts.ListenToSqlServerQueue("inbound")

.CircuitBreaker(cb =>
{
// fine tune the circuit breaker
// policies here
})

// Optionally specify how many messages to
// fetch into the listener at any one time
.MaximumMessagesToReceive(50);
}).StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Persistence/PersistenceTests/Postgresql/Transport/DocumentationSamples.cs#L12-L46' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_postgres_transport' title='Start of snippet'>anchor</a></sup>
<a id='snippet-sample_using_postgres_transport-1'></a>
```cs
using var host = await Host.CreateDefaultBuilder()
.UseWolverine((context, opts) =>
{
var connectionString = context.Configuration.GetConnectionString("postgres");
opts.UsePostgresqlPersistenceAndTransport(connectionString, "myapp")

// Tell Wolverine to build out all necessary queue or scheduled message
// tables on demand as needed
.AutoProvision()

// Optional that may be helpful in testing, but probably bad
// in production!
.AutoPurgeOnStartup();

// Use this extension method to create subscriber rules
opts.PublishAllMessages().ToPostgresqlQueue("outbound");

// Use this to set up queue listeners
opts.ListenToPostgresqlQueue("inbound")

.CircuitBreaker(cb =>
{
// fine tune the circuit breaker
// policies here
})

// Optionally specify how many messages to
// fetch into the listener at any one time
.MaximumMessagesToReceive(50);
}).StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Persistence/PostgresqlTests/DocumentationSamples.cs#L12-L46' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_postgres_transport-1' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

The PostgreSQL transport is strictly queue-based at this point. The queues are configured as durable by default, meaning
that they are utilizing the transactional inbox and outbox. The PostgreSQL queues can also be buffered:

<!-- snippet: sample_setting_sql_server_queue_to_buffered -->
<a id='snippet-sample_setting_sql_server_queue_to_buffered'></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>
<!-- endSnippet -->

Using this option just means that the PostgreSQL queues can be used for both sending or receiving with no integration
with the transactional inbox or outbox. This is a little more performant, but less safe as messages could be
lost if held in memory when the application shuts down unexpectedly.

## Multi-Tenancy

If utilizing the PostgreSQL transport with Marten multi-tenancy through separate databases per tenant, the PostgreSQL
queues will be built an monitored for each tenant database as well as any master database.

## Integration with Marten

The PostgreSQL message persistence and transport is automatically included with the `AddMarten().IntegrateWithWolverine()`
configuration syntax.
7 changes: 1 addition & 6 deletions docs/guide/durability/sqlserver.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,9 @@ 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-1' 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' 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
3 changes: 3 additions & 0 deletions docs/guide/messaging/transports/postgresql.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# PostgreSQL Transport

TODO
48 changes: 48 additions & 0 deletions src/Persistence/PostgresqlTests/DocumentationSamples.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Wolverine;
using Wolverine.Postgresql;

namespace PostgresqlTests;

public class DocumentationSamples
{
public static async Task Bootstrapping()
{
#region sample_using_postgres_transport

using var host = await Host.CreateDefaultBuilder()
.UseWolverine((context, opts) =>
{
var connectionString = context.Configuration.GetConnectionString("postgres");
opts.UsePostgresqlPersistenceAndTransport(connectionString, "myapp")

// Tell Wolverine to build out all necessary queue or scheduled message
// tables on demand as needed
.AutoProvision()

// Optional that may be helpful in testing, but probably bad
// in production!
.AutoPurgeOnStartup();


// Use this extension method to create subscriber rules
opts.PublishAllMessages().ToPostgresqlQueue("outbound");

// Use this to set up queue listeners
opts.ListenToPostgresqlQueue("inbound")

.CircuitBreaker(cb =>
{
// fine tune the circuit breaker
// policies here
})

// Optionally specify how many messages to
// fetch into the listener at any one time
.MaximumMessagesToReceive(50);
}).StartAsync();

#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ await SenderIs(opts =>
opts.UsePostgresqlPersistenceAndTransport(Servers.PostgresConnectionString, "buffered_compliance")
.AutoProvision().AutoPurgeOnStartup().DisableInboxAndOutboxOnAll();

#region sample_setting_sql_server_queue_to_buffered
#region sample_setting_postgres_queue_to_buffered

opts.ListenToPostgresqlQueue("sender").BufferedInMemory();

Expand Down

0 comments on commit 07bc2dd

Please sign in to comment.