Skip to content

Commit

Permalink
Merge pull request #5456 from Arkatufus/master
Browse files Browse the repository at this point in the history
Version 1.4.31 Release
  • Loading branch information
Arkatufus committed Dec 20, 2021
2 parents 594b1ba + 47e39e2 commit c795dee
Show file tree
Hide file tree
Showing 24 changed files with 399 additions and 279 deletions.
18 changes: 16 additions & 2 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
#### 1.4.30 December 13 2021 ####
#### 1.4.31 December 20 2021 ####
Akka.NET v1.4.30 is a minor release that contains some bug fixes.

Akka.NET v1.4.30 contained a breaking change that broke binary compatibility with all Akka.DI plugins.
Even though those plugins are deprecated that change is not compatible with our SemVer standards
and needed to be reverted. We regret the error.

Bug fixes:
* [Akka: Reverted Props code refactor](https://github.com/akkadotnet/akka.net/pull/5454)

| COMMITS | LOC+ | LOC- | AUTHOR |
| --- | --- | --- | --- |
| 1 | 9 | 2 | Gregorius Soedharmo |

#### 1.4.30 December 20 2021 ####
Akka.NET v1.4.30 is a minor release that contains some enhancements for Akka.Streams and some bug fixes.

New features:
* [Akka: Added StringBuilder pooling in NewtonsoftJsonSerializer](https://github.com/akkadotnet/akka.net/pull/4929)
* [Akka.TestKint: Added InverseFishForMessage](https://github.com/akkadotnet/akka.net/pull/5430)
* [Akka.TestKit: Added InverseFishForMessage](https://github.com/akkadotnet/akka.net/pull/5430)
* [Akka.Streams: Added custom frame sized Flow to Framing](https://github.com/akkadotnet/akka.net/pull/5444)
* [Akka.Streams: Allow Stream to be consumed as IAsyncEnumerable](https://github.com/akkadotnet/akka.net/pull/4742)

Expand Down
33 changes: 19 additions & 14 deletions src/contrib/dependencyinjection/Akka.DI.Core/DIActorProducer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ namespace Akka.DI.Core
/// <summary>
/// This class represents an actor creation strategy that uses dependency injection (DI) to resolve and instantiate actors based on their type.
/// </summary>
public sealed class DIActorProducer : IIndirectActorProducerWithActorType
public class DIActorProducer : IIndirectActorProducer
{
private readonly IDependencyResolver _dependencyResolver;
private readonly Type _actorType;
private readonly Func<ActorBase> _actorFactory;
private IDependencyResolver dependencyResolver;
private Type actorType;

public Type ActorType => _actorType;
readonly Func<ActorBase> actorFactory;

/// <summary>
/// Initializes a new instance of the <see cref="DIActorProducer"/> class.
Expand All @@ -34,20 +33,26 @@ public DIActorProducer(IDependencyResolver dependencyResolver, Type actorType)
if (dependencyResolver == null) throw new ArgumentNullException(nameof(dependencyResolver), $"DIActorProducer requires {nameof(dependencyResolver)} to be provided");
if (actorType == null) throw new ArgumentNullException(nameof(actorType), $"DIActorProducer requires {nameof(actorType)} to be provided");

_dependencyResolver = dependencyResolver;
_actorType = actorType;
_actorFactory = dependencyResolver.CreateActorFactory(actorType);
this.dependencyResolver = dependencyResolver;
this.actorType = actorType;
this.actorFactory = dependencyResolver.CreateActorFactory(actorType);
}


/// <summary>
/// Retrieves the type of the actor to produce.
/// </summary>
public Type ActorType
{
get { return this.actorType; }
}

/// <summary>
/// Creates an actor based on the container's implementation specific actor factory.
/// </summary>
/// <returns>An actor created by the container.</returns>
public ActorBase Produce(Props props)
public ActorBase Produce()
{
if (props.Type != _actorType)
throw new InvalidOperationException($"invalid actor type {props.Type}");
return _actorFactory();
return actorFactory();
}

/// <summary>
Expand All @@ -56,7 +61,7 @@ public ActorBase Produce(Props props)
/// <param name="actor">The actor to remove from the container.</param>
public void Release(ActorBase actor)
{
_dependencyResolver.Release(actor);
dependencyResolver.Release(actor);
}
}
}
2 changes: 1 addition & 1 deletion src/contrib/dependencyinjection/Akka.DI.Core/DIExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void Initialize(IDependencyResolver dependencyResolver)
/// <returns>A <see cref="Akka.Actor.Props"/> configuration object for the given actor type.</returns>
public Props Props(Type actorType)
{
return Akka.Actor.Props.CreateBy(new DIActorProducer(dependencyResolver, actorType), actorType);
return new Props(typeof(DIActorProducer), new object[] { dependencyResolver, actorType });
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public static ServiceProvider For(ActorSystem actorSystem)
/// <returns>A new <see cref="Akka.Actor.Props"/> instance which uses DI internally.</returns>
public Props Props<T>(params object[] args) where T : ActorBase
{
return Akka.Actor.Props.CreateBy(new ServiceProviderActorProducer(Provider), typeof(T), args);
return Akka.Actor.Props.CreateBy(new ServiceProviderActorProducer<T>(Provider, args));
}
}

Expand Down Expand Up @@ -93,23 +93,43 @@ public override ServiceProvider CreateExtension(ExtendedActorSystem system)
///
/// Used to create actors via the <see cref="ActivatorUtilities"/>.
/// </summary>
internal sealed class ServiceProviderActorProducer : IIndirectActorProducer
internal class ServiceProviderActorProducer : IIndirectActorProducer
{
private readonly IServiceProvider _provider;

public ServiceProviderActorProducer(IServiceProvider provider)
private readonly object[] _args;

public ServiceProviderActorProducer(IServiceProvider provider, Type actorType, object[] args)
{
_provider = provider;
_args = args;
ActorType = actorType;
}

public ActorBase Produce(Props props)
public ActorBase Produce()
{
return (ActorBase)ActivatorUtilities.CreateInstance(_provider, props.Type, props.Arguments);
return (ActorBase)ActivatorUtilities.CreateInstance(_provider, ActorType, _args);
}

public Type ActorType { get; }

public void Release(ActorBase actor)
{
// no-op
}
}

/// <summary>
/// INTERNAL API
///
/// Used to create actors via the <see cref="ActivatorUtilities"/>.
/// </summary>
/// <typeparam name="TActor">the actor type</typeparam>
internal class ServiceProviderActorProducer<TActor> : ServiceProviderActorProducer where TActor:ActorBase
{

public ServiceProviderActorProducer(IServiceProvider provider, object[] args)
: base(provider, typeof(TActor), args)
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,11 @@ namespace Akka.DependencyInjection
/// </summary>
public class ServiceProviderDependencyResolver : IDependencyResolver
{
private readonly ServiceProviderActorProducer _producer;

public IServiceProvider ServiceProvider { get; }

public ServiceProviderDependencyResolver(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
_producer = new ServiceProviderActorProducer(ServiceProvider);
}

public IResolverScope CreateScope()
Expand All @@ -46,7 +43,7 @@ public object GetService(Type type)
public Props Props(Type type, params object[] args)
{
if(typeof(ActorBase).IsAssignableFrom(type))
return Akka.Actor.Props.CreateBy(_producer, type, args);
return Akka.Actor.Props.CreateBy(new ServiceProviderActorProducer(ServiceProvider, type, args));
throw new ArgumentException(nameof(type), $"[{type}] does not implement Akka.Actor.ActorBase.");
}

Expand All @@ -57,7 +54,7 @@ public Props Props(Type type)

public Props Props<T>(params object[] args) where T : ActorBase
{
return Akka.Actor.Props.CreateBy(_producer, typeof(T), args);
return Akka.Actor.Props.CreateBy(new ServiceProviderActorProducer<T>(ServiceProvider, args));
}
}

Expand Down
37 changes: 20 additions & 17 deletions src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,7 @@ namespace Akka.Actor
protected override void PreStart() { }
protected override bool Receive(object message) { }
}
public sealed class HashedWheelTimerScheduler : Akka.Actor.SchedulerBase, Akka.Actor.IDateTimeOffsetNowTimeProvider, Akka.Actor.ITimeProvider, System.IDisposable
public class HashedWheelTimerScheduler : Akka.Actor.SchedulerBase, Akka.Actor.IDateTimeOffsetNowTimeProvider, Akka.Actor.ITimeProvider, System.IDisposable
{
public HashedWheelTimerScheduler(Akka.Configuration.Config scheduler, Akka.Event.ILoggingAdapter log) { }
public override System.TimeSpan HighResMonotonicClock { get; }
Expand Down Expand Up @@ -1071,14 +1071,10 @@ namespace Akka.Actor
void Send(Akka.Actor.IActorRef target, object message);
}
public interface IIndirectActorProducer
{
Akka.Actor.ActorBase Produce(Akka.Actor.Props props);
void Release(Akka.Actor.ActorBase actor);
}
[System.ObsoleteAttribute("Do not use this interface")]
public interface IIndirectActorProducerWithActorType : Akka.Actor.IIndirectActorProducer
{
System.Type ActorType { get; }
Akka.Actor.ActorBase Produce();
void Release(Akka.Actor.ActorBase actor);
}
public interface IInternalActor
{
Expand Down Expand Up @@ -1413,29 +1409,31 @@ namespace Akka.Actor
public System.Exception RestartException { get; }
public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class Props : Akka.Util.ISurrogated, System.IEquatable<Akka.Actor.Props>
public class Props : Akka.Util.ISurrogated, System.IEquatable<Akka.Actor.Props>
{
public static readonly Akka.Actor.Props None;
protected Props() { }
protected Props(Akka.Actor.Props copy) { }
public Props(System.Type type, object[] args) { }
public Props(System.Type type) { }
public Props(System.Type type, Akka.Actor.SupervisorStrategy supervisorStrategy, System.Collections.Generic.IEnumerable<object> args) { }
public Props(System.Type type, Akka.Actor.SupervisorStrategy supervisorStrategy, params object[] args) { }
public Props(Akka.Actor.Deploy deploy, System.Type type, System.Collections.Generic.IEnumerable<object> args) { }
public Props(Akka.Actor.Deploy deploy, System.Type type, params object[] args) { }
public object[] Arguments { get; }
public Akka.Actor.Deploy Deploy { get; }
public Akka.Actor.Deploy Deploy { get; set; }
[Newtonsoft.Json.JsonIgnoreAttribute()]
public string Dispatcher { get; }
public static Akka.Actor.Props Empty { get; }
[Newtonsoft.Json.JsonIgnoreAttribute()]
public string Mailbox { get; }
[Newtonsoft.Json.JsonIgnoreAttribute()]
public Akka.Routing.RouterConfig RouterConfig { get; }
public Akka.Actor.SupervisorStrategy SupervisorStrategy { get; }
public static Akka.Actor.Props Terminated { get; }
public Akka.Actor.SupervisorStrategy SupervisorStrategy { get; set; }
[Newtonsoft.Json.JsonIgnoreAttribute()]
public System.Type Type { get; }
public string TypeName { get; }
protected virtual Akka.Actor.Props Copy() { }
public static Akka.Actor.Props Create<TActor>(System.Linq.Expressions.Expression<System.Func<TActor>> factory, Akka.Actor.SupervisorStrategy supervisorStrategy = null)
where TActor : Akka.Actor.ActorBase { }
public static Akka.Actor.Props Create<TActor>(params object[] args)
Expand All @@ -1445,20 +1443,20 @@ namespace Akka.Actor
public static Akka.Actor.Props Create(System.Type type, params object[] args) { }
[System.ObsoleteAttribute("Do not use this method. Call CreateBy(IIndirectActorProducer, params object[] arg" +
"s) instead")]
public static Akka.Actor.Props CreateBy<TProducer>(System.Type type, params object[] args)
public static Akka.Actor.Props CreateBy<TProducer>(params object[] args)
where TProducer : class, Akka.Actor.IIndirectActorProducer { }
public static Akka.Actor.Props CreateBy(Akka.Actor.IIndirectActorProducer producer, System.Type type, params object[] args) { }
public static Akka.Actor.Props CreateBy(Akka.Actor.IIndirectActorProducer producer, params object[] args) { }
public bool Equals(Akka.Actor.Props other) { }
public override bool Equals(object obj) { }
public override int GetHashCode() { }
public Akka.Actor.ActorBase NewActor() { }
public virtual Akka.Actor.ActorBase NewActor() { }
public Akka.Util.ISurrogate ToSurrogate(Akka.Actor.ActorSystem system) { }
public Akka.Actor.Props WithDeploy(Akka.Actor.Deploy deploy) { }
public Akka.Actor.Props WithDispatcher(string dispatcher) { }
public Akka.Actor.Props WithMailbox(string mailbox) { }
public Akka.Actor.Props WithRouter(Akka.Routing.RouterConfig routerConfig) { }
public Akka.Actor.Props WithSupervisorStrategy(Akka.Actor.SupervisorStrategy supervisorStrategy) { }
public sealed class PropsSurrogate : Akka.Util.ISurrogate
public class PropsSurrogate : Akka.Util.ISurrogate
{
public PropsSurrogate() { }
public object[] Arguments { get; set; }
Expand Down Expand Up @@ -1785,6 +1783,11 @@ namespace Akka.Actor
public override int GetHashCode() { }
public override string ToString() { }
}
public class TerminatedProps : Akka.Actor.Props
{
public TerminatedProps() { }
public override Akka.Actor.ActorBase NewActor() { }
}
[System.ObsoleteAttribute("TypedActor in its current shape will be removed in v1.5")]
public abstract class TypedActor : Akka.Actor.ActorBase
{
Expand Down Expand Up @@ -5033,7 +5036,7 @@ namespace Akka.Util
protected Resolve() { }
public abstract System.Type ActorType { get; }
protected static Akka.Util.IResolver Resolver { get; }
public abstract Akka.Actor.ActorBase Produce(Akka.Actor.Props props);
public abstract Akka.Actor.ActorBase Produce();
public void Release(Akka.Actor.ActorBase actor) { }
public static void SetResolver(Akka.Util.IResolver resolver) { }
}
Expand All @@ -5043,7 +5046,7 @@ namespace Akka.Util
public Resolve(params object[] args) { }
public override System.Type ActorType { get; }
public object[] Arguments { get; }
public override Akka.Actor.ActorBase Produce(Akka.Actor.Props props) { }
public override Akka.Actor.ActorBase Produce() { }
}
public class static Result
{
Expand Down
2 changes: 1 addition & 1 deletion src/core/Akka.FSharp.Tests/ApiTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ let ``cannot spawn actor with simple expr args from expression`` () =
let system = Configuration.load() |> System.create "test"
// this formulation is supported in FsApi's expression evaluator, however the checks in Props.Create
// do not support this, so we test that we can evaluate this but not actually run it, as a proof of concept
Assert.Throws<ArgumentException>(fun () ->
Assert.Throws<InvalidCastException>(fun () ->
let actor = spawnObj system "test-actor" <@ fun () ->
let arg1 = 1
let arg2 = true
Expand Down
9 changes: 3 additions & 6 deletions src/core/Akka.Remote.Tests/RemotingSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ public void Remoting_must_create_by_IndirectActorProducer()
{
try
{
var r = Sys.ActorOf(Props.CreateBy(new TestResolver<Echo2>(), typeof(Echo2)), "echo");
var r = Sys.ActorOf(Props.CreateBy(new TestResolver<Echo2>()), "echo");
Assert.Equal("akka.test://remote-sys@localhost:12346/remote/akka.test/RemotingSpec@localhost:12345/user/echo", r.Path.ToString());
}
finally
Expand All @@ -426,7 +426,7 @@ public void Remoting_must_create_by_IndirectActorProducer_and_ping()
{
try
{
var r = Sys.ActorOf(Props.CreateBy(new TestResolver<Echo2>(), typeof(Echo2)), "echo");
var r = Sys.ActorOf(Props.CreateBy(new TestResolver<Echo2>()), "echo");
Assert.Equal("akka.test://remote-sys@localhost:12346/remote/akka.test/RemotingSpec@localhost:12345/user/echo", r.Path.ToString());
r.Tell("ping", TestActor);
ExpectMsg(("pong", TestActor), TimeSpan.FromSeconds(1.5));
Expand Down Expand Up @@ -911,11 +911,8 @@ public TestResolver(params object[] args)
_args = args;
}

public ActorBase Produce(Props props)
public ActorBase Produce()
{
if (props.Type != ActorType)
throw new InvalidOperationException("invalid actor type");

return (ActorBase)Activator.CreateInstance(ActorType, _args);
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/Akka.Remote/RemoteActorRefProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public ActorPath RootPath
public Deployer Deployer { get; protected set; }

/// <inheritdoc/>
public Address DefaultAddress { get { return Transport?.DefaultAddress; } }
public Address DefaultAddress { get { return Transport.DefaultAddress; } }

private Information _serializationInformationCache;

Expand Down
2 changes: 1 addition & 1 deletion src/core/Akka.Streams.Tests/Dsl/FutureFlattenSourceSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ public void TaskSource_must_fail_when_the_task_source_materialization_fails()
var (innerSourceMat, outerSinkMat) = Source.FromTaskSource(inner).ToMaterialized(Sink.Seq<int>(), Keep.Both).Run(_materializer);
// wait until the underlying tasks are completed
AwaitCondition(() => outerSinkMat.IsFaulted && innerSourceMat.IsFaulted, TimeSpan.FromSeconds(1), TimeSpan.FromMilliseconds(100));
Thread.Sleep(100);
outerSinkMat.Exception.Flatten().InnerException.Should().Be(new TestException("INNER_FAILED"));
innerSourceMat.Exception.Flatten().InnerException.Should().Be(new TestException("INNER_FAILED"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,13 @@ public void SpecifiedNumbersOfExceptionsCanBeIntercepted()
[Fact]
public void ShouldFailIfMoreExceptionsThenSpecifiedAreLogged()
{
//todo fix logging race
var exception = XAssert.Throws<TrueException>(() =>
{
EventFilter.Exception<SomeException>().Expect(2, () =>
{
Log.Error(new SomeException(), "whatever");
Log.Error(new SomeException(), "whatever");
Log.Error(new SomeException(), "whatever");
});
});

}));
Assert.Contains("1 message too many", exception.Message, StringComparison.OrdinalIgnoreCase);
}

Expand Down
Loading

0 comments on commit c795dee

Please sign in to comment.