Skip to content

Commit

Permalink
Adjusted Async projection test with IoC injection to remove flakiness
Browse files Browse the repository at this point in the history
The issue was in the Daemon run both as hosted service and then manually to wait for shards.
  • Loading branch information
oskardudycz committed Oct 20, 2023
1 parent da307b5 commit fa24e48
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 30 deletions.
22 changes: 14 additions & 8 deletions docs/events/projections/ioc.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Let's say you have a custom aggregation projection like this one below that need
<!-- snippet: sample_ProductProjection -->
<a id='snippet-sample_productprojection'></a>
```cs
public class ProductProjection : CustomProjection<Product, Guid>
public class ProductProjection: CustomProjection<Product, Guid>
{
private readonly IPriceLookup _lookup;

Expand All @@ -28,10 +28,14 @@ public class ProductProjection : CustomProjection<Product, Guid>
ProjectionName = "Product";
}

public override ValueTask ApplyChangesAsync(DocumentSessionBase session, EventSlice<Product, Guid> slice, CancellationToken cancellation,
ProjectionLifecycle lifecycle = ProjectionLifecycle.Inline)
public override ValueTask ApplyChangesAsync(
DocumentSessionBase session,
EventSlice<Product, Guid> slice,
CancellationToken cancellation,
ProjectionLifecycle lifecycle = ProjectionLifecycle.Inline
)
{
slice.Aggregate ??= new Product{Id = slice.Id};
slice.Aggregate ??= new Product { Id = slice.Id };

foreach (var data in slice.AllData())
{
Expand All @@ -52,7 +56,7 @@ public class ProductProjection : CustomProjection<Product, Guid>
}
}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/EventSourcingTests/Projections/projections_with_IoC_services.cs#L149-L187' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_productprojection' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/EventSourcingTests/Projections/projections_with_IoC_services.cs#L144-L186' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_productprojection' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Now, we *want* to use this projection at runtime within Marten, and need to register the projection
Expand All @@ -73,12 +77,14 @@ using var host = await Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder()
opts.DatabaseSchemaName = "ioc";
})
// Note that this is chained after the call to AddMarten()
.AddProjectionWithServices<ProductProjection>(ProjectionLifecycle.Inline, ServiceLifetime.Singleton);

.AddProjectionWithServices<ProductProjection>(
ProjectionLifecycle.Inline,
ServiceLifetime.Singleton
);
})
.StartAsync();
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/EventSourcingTests/Projections/projections_with_IoC_services.cs#L27-L45' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_registering_projection_built_by_services' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/EventSourcingTests/Projections/projections_with_IoC_services.cs#L23-L43' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_registering_projection_built_by_services' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Note that we're having to explicitly specify the projection lifecycle for the projection used within
Expand Down
43 changes: 21 additions & 22 deletions src/EventSourcingTests/Projections/projections_with_IoC_services.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
using System.Threading.Tasks;
using JasperFx.Core;
using Marten;
using Marten.Events;
using Marten.Events.Aggregation;
using Marten.Events.Daemon;
using Marten.Events.Daemon.Resiliency;
using Marten.Events.Projections;
using Marten.Internal.Sessions;
using Marten.Testing.Harness;
Expand All @@ -17,7 +14,6 @@

namespace EventSourcingTests.Projections;


[Collection("ioc")]
public class projections_with_IoC_services
{
Expand All @@ -37,29 +33,32 @@ public async Task use_projection_as_singleton_and_inline()
opts.DatabaseSchemaName = "ioc";
})
// Note that this is chained after the call to AddMarten()
.AddProjectionWithServices<ProductProjection>(ProjectionLifecycle.Inline, ServiceLifetime.Singleton);

.AddProjectionWithServices<ProductProjection>(
ProjectionLifecycle.Inline,
ServiceLifetime.Singleton
);
})
.StartAsync();

#endregion

var store = host.Services.GetRequiredService<IDocumentStore>();

using var session = store.LightweightSession();
var streamId = session.Events.StartStream<Product>(new ProductRegistered("Ankle Socks", "Socks")).Id;
await using var session = store.LightweightSession();
var streamId = session.Events.StartStream<Product>(
new ProductRegistered("Ankle Socks", "Socks")
).Id;
await session.SaveChangesAsync();

var product = await session.LoadAsync<Product>(streamId);
product.Price.ShouldBeGreaterThan(0);
product.Name.ShouldBe("Ankle Socks");

}

[Fact]
public async Task use_projection_as_singleton_and_async()
{
using var host = await Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder()
using var host = await Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddSingleton<IPriceLookup, PriceLookup>();
Expand All @@ -68,16 +67,15 @@ public async Task use_projection_as_singleton_and_async()
{
opts.Connection(ConnectionSource.ConnectionString);
opts.DatabaseSchemaName = "ioc";
opts.Projections.DaemonLockId = 99123;
})
.AddAsyncDaemon(DaemonMode.Solo)
.AddProjectionWithServices<ProductProjection>(ProjectionLifecycle.Async, ServiceLifetime.Singleton);

}).StartAsync();

var store = host.Services.GetRequiredService<IDocumentStore>();
await store.Advanced.Clean.CompletelyRemoveAllAsync();

using var session = store.LightweightSession();
await using var session = store.LightweightSession();
var streamId = session.Events.StartStream<Product>(new ProductRegistered("Ankle Socks", "Socks")).Id;
await session.SaveChangesAsync();

Expand All @@ -87,9 +85,9 @@ public async Task use_projection_as_singleton_and_async()
await daemon.Tracker.WaitForShardState("Product:All", 1);

var product = await session.LoadAsync<Product>(streamId);
product.ShouldNotBeNull();
product.Price.ShouldBeGreaterThan(0);
product.Name.ShouldBe("Ankle Socks");

}

[Fact]
Expand All @@ -105,23 +103,20 @@ public async Task use_projection_as_scoped_and_inline()
opts.Connection(ConnectionSource.ConnectionString);
opts.DatabaseSchemaName = "ioc";
}).AddProjectionWithServices<ProductProjection>(ProjectionLifecycle.Inline, ServiceLifetime.Scoped);

}).StartAsync();

var store = host.Services.GetRequiredService<IDocumentStore>();

using var session = store.LightweightSession();
await using var session = store.LightweightSession();
var streamId = session.Events.StartStream<Product>(new ProductRegistered("Ankle Socks", "Socks")).Id;
await session.SaveChangesAsync();

var product = await session.LoadAsync<Product>(streamId);
product.Price.ShouldBeGreaterThan(0);
product.Name.ShouldBe("Ankle Socks");

}
}


public interface IPriceLookup
{
double PriceFor(string category);
Expand All @@ -148,7 +143,7 @@ public record ProductRegistered(string Name, string Category);

#region sample_ProductProjection

public class ProductProjection : CustomProjection<Product, Guid>
public class ProductProjection: CustomProjection<Product, Guid>
{
private readonly IPriceLookup _lookup;

Expand All @@ -160,10 +155,14 @@ public ProductProjection(IPriceLookup lookup)
ProjectionName = "Product";
}

public override ValueTask ApplyChangesAsync(DocumentSessionBase session, EventSlice<Product, Guid> slice, CancellationToken cancellation,
ProjectionLifecycle lifecycle = ProjectionLifecycle.Inline)
public override ValueTask ApplyChangesAsync(
DocumentSessionBase session,
EventSlice<Product, Guid> slice,
CancellationToken cancellation,
ProjectionLifecycle lifecycle = ProjectionLifecycle.Inline
)
{
slice.Aggregate ??= new Product{Id = slice.Id};
slice.Aggregate ??= new Product { Id = slice.Id };

foreach (var data in slice.AllData())
{
Expand Down

0 comments on commit fa24e48

Please sign in to comment.