Skip to content

Commit

Permalink
Added reproduction spec for missing custom mailbox when using DI (#7402)
Browse files Browse the repository at this point in the history
* Added reproduction spec for missing custom mailbox when using DI

* fixed spec
  • Loading branch information
Aaronontheweb authored Dec 4, 2024
1 parent 1a22e39 commit 1f448e9
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 59 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// -----------------------------------------------------------------------
// <copyright file="ActorTestServices.cs" company="Akka.NET Project">
// Copyright (C) 2009-2024 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2024 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Threading;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Configuration;
using Akka.Dispatch;
using Akka.TestKit;
using Akka.Util.Internal;
using Microsoft.Extensions.Hosting;

namespace Akka.DependencyInjection.Tests;

internal class TestDiActor : ReceiveActor
{
public static readonly AtomicCounter Counter = new(0);

public TestDiActor(InjectedService injected)
{
long count = Counter.GetAndIncrement();
Receive<GetMessage>(_ => Sender.Tell(new Message { Value = injected.Message, Counter = count }));
}
}

internal class InjectedEchoActor : ReceiveActor
{
public InjectedEchoActor(InjectedService injected, string thing)
{
Receive<string>(str => Sender.Tell(new Message { Value = injected.Message + thing, Counter = 0 }));
Receive<int>(i => Sender.Tell(new Message { Value = injected.Message + thing, Counter = 0 }));
}
}

internal class Message
{
public string Value { get; set; }
public long Counter { get; set; }
}

internal class GetMessage
{
public static readonly GetMessage Instance = new();

private GetMessage()
{
}
}

internal class InjectedService
{
public string Message => "I was injected";
}

internal class CustomMailbox : UnboundedPriorityMailbox
{
public CustomMailbox(Settings settings, Config config) : base(settings, config)
{
}

protected override int PriorityGenerator(object message)
{
return message switch
{
string => 1,
int => 2,
_ => 3
};
}
}

internal class AkkaService : IHostedService
{
public const string CustomMailboxName = "custom-mailbox";

private readonly Config _customMailboxHocon = $$"""
custom-mailbox {
mailbox-type = "{{typeof(CustomMailbox).AssemblyQualifiedName}}"
}
""";

public ActorSystem ActorSystem { get; private set; }

private readonly IServiceProvider _serviceProvider;

public AkkaService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}

public Task StartAsync(CancellationToken cancellationToken)
{
var setup = DependencyResolverSetup.Create(_serviceProvider)
.And(BootstrapSetup.Create().WithConfig(_customMailboxHocon.WithFallback(TestKitBase.DefaultConfig)));

ActorSystem = ActorSystem.Create("TestSystem", setup);
return Task.CompletedTask;
}

public async Task StopAsync(CancellationToken cancellationToken = default)
{
await ActorSystem.Terminate();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// -----------------------------------------------------------------------
// <copyright file="DiPropsSpecs.cs" company="Akka.NET Project">
// Copyright (C) 2009-2024 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2024 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Configuration;
using Akka.Dispatch;
using Akka.Util.Internal;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
using Xunit.Abstractions;

namespace Akka.DependencyInjection.Tests;

public class DiPropsSpecs : IAsyncLifetime
{
private readonly IServiceProvider _serviceProvider;
private readonly AkkaService _akkaService;
private readonly ITestOutputHelper _output;
private TestKit.Xunit2.TestKit _testKit;

public DiPropsSpecs(ITestOutputHelper output)
{
_output = output;
var services = new ServiceCollection()
.AddSingleton<InjectedService>()
.AddSingleton<AkkaService>()
.AddHostedService<AkkaService>();

_serviceProvider = services.BuildServiceProvider();
_akkaService = _serviceProvider.GetRequiredService<AkkaService>();
}


[Fact(DisplayName = "DI should work with custom mailbox")]
public async Task ShouldWorkWithCustomMailbox()
{
var system = _serviceProvider.GetRequiredService<AkkaService>().ActorSystem;
var resolver = DependencyResolver.For(system);
const string thing = "foobar";
var props = resolver.Props<InjectedEchoActor>(thing).WithMailbox(AkkaService.CustomMailboxName);
var actor = system.ActorOf(props, "testDIActorWithCustomMailbox");

var probe = _testKit.CreateTestProbe(system);
actor.Tell(1, probe);
actor.Tell("test", probe);
var result1 = await probe.ExpectMsgAsync<Message>();
result1.Value.Should().Be("I was injected" + thing);
var result2 = await probe.ExpectMsgAsync<Message>();
result2.Value.Should().Be("I was injected" + thing);

// Verify that the custom mailbox was used
var actorRef = (RepointableActorRef)actor;
actorRef.MailboxType.GetType().Should().Be(typeof(CustomMailbox));
}

public async Task InitializeAsync()
{
await _akkaService.StartAsync(default);
_testKit = new TestKit.Xunit2.TestKit(_akkaService.ActorSystem, _output);
}

public async Task DisposeAsync()
{
await _akkaService.StopAsync();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Event;
using Akka.Routing;
using Akka.TestKit;
using Akka.Util.Internal;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Xunit;
using Xunit.Abstractions;

Expand Down Expand Up @@ -131,60 +127,5 @@ public async Task DisposeAsync()
{
await _akkaService.StopAsync();
}

internal class TestDiActor : ReceiveActor
{
public static readonly AtomicCounter Counter = new(0);

public TestDiActor(InjectedService injected)
{
long count = Counter.GetAndIncrement();
Receive<GetMessage>(_ => Sender.Tell(new Message{Value = injected.Message, Counter = count}));
}
}

internal class Message
{
public string Value { get; set; }
public long Counter { get; set; }
}

internal class GetMessage
{
public static readonly GetMessage Instance = new();
private GetMessage()
{ }
}

internal class InjectedService
{
public string Message => "I was injected";
}

internal class AkkaService : IHostedService
{
public ActorSystem ActorSystem { get; private set; }

private readonly IServiceProvider _serviceProvider;

public AkkaService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}

public Task StartAsync(CancellationToken cancellationToken)
{
var setup = DependencyResolverSetup.Create(_serviceProvider)
.And(BootstrapSetup.Create().WithConfig(TestKitBase.DefaultConfig));

ActorSystem = ActorSystem.Create("TestSystem", setup);
return Task.CompletedTask;
}

public async Task StopAsync(CancellationToken cancellationToken = default)
{
await ActorSystem.Terminate();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tests.MultiNode")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tools")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.DependencyInjection")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.DependencyInjection.Tests")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.DistributedData")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Docs.Tests")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.MultiNodeTestRunner.Shared.Tests")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tests.MultiNode")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tools")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.DependencyInjection")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.DependencyInjection.Tests")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.DistributedData")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Docs.Tests")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.MultiNodeTestRunner.Shared.Tests")]
Expand Down
1 change: 1 addition & 0 deletions src/core/Akka/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@
[assembly: InternalsVisibleTo("Akka.Persistence.TCK")]
[assembly: InternalsVisibleTo("Akka.DistributedData")]
[assembly: InternalsVisibleTo("Akka.DependencyInjection")]
[assembly: InternalsVisibleTo("Akka.DependencyInjection.Tests")]

0 comments on commit 1f448e9

Please sign in to comment.