Skip to content

Commit

Permalink
Add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Hawxy committed May 7, 2024
1 parent 0f2e849 commit ec54811
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 5 deletions.
34 changes: 32 additions & 2 deletions docs/configuration/hostbuilder.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ services.AddMarten()
.UseLightweightSessions()
.UseNpgsqlDataSource();
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/CoreTests/MartenServiceCollectionExtensionsTests.cs#L291-L299' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_usenpgsqldatasource' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/CoreTests/MartenServiceCollectionExtensionsTests.cs#L292-L300' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_usenpgsqldatasource' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

If you're on .NET 8 (and above), you can also use a dedicated [keyed registration](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#keyed-di-services). This can be useful for scenarios where you need more than one data source registered:
Expand All @@ -143,9 +143,39 @@ services.AddMarten()
.UseLightweightSessions()
.UseNpgsqlDataSource();
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/CoreTests/MartenServiceCollectionExtensionsTests.cs#L291-L299' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_usenpgsqldatasource' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/CoreTests/MartenServiceCollectionExtensionsTests.cs#L292-L300' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_usenpgsqldatasource' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## Using a Multi-Host Data Source <Badge type="tip" text="7.11" />

Marten includes support for `NpgsqlMultiHostDataSource`, allowing you to spread queries over your read replicas, potentially improving throughput in read-heavy applications. To get started, your connection string should specify your primary host along with all replicas, per [Npgsql documentation](https://www.npgsql.org/doc/failover-and-load-balancing.html).

Configuring `NpgsqlMultiHostDataSource` is very similar to a normal data source, simply swapping it for `AddMultiHostNpgsqlDataSource`. Marten will always use the primary node for queries with a `NpgsqlMultiHostDataSource` unless you explictly opt to use the standby nodes. You can adjust what type of node Marten uses for querying via the `MultiHostSettings` store options:

<!-- snippet: sample_using_UseNpgsqlDataSourceMultiHost -->
<a id='snippet-sample_using_usenpgsqldatasourcemultihost'></a>
```cs
services.AddMultiHostNpgsqlDataSource(ConnectionSource.ConnectionString);

services.AddMarten(x =>
{
// Will prefer standby nodes for querying.
x.Advanced.MultiHostSettings.ReadSessionPreference = TargetSessionAttributes.PreferStandby;
})
.UseLightweightSessions()
.UseNpgsqlDataSource();
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/CoreTests/MartenServiceCollectionExtensionsTests.cs#L314-L326' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_usenpgsqldatasourcemultihost' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

::: warning
Marten will only use your read node preference with user queries (using IQuerySession) that are using a Marten-managed lifetime.

Internal queries, including the async daemon, will always use your primary node for reliability.

Ensure your replication delay is acceptable as you risk returning outdated queries.
:::

## Composite Configuration with ConfigureMarten()

The `AddMarten()` mechanism assumes that you are expressing all of the Marten configuration in one place and "know" what that configuration is upfront. Consider these possibilities where that isn't necessarily possible or desirable:
Expand Down
2 changes: 1 addition & 1 deletion docs/schema/migrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ services.AddMarten(opts =>
// database changes on application startup
.ApplyAllDatabaseChangesOnStartup();
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/CoreTests/MartenServiceCollectionExtensionsTests.cs#L149-L162' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_applyalldatabasechangesonstartup' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/CoreTests/MartenServiceCollectionExtensionsTests.cs#L150-L163' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_applyalldatabasechangesonstartup' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

In the option above, Marten is calling the same functionality within an `IHostedService` background task.
Expand Down
31 changes: 30 additions & 1 deletion src/CoreTests/MartenServiceCollectionExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Marten.Testing.Harness;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Npgsql;
using Shouldly;
using Weasel.Core.Migrations;
using Xunit;
Expand Down Expand Up @@ -138,7 +139,7 @@ public void no_error_if_IHostEnvironment_does_not_exist()
var rules = store.Options.CreateGenerationRules();
rules.ApplicationAssembly.ShouldBe(store.Options.ApplicationAssembly);
}

[Fact]
public async Task apply_changes_on_startup()
{
Expand Down Expand Up @@ -305,6 +306,34 @@ public async Task use_npgsql_data_source()
Call(session).ShouldNotThrow();
}

[Fact]
public async Task use_npgsql_multi_host_data_source()
{
var services = new ServiceCollection();

#region sample_using_UseNpgsqlDataSourceMultiHost

services.AddMultiHostNpgsqlDataSource(ConnectionSource.ConnectionString);

services.AddMarten(x =>
{
// Will prefer standby nodes for querying.
x.Advanced.MultiHostSettings.ReadSessionPreference = TargetSessionAttributes.PreferStandby;
})
.UseLightweightSessions()
.UseNpgsqlDataSource();

#endregion

var serviceProvider = services.BuildServiceProvider();

await using var session = serviceProvider.GetService<IDocumentSession>();
Func<bool> Call(IDocumentSession s) => () => s.Query<Target>().Any();
Call(session).ShouldNotThrow();
}



#if NET8_0
[Fact]
public async Task use_npgsql_data_source_with_keyed_registration()
Expand Down
2 changes: 1 addition & 1 deletion src/Marten/StoreOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,7 @@ public void ModifySerializer(Action<ISerializer> configure)
public PostgresqlMigrator Migrator { get; } = new();

/// <summary>
/// Configuration options when using <see cref="NpgsqlMultiHostDataSource"/>
/// Configuration options when using a <see cref="NpgsqlMultiHostDataSource"/>
/// </summary>
public MultiHostSettings MultiHostSettings { get; } = new();

Expand Down

0 comments on commit ec54811

Please sign in to comment.