-
Notifications
You must be signed in to change notification settings - Fork 647
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* Compile-only smoke test for API usages under nullable reference types * Change ToSaga expressions to object? * Message mappers too, otherwise messages have to be 100% non-null properties * Approve * Additional approvals and API test coverage --------- Co-authored-by: Daniel Marbach <[email protected]>
- Loading branch information
1 parent
627c0be
commit 21e5b5e
Showing
6 changed files
with
205 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
#nullable enable | ||
|
||
/** | ||
* The code in this file is not meant to be executed. It only shows idiomatic usages of NServiceBus | ||
* APIs, but with nullable reference types enabled, so that we can attempt to make sure that the | ||
* addition of nullable annotations in our public APIs doesn't create nullability warnings on | ||
* our own APIs under normal circumstances. It's sort of a mini-Snippets to provide faster | ||
* feedback than having to release an alpha package and check that Snippets in docs compile. | ||
*/ | ||
|
||
namespace NServiceBus.Core.Tests.API.NullableApiUsages | ||
{ | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using NServiceBus.Extensibility; | ||
using NServiceBus.Logging; | ||
using NServiceBus.MessageMutator; | ||
using NServiceBus.Persistence; | ||
using NServiceBus.Pipeline; | ||
using NServiceBus.Sagas; | ||
|
||
public class TopLevelApis | ||
{ | ||
public async Task SetupEndpoint(CancellationToken cancellationToken = default) | ||
{ | ||
var cfg = new EndpointConfiguration("EndpointName"); | ||
|
||
cfg.Conventions() | ||
.DefiningCommandsAs(t => t.Namespace?.EndsWith(".Commands") ?? false) | ||
.DefiningEventsAs(t => t.Namespace?.EndsWith(".Events") ?? false) | ||
.DefiningMessagesAs(t => t.Namespace?.EndsWith(".Messages") ?? false); | ||
|
||
cfg.SendFailedMessagesTo("error"); | ||
|
||
var routing = cfg.UseTransport(new LearningTransport()); | ||
routing.RouteToEndpoint(typeof(Cmd), "Destination"); | ||
|
||
var persistence = cfg.UsePersistence<LearningPersistence>(); | ||
|
||
cfg.UseSerialization<SystemJsonSerializer>() | ||
.Options(new System.Text.Json.JsonSerializerOptions()); | ||
|
||
// Start directly | ||
await Endpoint.Start(cfg, cancellationToken); | ||
|
||
// Or create, then start | ||
var startable = await Endpoint.Create(cfg, cancellationToken); | ||
var ep = await startable.Start(cancellationToken); | ||
|
||
await ep.Send(new Cmd(), cancellationToken); | ||
await ep.Publish(new Evt(), cancellationToken); | ||
await ep.Publish<Evt>(cancellationToken); | ||
} | ||
} | ||
|
||
public class TestHandler : IHandleMessages<Cmd> | ||
{ | ||
ILog logger; | ||
|
||
public TestHandler(ILog logger) | ||
{ | ||
this.logger = logger; | ||
} | ||
|
||
public async Task Handle(Cmd message, IMessageHandlerContext context) | ||
{ | ||
logger.Info(message.OrderId); | ||
await context.Send(new Cmd()); | ||
await context.Publish(new Evt()); | ||
|
||
var opts = new SendOptions(); | ||
opts.DelayDeliveryWith(TimeSpan.FromSeconds(5)); | ||
opts.SetHeader("a", "1"); | ||
} | ||
} | ||
|
||
public class TestSaga : Saga<TestSagaData>, | ||
IAmStartedByMessages<Cmd>, | ||
IHandleMessages<Evt>, | ||
IHandleTimeouts<TestTimeout> | ||
{ | ||
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<TestSagaData> mapper) | ||
{ | ||
mapper.MapSaga(saga => saga.OrderId) | ||
.ToMessage<Cmd>(m => m.OrderId) | ||
.ToMessage<Evt>(m => m.OrderId) | ||
.ToMessageHeader<Cmd>("HeaderName"); | ||
} | ||
|
||
public async Task Handle(Cmd message, IMessageHandlerContext context) | ||
{ | ||
await context.Send(new Cmd()); | ||
await context.Publish(new Evt()); | ||
Console.WriteLine(Data.OrderId); | ||
await RequestTimeout<TestTimeout>(context, TimeSpan.FromMinutes(1)); | ||
MarkAsComplete(); | ||
} | ||
|
||
public async Task Handle(Evt message, IMessageHandlerContext context) | ||
{ | ||
await context.Send(new Cmd()); | ||
await context.Publish(new Evt()); | ||
await context.Publish<Evt>(); | ||
} | ||
|
||
public Task Timeout(TestTimeout state, IMessageHandlerContext context) | ||
{ | ||
Console.WriteLine(state.TimeoutData); | ||
return Task.CompletedTask; | ||
} | ||
} | ||
|
||
public class TestSagaOldMapping : Saga<TestSagaData>, | ||
IAmStartedByMessages<Cmd> | ||
{ | ||
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<TestSagaData> mapper) | ||
{ | ||
mapper.ConfigureMapping<Cmd>(m => m.OrderId).ToSaga(s => s.OrderId); | ||
mapper.ConfigureHeaderMapping<Cmd>("HeaderName"); | ||
} | ||
|
||
public Task Handle(Cmd message, IMessageHandlerContext context) => throw new NotImplementedException(); | ||
} | ||
|
||
public class Cmd : ICommand | ||
{ | ||
public string? OrderId { get; set; } | ||
} | ||
|
||
public class Evt : IEvent | ||
{ | ||
public string? OrderId { get; set; } | ||
} | ||
|
||
public class TestSagaData : ContainSagaData | ||
{ | ||
public string? OrderId { get; set; } | ||
} | ||
|
||
public class TestTimeout | ||
{ | ||
public string? TimeoutData { get; set; } | ||
} | ||
|
||
public class NotUsedSagaFinder : ISagaFinder<TestSagaData, Cmd> | ||
{ | ||
public async Task<TestSagaData?> FindBy(Cmd message, ISynchronizedStorageSession storageSession, IReadOnlyContextBag context, CancellationToken cancellationToken = default) | ||
{ | ||
// Super-gross, never do this | ||
await Task.Yield(); | ||
|
||
if (context.TryGet<TestSagaData>(out var result)) | ||
{ | ||
return result; | ||
} | ||
|
||
return null; | ||
} | ||
} | ||
|
||
public class TestBehavior : Behavior<IIncomingLogicalMessageContext> | ||
{ | ||
public override async Task Invoke(IIncomingLogicalMessageContext context, Func<Task> next) | ||
{ | ||
await Task.Delay(10); | ||
await next(); | ||
} | ||
} | ||
|
||
public class TestIncomingMutator : IMutateIncomingMessages | ||
{ | ||
public Task MutateIncoming(MutateIncomingMessageContext context) => Task.CompletedTask; | ||
} | ||
|
||
public class TestIncomingTransportMutator : IMutateIncomingTransportMessages | ||
{ | ||
public Task MutateIncoming(MutateIncomingTransportMessageContext context) => Task.CompletedTask; | ||
} | ||
|
||
public class TestOutgoingMutator : IMutateOutgoingMessages | ||
{ | ||
public Task MutateOutgoing(MutateOutgoingMessageContext context) => Task.CompletedTask; | ||
} | ||
|
||
public class TestOutgoingTransportMutator : IMutateOutgoingTransportMessages | ||
{ | ||
public Task MutateOutgoing(MutateOutgoingTransportMessageContext context) => Task.CompletedTask; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters