diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 524e5fd4bfd..71ee73ab0cc 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,3 +1,27 @@
+#### 1.4.20 May 12 2021 ####
+**Maintenance Release for Akka.NET 1.4**
+
+Akka.NET v1.4.20 is a minor release that includes some bug fixes and improvements to Akka.NET.
+
+* [Akka: Fixed some `internal-dispatcher` usages ](https://github.com/akkadotnet/akka.net/pull/4995)
+* [Akka: Remove restrictions required by netstandard 1.x but available in 2.0 ](https://github.com/akkadotnet/akka.net/pull/3790)
+* [Akka: Prevent loggers to throw `FormatException` and show a friendly message instead. ](https://github.com/akkadotnet/akka.net/pull/4998)
+* [Akka.Persistence.Sql.Common: Some persistent actors are stuck with `RecoveryTimedOutException` after circuit breaker opens](https://github.com/akkadotnet/akka.net/issues/4265)
+* [Akka.Persistence.Sql.Common: marking Akka.Persistence.Sql.Common as `beta` for v1.4.20](https://github.com/akkadotnet/akka.net/pull/5006)
+* [Akka.Remote: `Akka.Remote.Serialization.PrimitiveSerializers` needs cross platform compatibility](https://github.com/akkadotnet/akka.net/issues/4986)
+* [Akka.Streams: Fixed `QueueSource.PostStop` and added a missing test case](https://github.com/akkadotnet/akka.net/pull/4991)
+* [Akka.Cluster.Sharding: Reduce sharding warnings when there are no buffered messages](https://github.com/akkadotnet/akka.net/pull/5003)
+
+To see the [full set of fixes in Akka.NET v1.4.20, please see the milestone on Github](https://github.com/akkadotnet/akka.net/milestone/50).
+
+| COMMITS | LOC+ | LOC- | AUTHOR |
+| --- | --- | --- | --- |
+| 4 | 677 | 316 | Gregorius Soedharmo |
+| 3 | 3 | 3 | dependabot[bot] |
+| 3 | 101 | 44 | Ismael Hamed |
+| 2 | 5 | 0 | Aaron Stannard |
+| 1 | 625 | 675 | Matthew Heaton |
+
#### 1.4.19 April 28 2021 ####
**Maintenance Release for Akka.NET 1.4**
diff --git a/src/common.props b/src/common.props
index bcf07da8e3f..809e3c7a451 100644
--- a/src/common.props
+++ b/src/common.props
@@ -14,13 +14,13 @@
0.10.1
13.0.1
2.0.1
- 3.15.8
+ 3.16.0
netcoreapp3.1
net5.0
net471
netstandard2.0
5.10.3
- 2.15.2
+ 2.15.3
2.0.3
4.7.0
akka;actors;actor model;Akka;concurrency
diff --git a/src/contrib/cluster/Akka.Cluster.Sharding.Tests.MultiNode/Akka.Cluster.Sharding.Tests.MultiNode.csproj b/src/contrib/cluster/Akka.Cluster.Sharding.Tests.MultiNode/Akka.Cluster.Sharding.Tests.MultiNode.csproj
index 5e3524af359..377aa9d05d8 100644
--- a/src/contrib/cluster/Akka.Cluster.Sharding.Tests.MultiNode/Akka.Cluster.Sharding.Tests.MultiNode.csproj
+++ b/src/contrib/cluster/Akka.Cluster.Sharding.Tests.MultiNode/Akka.Cluster.Sharding.Tests.MultiNode.csproj
@@ -25,14 +25,6 @@
-
- $(DefineConstants);
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/cluster/Akka.Cluster.Sharding.Tests.MultiNode/AsyncWriteProxyEx.cs b/src/contrib/cluster/Akka.Cluster.Sharding.Tests.MultiNode/AsyncWriteProxyEx.cs
index c7faf070f9e..b84c623aff7 100644
--- a/src/contrib/cluster/Akka.Cluster.Sharding.Tests.MultiNode/AsyncWriteProxyEx.cs
+++ b/src/contrib/cluster/Akka.Cluster.Sharding.Tests.MultiNode/AsyncWriteProxyEx.cs
@@ -43,7 +43,6 @@ public AsyncReplayTimeoutException(string message)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -53,7 +52,6 @@ protected AsyncReplayTimeoutException(SerializationInfo info, StreamingContext c
: base(info, context)
{
}
-#endif
}
///
diff --git a/src/contrib/cluster/Akka.Cluster.Sharding.Tests/Akka.Cluster.Sharding.Tests.csproj b/src/contrib/cluster/Akka.Cluster.Sharding.Tests/Akka.Cluster.Sharding.Tests.csproj
index de4079d687c..e3331ead973 100644
--- a/src/contrib/cluster/Akka.Cluster.Sharding.Tests/Akka.Cluster.Sharding.Tests.csproj
+++ b/src/contrib/cluster/Akka.Cluster.Sharding.Tests/Akka.Cluster.Sharding.Tests.csproj
@@ -27,14 +27,6 @@
-
- $(DefineConstants);SERIALIZABLE
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/cluster/Akka.Cluster.Sharding/Akka.Cluster.Sharding.csproj b/src/contrib/cluster/Akka.Cluster.Sharding/Akka.Cluster.Sharding.csproj
index 9a89df9c92e..8234137e52c 100644
--- a/src/contrib/cluster/Akka.Cluster.Sharding/Akka.Cluster.Sharding.csproj
+++ b/src/contrib/cluster/Akka.Cluster.Sharding/Akka.Cluster.Sharding.csproj
@@ -18,10 +18,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/cluster/Akka.Cluster.Sharding/ShardRegion.cs b/src/contrib/cluster/Akka.Cluster.Sharding/ShardRegion.cs
index efda79c5404..784271accba 100644
--- a/src/contrib/cluster/Akka.Cluster.Sharding/ShardRegion.cs
+++ b/src/contrib/cluster/Akka.Cluster.Sharding/ShardRegion.cs
@@ -664,11 +664,25 @@ private void Register()
? $"Coordinator [{MembersByAge.First()}] is unreachable."
: $"Coordinator [{MembersByAge.First()}] is reachable.";
- Log.Warning("{0}: Trying to register to coordinator at [{1}], but no acknowledgement. Total [{2}] buffered messages. [{3}]",
- TypeName,
- string.Join(", ", actorSelections.Select(i => i.PathString)),
- TotalBufferSize,
- coordinatorMessage);
+ var bufferSize = ShardBuffers.Count;
+ if (bufferSize > 0)
+ {
+ if (Log.IsWarningEnabled)
+ {
+ Log.Warning("{0}: Trying to register to coordinator at [{1}], but no acknowledgement. Total [{2}] buffered messages. [{3}]",
+ TypeName,
+ string.Join(", ", actorSelections.Select(i => i.PathString)),
+ TotalBufferSize,
+ coordinatorMessage);
+ }
+ }
+ else if (Log.IsDebugEnabled)
+ {
+ Log.Debug("{0}: Trying to register to coordinator at [{1}], but no acknowledgement. No buffered messages yet. [{2}]",
+ TypeName,
+ string.Join(", ", actorSelections.Select(i => i.PathString)),
+ coordinatorMessage);
+ }
}
else
{
@@ -678,8 +692,17 @@ private void Register()
? "Has Cluster Sharding been started on every node and nodes been configured with the correct role(s)?"
: "Probably, no seed-nodes configured and manual cluster join not performed?";
- Log.Warning("{0}: No coordinator found to register. {1} Total [{2}] buffered messages.",
- TypeName, possibleReason, TotalBufferSize);
+ var bufferSize = ShardBuffers.Count;
+ if (bufferSize > 0)
+ {
+ Log.Warning("{0}: No coordinator found to register. {1} Total [{2}] buffered messages.",
+ TypeName, possibleReason, TotalBufferSize);
+ }
+ else
+ {
+ Log.Debug("{0}: No coordinator found to register. {1} No buffered messages yet.",
+ TypeName, possibleReason);
+ }
}
}
}
diff --git a/src/contrib/cluster/Akka.Cluster.Tools.Tests.MultiNode/Akka.Cluster.Tools.Tests.MultiNode.csproj b/src/contrib/cluster/Akka.Cluster.Tools.Tests.MultiNode/Akka.Cluster.Tools.Tests.MultiNode.csproj
index 6317a468a79..466bb53fc8a 100644
--- a/src/contrib/cluster/Akka.Cluster.Tools.Tests.MultiNode/Akka.Cluster.Tools.Tests.MultiNode.csproj
+++ b/src/contrib/cluster/Akka.Cluster.Tools.Tests.MultiNode/Akka.Cluster.Tools.Tests.MultiNode.csproj
@@ -19,10 +19,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/cluster/Akka.Cluster.Tools.Tests/Akka.Cluster.Tools.Tests.csproj b/src/contrib/cluster/Akka.Cluster.Tools.Tests/Akka.Cluster.Tools.Tests.csproj
index 664c232ced6..5ed0131226e 100644
--- a/src/contrib/cluster/Akka.Cluster.Tools.Tests/Akka.Cluster.Tools.Tests.csproj
+++ b/src/contrib/cluster/Akka.Cluster.Tools.Tests/Akka.Cluster.Tools.Tests.csproj
@@ -19,14 +19,6 @@
-
- $(DefineConstants);SERIALIZABLE
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/cluster/Akka.Cluster.Tools.Tests/Singleton/ClusterSingletonLeaseSpec.cs b/src/contrib/cluster/Akka.Cluster.Tools.Tests/Singleton/ClusterSingletonLeaseSpec.cs
index 06750f8ae88..cd9ca2522a2 100644
--- a/src/contrib/cluster/Akka.Cluster.Tools.Tests/Singleton/ClusterSingletonLeaseSpec.cs
+++ b/src/contrib/cluster/Akka.Cluster.Tools.Tests/Singleton/ClusterSingletonLeaseSpec.cs
@@ -117,7 +117,7 @@ public ClusterSingletonLeaseSpec() : base(ConfigurationFactory.ParseString(@"
private ClusterSingletonManagerSettings NextSettings() => ClusterSingletonManagerSettings.Create(Sys).WithSingletonName(NextName());
- private string LeaseNameFor(ClusterSingletonManagerSettings settings) => $"AkkaSpec-singleton-akka://AkkaSpec/user/{settings.SingletonName}";
+ private string LeaseNameFor(ClusterSingletonManagerSettings settings) => $"{Sys.Name}-singleton-akka://{Sys.Name}/user/{settings.SingletonName}";
[Fact]
public void ClusterSingleton_with_lease_should_not_start_until_lease_is_available()
diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Akka.Cluster.Tools.csproj b/src/contrib/cluster/Akka.Cluster.Tools/Akka.Cluster.Tools.csproj
index 4b03bb18282..dc65eda72f2 100644
--- a/src/contrib/cluster/Akka.Cluster.Tools/Akka.Cluster.Tools.csproj
+++ b/src/contrib/cluster/Akka.Cluster.Tools/Akka.Cluster.Tools.csproj
@@ -15,10 +15,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManager.cs b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManager.cs
index 4461edfa6f8..679c2d6c69b 100644
--- a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManager.cs
+++ b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManager.cs
@@ -525,7 +525,6 @@ public sealed class ClusterSingletonManagerIsStuckException : AkkaException
/// The message that describes the error.
public ClusterSingletonManagerIsStuckException(string message) : base(message) { }
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -534,7 +533,6 @@ public ClusterSingletonManagerIsStuckException(string message) : base(message) {
public ClusterSingletonManagerIsStuckException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
}
///
diff --git a/src/contrib/cluster/Akka.DistributedData.Tests.MultiNode/Akka.DistributedData.Tests.MultiNode.csproj b/src/contrib/cluster/Akka.DistributedData.Tests.MultiNode/Akka.DistributedData.Tests.MultiNode.csproj
index 5f7445c71a1..205ab0ae536 100644
--- a/src/contrib/cluster/Akka.DistributedData.Tests.MultiNode/Akka.DistributedData.Tests.MultiNode.csproj
+++ b/src/contrib/cluster/Akka.DistributedData.Tests.MultiNode/Akka.DistributedData.Tests.MultiNode.csproj
@@ -24,10 +24,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/cluster/Akka.DistributedData.Tests/Akka.DistributedData.Tests.csproj b/src/contrib/cluster/Akka.DistributedData.Tests/Akka.DistributedData.Tests.csproj
index f1e12967f2b..f54d7a07fa8 100644
--- a/src/contrib/cluster/Akka.DistributedData.Tests/Akka.DistributedData.Tests.csproj
+++ b/src/contrib/cluster/Akka.DistributedData.Tests/Akka.DistributedData.Tests.csproj
@@ -20,10 +20,6 @@
-
- $(DefineConstants);SERIALIZABLE
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/cluster/Akka.DistributedData/Akka.DistributedData.csproj b/src/contrib/cluster/Akka.DistributedData/Akka.DistributedData.csproj
index 9169c811907..8927f87542e 100644
--- a/src/contrib/cluster/Akka.DistributedData/Akka.DistributedData.csproj
+++ b/src/contrib/cluster/Akka.DistributedData/Akka.DistributedData.csproj
@@ -14,9 +14,9 @@
-
- $(DefineConstants);CORECLR
-
+
+
+
$(DefineConstants);RELEASE
diff --git a/src/contrib/cluster/Akka.DistributedData/Durable/Messages.cs b/src/contrib/cluster/Akka.DistributedData/Durable/Messages.cs
index d4d85508434..52f24588f42 100644
--- a/src/contrib/cluster/Akka.DistributedData/Durable/Messages.cs
+++ b/src/contrib/cluster/Akka.DistributedData/Durable/Messages.cs
@@ -91,11 +91,9 @@ public LoadFailedException(string message, Exception cause) : base(message, caus
{
}
-#if SERIALIZATION
public LoadFailedException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
}
public sealed class DurableDataEnvelope : IReplicatorMessage, IEquatable
diff --git a/src/contrib/cluster/Akka.DistributedData/Replicator.Messages.cs b/src/contrib/cluster/Akka.DistributedData/Replicator.Messages.cs
index 4109982b925..e9800b7315c 100644
--- a/src/contrib/cluster/Akka.DistributedData/Replicator.Messages.cs
+++ b/src/contrib/cluster/Akka.DistributedData/Replicator.Messages.cs
@@ -997,6 +997,7 @@ public override bool Equals(object obj)
///
/// TBD
///
+ [Serializable]
public class DataDeletedException : Exception
{
///
@@ -1006,6 +1007,13 @@ public class DataDeletedException : Exception
public DataDeletedException(string message) : base(message)
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected DataDeletedException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
public interface IReplicatorMessage { }
diff --git a/src/contrib/dependencyinjection/Akka.DI.Core/Akka.DI.Core.csproj b/src/contrib/dependencyinjection/Akka.DI.Core/Akka.DI.Core.csproj
index c4e9bda2f64..c4c0ea24639 100644
--- a/src/contrib/dependencyinjection/Akka.DI.Core/Akka.DI.Core.csproj
+++ b/src/contrib/dependencyinjection/Akka.DI.Core/Akka.DI.Core.csproj
@@ -13,15 +13,11 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
-
+
diff --git a/src/contrib/dependencyinjection/Akka.DI.Core/Extensions.cs b/src/contrib/dependencyinjection/Akka.DI.Core/Extensions.cs
index 4d9ebc728aa..d8b3b732e30 100644
--- a/src/contrib/dependencyinjection/Akka.DI.Core/Extensions.cs
+++ b/src/contrib/dependencyinjection/Akka.DI.Core/Extensions.cs
@@ -11,9 +11,6 @@
using System.Reflection;
using Akka.Actor;
-#if CORECLR
-using Microsoft.Extensions.DependencyModel;
-#endif
namespace Akka.DI.Core
{
///
@@ -78,28 +75,7 @@ public static Type GetTypeValue(this string typeName)
/// The list of loaded assemblies
private static IEnumerable GetLoadedAssemblies()
{
-#if APPDOMAIN
return AppDomain.CurrentDomain.GetAssemblies();
-#elif CORECLR
- var assemblies = new List();
- var dependencies = DependencyContext.Default.RuntimeLibraries;
- foreach (var library in dependencies)
- {
- try
- {
- var assembly = Assembly.Load(new AssemblyName(library.Name));
- assemblies.Add(assembly);
- }
- catch
- {
- //do nothing can't if can't load assembly
- }
- }
- return assemblies;
-#else
-#warning Method not implemented
- throw new NotImplementedException();
-#endif
}
}
}
diff --git a/src/contrib/dependencyinjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj b/src/contrib/dependencyinjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj
index 75e51a1cdb8..17377f73ee8 100644
--- a/src/contrib/dependencyinjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj
+++ b/src/contrib/dependencyinjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj
@@ -14,14 +14,6 @@
-
- $(DefineConstants);APPDOMAIN
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/persistence/Akka.Persistence.Query.Sql/Akka.Persistence.Query.Sql.csproj b/src/contrib/persistence/Akka.Persistence.Query.Sql/Akka.Persistence.Query.Sql.csproj
index 8c2fe06fc9d..a80b880462a 100644
--- a/src/contrib/persistence/Akka.Persistence.Query.Sql/Akka.Persistence.Query.Sql.csproj
+++ b/src/contrib/persistence/Akka.Persistence.Query.Sql/Akka.Persistence.Query.Sql.csproj
@@ -16,10 +16,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Akka.Persistence.Sql.Common.csproj b/src/contrib/persistence/Akka.Persistence.Sql.Common/Akka.Persistence.Sql.Common.csproj
index 47c45e97196..f45af5faf11 100644
--- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Akka.Persistence.Sql.Common.csproj
+++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Akka.Persistence.Sql.Common.csproj
@@ -7,6 +7,7 @@
$(NetStandardLibVersion)
$(AkkaPackageTags);persistence;eventsource;sql
true
+ beta
@@ -17,14 +18,10 @@
-
+
-
- $(DefineConstants);CORECLR;CONFIGURATION
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/BatchingSqlJournal.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/BatchingSqlJournal.cs
index 19f24f30044..36aeb315709 100644
--- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/BatchingSqlJournal.cs
+++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/BatchingSqlJournal.cs
@@ -13,6 +13,7 @@
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
+using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Akka.Actor;
@@ -22,6 +23,7 @@
using Akka.Persistence.Journal;
using Akka.Serialization;
using Akka.Util;
+using Akka.Util.Internal;
namespace Akka.Persistence.Sql.Common.Journal
{
@@ -256,14 +258,12 @@ protected BatchingSqlJournalSetup(Config config, QueryConfiguration namingConven
throw ConfigurationException.NullOrEmptyConfig();
var connectionString = config.GetString("connection-string", null);
-#if CONFIGURATION
if (string.IsNullOrWhiteSpace(connectionString))
{
connectionString = System.Configuration.ConfigurationManager
.ConnectionStrings[config.GetString("connection-string-name", "DefaultConnection")]?
.ConnectionString;
}
-#endif
if (string.IsNullOrWhiteSpace(connectionString))
throw new ConfigurationException("No connection string for Sql Event Journal was specified");
@@ -360,11 +360,13 @@ private sealed class ChunkExecutionFailure : IDeadLetterSuppression
{
public Exception Cause { get; }
public IJournalRequest[] Requests { get; }
+ public int ChunkId { get; }
- public ChunkExecutionFailure(Exception cause, IJournalRequest[] requests)
+ public ChunkExecutionFailure(Exception cause, IJournalRequest[] requests, int chunkId)
{
Cause = cause;
Requests = requests;
+ ChunkId = chunkId;
}
}
@@ -373,14 +375,12 @@ private sealed class BatchComplete
public readonly int ChunkId;
public readonly int OperationCount;
public readonly TimeSpan TimeSpent;
- public readonly Exception Cause;
- public BatchComplete(int chunkId, int operationCount, TimeSpan timeSpent, Exception cause = null)
+ public BatchComplete(int chunkId, int operationCount, TimeSpan timeSpent)
{
ChunkId = chunkId;
TimeSpent = timeSpent;
OperationCount = operationCount;
- Cause = cause;
}
}
@@ -532,11 +532,19 @@ public RequestChunk(int chunkId, IJournalRequest[] requests)
///
protected readonly ILoggingAdapter Log;
+ private readonly Queue<(IJournalRequest request, long id)>[] _buffers;
+
+ ///
+ /// Buffer for write requests that are waiting to be served when next DB connection will be released.
+ ///
+ private Queue<(IJournalRequest request, long id)> WriteBuffer => _buffers[0];
+
///
- /// Buffer for requests that are waiting to be served when next DB connection will be released.
- /// This object access is NOT thread safe.
+ /// Buffer for read requests that are waiting to be served when next DB connection will be released.
///
- protected readonly Queue Buffer;
+ private Queue<(IJournalRequest request, long id)> ReadBuffer => _buffers[1];
+
+ private readonly AtomicCounterLong _bufferIdCounter;
private readonly Dictionary> _persistenceIdSubscribers;
private readonly Dictionary> _tagSubscribers;
@@ -560,7 +568,13 @@ protected BatchingSqlJournal(BatchingSqlJournalSetup setup)
_newEventSubscriber = new HashSet();
_remainingOperations = Setup.MaxConcurrentOperations;
- Buffer = new Queue(Setup.MaxBatchSize);
+ _buffers = new[]
+ {
+ new Queue<(IJournalRequest, long)>(Setup.MaxBatchSize),
+ new Queue<(IJournalRequest, long)>(Setup.MaxBatchSize)
+ };
+ _bufferIdCounter = new AtomicCounterLong(0);
+
_serialization = Context.System.Serialization;
Log = Context.GetLogger();
_circuitBreaker = CircuitBreaker.Create(
@@ -733,31 +747,65 @@ protected sealed override bool Receive(object message)
private void FailChunkExecution(ChunkExecutionFailure message)
{
+ _remainingOperations++;
var cause = message.Cause;
- Log.Error(cause, "Failed to execute chunk for {0} requests", message.Requests.Length);
-
- foreach (var req in message.Requests)
+ Log.Error(cause, "An error occurred during event batch processing. ChunkId: [{0}], batched requests: [{1}]", message.ChunkId, message.Requests.Length);
+
+ foreach (var request in message.Requests)
{
- switch (req)
+ switch (request)
{
- case WriteMessages write:
- var atomicWriteCount = write.Messages.OfType().Count();
- write.PersistentActor.Tell(new WriteMessagesFailed(cause, atomicWriteCount));
+ case WriteMessages req:
+ {
+ var atomicWriteCount = req.Messages.OfType().Count();
+ var actorInstanceId = req.ActorInstanceId;
+ var aRef = req.PersistentActor;
+
+ aRef.Tell(new WriteMessagesFailed(cause, atomicWriteCount));
+ foreach (var envelope in req.Messages)
+ {
+ if (!(envelope is AtomicWrite write))
+ continue;
+
+ var writes = (IImmutableList)write.Payload;
+ foreach (var unadapted in writes)
+ {
+ if (cause is DbException)
+ {
+ // database-related exceptions should result in failure
+ aRef.Tell(new WriteMessageFailure(unadapted, cause, actorInstanceId), unadapted.Sender);
+ }
+ else
+ {
+ aRef.Tell(new WriteMessageRejected(unadapted, cause, actorInstanceId), unadapted.Sender);
+ }
+ }
+ }
break;
+ }
+
+ case DeleteMessagesTo delete:
+ delete.PersistentActor.Tell(new DeleteMessagesFailure(cause, delete.ToSequenceNr), ActorRefs.NoSender);
+ break;
+
case ReplayMessages replay:
replay.PersistentActor.Tell(new ReplayMessagesFailure(cause));
break;
- case DeleteMessagesTo delete:
- delete.PersistentActor.Tell(new DeleteMessagesFailure(cause, delete.ToSequenceNr));
- break;
+
case ReplayTaggedMessages replayTagged:
replayTagged.ReplyTo.Tell(new ReplayMessagesFailure(cause));
break;
+
case ReplayAllEvents replayAll:
replayAll.ReplyTo.Tell(new EventReplayFailure(cause));
break;
+
+ default:
+ throw new Exception($"Unknown persistence journal request type [{request.GetType()}]");
}
}
+
+ TryProcess();
}
#region subscriptions
@@ -829,10 +877,20 @@ private void NotifyPersistenceIdChanged(string persistenceId)
/// TBD
protected void BatchRequest(IJournalRequest message)
{
- if (Buffer.Count > Setup.MaxBufferSize)
+ if (WriteBuffer.Count + ReadBuffer.Count > Setup.MaxBufferSize)
+ {
OnBufferOverflow(message);
+ }
else
- Buffer.Enqueue(message);
+ {
+ var id = _bufferIdCounter.GetAndIncrement();
+ // Enqueue writes and delete operation requests into the write queue,
+ // else if they are query operations, enqueue them into the read queue
+ if (message is WriteMessages || message is DeleteMessagesTo)
+ WriteBuffer.Enqueue((message, id));
+ else
+ ReadBuffer.Enqueue((message, id));
+ }
TryProcess();
}
@@ -870,25 +928,28 @@ protected virtual void OnBufferOverflow(IJournalMessage request)
private void TryProcess()
{
- if (_remainingOperations > 0 && Buffer.Count > 0)
+ if (_remainingOperations > 0 && (WriteBuffer.Count > 0 || ReadBuffer.Count > 0))
{
_remainingOperations--;
var chunk = DequeueChunk(_remainingOperations);
var context = Context;
_circuitBreaker.WithCircuitBreaker(() => ExecuteChunk(chunk, context))
- .PipeTo(Self, failure: ex => new ChunkExecutionFailure(ex, chunk.Requests));
+ .PipeTo(Self, failure: ex => new ChunkExecutionFailure(ex, chunk.Requests, chunk.ChunkId));
}
}
private async Task ExecuteChunk(RequestChunk chunk, IActorContext context)
{
- Exception cause = null;
+ var writeResults = new Queue();
+ var isWriteOperation = false;
var stopwatch = new Stopwatch();
using (var connection = CreateConnection(Setup.ConnectionString))
{
await connection.OpenAsync();
+ // In the grand scheme of thing, using a transaction in an all read batch operation
+ // should not hurt performance by much, because it is done only once at the start.
using (var tx = connection.BeginTransaction(Setup.IsolationLevel))
using (var command = (TCommand)connection.CreateCommand())
{
@@ -897,21 +958,23 @@ private async Task ExecuteChunk(RequestChunk chunk, IActorContext
try
{
stopwatch.Start();
- for (int i = 0; i < chunk.Requests.Length; i++)
+ // This looks dangerous at a glance, but we have separated read and write operations
+ // in the DequeueChunk method.
+ foreach (var req in chunk.Requests)
{
- var req = chunk.Requests[i];
-
switch (req)
{
case WriteMessages msg:
- await HandleWriteMessages(msg, command);
- break;
- case ReplayMessages msg:
- await HandleReplayMessages(msg, command, context);
+ isWriteOperation = true;
+ writeResults.Enqueue(await HandleWriteMessages(msg, command));
break;
case DeleteMessagesTo msg:
+ isWriteOperation = true;
await HandleDeleteMessagesTo(msg, command);
break;
+ case ReplayMessages msg:
+ await HandleReplayMessages(msg, command, context);
+ break;
case ReplayTaggedMessages msg:
await HandleReplayTaggedMessages(msg, command);
break;
@@ -926,21 +989,19 @@ private async Task ExecuteChunk(RequestChunk chunk, IActorContext
break;
}
}
-
tx.Commit();
-
- if (CanPublish)
- {
- for (int i = 0; i < chunk.Requests.Length; i++)
- {
- context.System.EventStream.Publish(chunk.Requests[i]);
- }
- }
}
- catch (Exception e)
+ catch (Exception e1)
{
- cause = e;
- tx.Rollback();
+ try
+ {
+ tx.Rollback();
+ }
+ catch (Exception e2)
+ {
+ throw new AggregateException(e2, e1);
+ }
+ throw;
}
finally
{
@@ -949,7 +1010,33 @@ private async Task ExecuteChunk(RequestChunk chunk, IActorContext
}
}
- return new BatchComplete(chunk.ChunkId, chunk.Requests.Length, stopwatch.Elapsed, cause);
+ if (CanPublish)
+ {
+ foreach (var request in chunk.Requests)
+ {
+ context.System.EventStream.Publish(request);
+ }
+ }
+
+ if (isWriteOperation)
+ {
+ foreach (var request in chunk.Requests)
+ {
+ switch (request)
+ {
+ case WriteMessages _:
+ writeResults.Dequeue().FinalizeSuccess(this);
+ break;
+ case DeleteMessagesTo req:
+ req.PersistentActor.Tell(new DeleteMessagesSuccess(req.ToSequenceNr));
+ break;
+ default:
+ throw new Exception($"Unknown database write operation {request.GetType()}");
+ }
+ }
+ }
+
+ return new BatchComplete(chunk.ChunkId, chunk.Requests.Length, stopwatch.Elapsed);
}
protected virtual async Task HandleDeleteMessagesTo(DeleteMessagesTo req, TCommand command)
@@ -957,35 +1044,24 @@ protected virtual async Task HandleDeleteMessagesTo(DeleteMessagesTo req, TComma
var toSequenceNr = req.ToSequenceNr;
var persistenceId = req.PersistenceId;
- try
- {
- var highestSequenceNr = await ReadHighestSequenceNr(persistenceId, command);
+ var highestSequenceNr = await ReadHighestSequenceNr(persistenceId, command);
- command.CommandText = DeleteBatchSql;
- command.Parameters.Clear();
- AddParameter(command, "@PersistenceId", DbType.String, persistenceId);
- AddParameter(command, "@ToSequenceNr", DbType.Int64, toSequenceNr);
-
- await command.ExecuteNonQueryAsync();
+ command.CommandText = DeleteBatchSql;
+ command.Parameters.Clear();
+ AddParameter(command, "@PersistenceId", DbType.String, persistenceId);
+ AddParameter(command, "@ToSequenceNr", DbType.Int64, toSequenceNr);
- if (highestSequenceNr <= toSequenceNr)
- {
- command.CommandText = UpdateSequenceNrSql;
- command.Parameters.Clear();
+ await command.ExecuteNonQueryAsync();
- AddParameter(command, "@PersistenceId", DbType.String, persistenceId);
- AddParameter(command, "@SequenceNr", DbType.Int64, highestSequenceNr);
+ if (highestSequenceNr <= toSequenceNr)
+ {
+ command.CommandText = UpdateSequenceNrSql;
+ command.Parameters.Clear();
- await command.ExecuteNonQueryAsync();
- }
+ AddParameter(command, "@PersistenceId", DbType.String, persistenceId);
+ AddParameter(command, "@SequenceNr", DbType.Int64, highestSequenceNr);
- var response = new DeleteMessagesSuccess(toSequenceNr);
- req.PersistentActor.Tell(response);
- }
- catch (Exception cause)
- {
- var response = new DeleteMessagesFailure(cause, toSequenceNr);
- req.PersistentActor.Tell(response, ActorRefs.NoSender);
+ await command.ExecuteNonQueryAsync();
}
}
@@ -1168,116 +1244,47 @@ protected virtual async Task HandleReplayMessages(ReplayMessages req, TCommand c
}
}
- private async Task HandleWriteMessages(WriteMessages req, TCommand command)
+ private async Task HandleWriteMessages(WriteMessages req, TCommand command)
{
- IJournalResponse summary = null;
- var responses = new List<(IJournalResponse, IActorRef)>();
var tags = new HashSet();
var persistenceIds = new HashSet();
- var actorInstanceId = req.ActorInstanceId;
- var atomicWriteCount = req.Messages.OfType().Count();
- try
- {
- command.CommandText = InsertEventSql;
+ command.CommandText = InsertEventSql;
- var tagBuilder = new StringBuilder(16); // magic number
+ var tagBuilder = new StringBuilder(16); // magic number
- foreach (var envelope in req.Messages)
+ foreach (var envelope in req.Messages.OfType())
+ {
+ var writes = (IImmutableList)envelope.Payload;
+ foreach (var unadapted in writes)
{
- if (envelope is AtomicWrite write)
+ command.Parameters.Clear();
+ tagBuilder.Clear();
+
+ var persistent = AdaptToJournal(unadapted);
+ if (persistent.Payload is Tagged tagged)
{
- var writes = (IImmutableList)write.Payload;
- foreach (var unadapted in writes)
+ if (tagged.Tags.Count != 0)
{
- try
+ tagBuilder.Append(';');
+ foreach (var tag in tagged.Tags)
{
- command.Parameters.Clear();
- tagBuilder.Clear();
-
- var persistent = AdaptToJournal(unadapted);
- if (persistent.Payload is Tagged tagged)
- {
- if (tagged.Tags.Count != 0)
- {
- tagBuilder.Append(';');
- foreach (var tag in tagged.Tags)
- {
- tags.Add(tag);
- tagBuilder.Append(tag).Append(';');
- }
- }
- persistent = persistent.WithPayload(tagged.Payload);
- }
-
- WriteEvent(command, persistent.WithTimestamp(DateTime.UtcNow.Ticks), tagBuilder.ToString());
-
- await command.ExecuteNonQueryAsync();
-
- var response = (new WriteMessageSuccess(unadapted, actorInstanceId), unadapted.Sender);
- responses.Add(response);
- persistenceIds.Add(persistent.PersistenceId);
- }
- catch (DbException cause)
- {
- // database-related exceptions should result in failure
- summary = new WriteMessagesFailed(cause, atomicWriteCount);
- var response = (new WriteMessageFailure(unadapted, cause, actorInstanceId), unadapted.Sender);
- responses.Add(response);
- }
- catch (Exception cause)
- {
- //TODO: this scope wraps atomic write. Atomic writes have all-or-nothing commits.
- // so we should revert transaction here. But we need to check how this affect performance.
-
- var response = (new WriteMessageRejected(unadapted, cause, actorInstanceId), unadapted.Sender);
- responses.Add(response);
+ tags.Add(tag);
+ tagBuilder.Append(tag).Append(';');
}
}
+ persistent = persistent.WithPayload(tagged.Payload);
}
- else
- {
- //TODO: other cases?
- var response = (new LoopMessageSuccess(envelope.Payload, actorInstanceId), envelope.Sender);
- responses.Add(response);
- }
- }
- if (HasTagSubscribers && tags.Count != 0)
- {
- foreach (var tag in tags)
- {
- NotifyTagChanged(tag);
- }
- }
+ WriteEvent(command, persistent.WithTimestamp(DateTime.UtcNow.Ticks), tagBuilder.ToString());
- if (HasPersistenceIdSubscribers)
- {
- foreach (var persistenceId in persistenceIds)
- {
- NotifyPersistenceIdChanged(persistenceId);
- }
- }
+ await command.ExecuteNonQueryAsync();
- if (HasNewEventsSubscribers)
- {
- NotifyNewEventAppended();
+ persistenceIds.Add(persistent.PersistenceId);
}
-
- summary = summary ?? WriteMessagesSuccessful.Instance;
- }
- catch (Exception cause)
- {
- summary = new WriteMessagesFailed(cause, atomicWriteCount);
}
- var aref = req.PersistentActor;
-
- aref.Tell(summary);
- foreach (var r in responses)
- {
- aref.Tell(r.Item1, r.Item2);
- }
+ return new WriteMessagesResult(req, tags, persistenceIds);
}
///
@@ -1388,29 +1395,111 @@ protected void AddParameter(TCommand command, string paramName, DbType dbType, o
/// Parameter to customize
protected virtual void PreAddParameterToCommand(TCommand command, DbParameter param) { }
+ ///
+ /// Select the buffer that has the smallest id on its first item, retrieve a maximum Setup.MaxBatchSize
+ /// items from it, and return it as a chunk that needs to be batched
+ ///
private RequestChunk DequeueChunk(int chunkId)
{
- var operationsCount = Math.Min(Buffer.Count, Setup.MaxBatchSize);
- var array = new IJournalRequest[operationsCount];
- for (int i = 0; i < operationsCount; i++)
+ var currentBuffer = _buffers
+ .Where(q => q.Count > 0)
+ .OrderBy(q => q.Peek().id).First();
+
+ var operations = new List();
+ if (ReferenceEquals(currentBuffer, WriteBuffer))
{
- var req = Buffer.Dequeue();
- array[i] = req;
+ // Stop dequeuing when we encounter another type of write operation request
+ // We don't batch delete and writes in the same batch, reason being a database
+ // can be deadlocked if write and delete happens in the same transaction
+ var writeType = currentBuffer.Peek().request.GetType();
+ while(currentBuffer.Count > 0 && currentBuffer.Peek().request.GetType() == writeType)
+ {
+ operations.Add(currentBuffer.Dequeue().request);
+ if (operations.Count == Setup.MaxBatchSize)
+ break;
+ }
}
-
- return new RequestChunk(chunkId, array);
+ else
+ {
+ while(currentBuffer.Count > 0)
+ {
+ operations.Add(currentBuffer.Dequeue().request);
+ if (operations.Count == Setup.MaxBatchSize)
+ break;
+ }
+ }
+
+ return new RequestChunk(chunkId, operations.ToArray());
}
private void CompleteBatch(BatchComplete msg)
{
_remainingOperations++;
- if (msg.Cause != null)
+ Log.Debug("Completed batch (chunkId: {0}) of {1} operations in {2} milliseconds", msg.ChunkId, msg.OperationCount, msg.TimeSpent.TotalMilliseconds);
+
+ TryProcess();
+ }
+
+ private class WriteMessagesResult
+ {
+ private readonly WriteMessages _request;
+
+ private readonly ImmutableHashSet _tags;
+ private readonly ImmutableHashSet _persistenceIds;
+
+ public WriteMessagesResult(
+ WriteMessages request,
+ IEnumerable tags,
+ IEnumerable persistenceIds)
{
- Log.Error(msg.Cause, "An error occurred during event batch processing (chunkId: {0})", msg.ChunkId);
+ _request = request;
+ _tags = tags.ToImmutableHashSet();
+ _persistenceIds = persistenceIds.ToImmutableHashSet();
}
- else Log.Debug("Completed batch (chunkId: {0}) of {1} operations in {2} milliseconds", msg.ChunkId, msg.OperationCount, msg.TimeSpent.TotalMilliseconds);
- TryProcess();
+ public void FinalizeSuccess(BatchingSqlJournal journal)
+ {
+ var actorInstanceId = _request.ActorInstanceId;
+ var aRef = _request.PersistentActor;
+ aRef.Tell(WriteMessagesSuccessful.Instance);
+
+ foreach (var envelope in _request.Messages)
+ {
+ if (!(envelope is AtomicWrite write))
+ {
+ aRef.Tell(new LoopMessageSuccess(envelope.Payload, actorInstanceId), envelope.Sender);
+ continue;
+ }
+
+ var writes = (IImmutableList)write.Payload;
+ foreach (var unadapted in writes)
+ {
+ aRef.Tell(new WriteMessageSuccess(unadapted, actorInstanceId), unadapted.Sender);
+ }
+ }
+
+ if (journal.HasTagSubscribers && _tags.Count != 0)
+ {
+ foreach (var tag in _tags)
+ {
+ journal.NotifyTagChanged(tag);
+ }
+ }
+
+ if (journal.HasPersistenceIdSubscribers)
+ {
+ foreach (var persistenceId in _persistenceIds)
+ {
+ journal.NotifyPersistenceIdChanged(persistenceId);
+ }
+ }
+
+ if (journal.HasNewEventsSubscribers)
+ {
+ journal.NotifyNewEventAppended();
+ }
+
+ }
}
}
@@ -1434,5 +1523,15 @@ public JournalBufferOverflowException() : base(
+ " change it.")
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected JournalBufferOverflowException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
}
diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/SqlJournal.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/SqlJournal.cs
index b043c1c1cbf..8d74a49c1b0 100644
--- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/SqlJournal.cs
+++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/SqlJournal.cs
@@ -506,12 +506,10 @@ protected virtual string GetConnectionString()
{
var connectionString = _settings.ConnectionString;
-#if CONFIGURATION
if (string.IsNullOrEmpty(connectionString))
{
connectionString = System.Configuration.ConfigurationManager.ConnectionStrings[_settings.ConnectionStringName].ConnectionString;
}
-#endif
return connectionString;
}
diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Snapshot/SqlSnapshotStore.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Snapshot/SqlSnapshotStore.cs
index ad92d5c665b..f63d246e7b3 100644
--- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Snapshot/SqlSnapshotStore.cs
+++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Snapshot/SqlSnapshotStore.cs
@@ -149,12 +149,10 @@ protected virtual string GetConnectionString()
{
var connectionString = _settings.ConnectionString;
-#if CONFIGURATION
if (string.IsNullOrEmpty(connectionString))
{
connectionString = System.Configuration.ConfigurationManager.ConnectionStrings[_settings.ConnectionStringName].ConnectionString;
}
-#endif
return connectionString;
}
diff --git a/src/contrib/persistence/Akka.Persistence.Sql.TestKit/Akka.Persistence.Sql.TestKit.csproj b/src/contrib/persistence/Akka.Persistence.Sql.TestKit/Akka.Persistence.Sql.TestKit.csproj
index 65bd043c117..b4c479e7925 100644
--- a/src/contrib/persistence/Akka.Persistence.Sql.TestKit/Akka.Persistence.Sql.TestKit.csproj
+++ b/src/contrib/persistence/Akka.Persistence.Sql.TestKit/Akka.Persistence.Sql.TestKit.csproj
@@ -16,10 +16,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Akka.Persistence.Sqlite.Tests.csproj b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Akka.Persistence.Sqlite.Tests.csproj
index 69486b773af..a396432f1ef 100644
--- a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Akka.Persistence.Sqlite.Tests.csproj
+++ b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Akka.Persistence.Sqlite.Tests.csproj
@@ -27,10 +27,6 @@
-
- $(DefineConstants);SERIALIZABLE
-
-
$(DefineConstants);RELEASE
diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj b/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj
index 0d52c1c8ac0..40be4c4326d 100644
--- a/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj
+++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/src/contrib/serializers/Akka.Serialization.Hyperion/Akka.Serialization.Hyperion.csproj b/src/contrib/serializers/Akka.Serialization.Hyperion/Akka.Serialization.Hyperion.csproj
index 13a0d932ec0..8fb0de29efb 100644
--- a/src/contrib/serializers/Akka.Serialization.Hyperion/Akka.Serialization.Hyperion.csproj
+++ b/src/contrib/serializers/Akka.Serialization.Hyperion/Akka.Serialization.Hyperion.csproj
@@ -12,6 +12,14 @@
+
+
+
+
+
+
+
+
$(DefineConstants);RELEASE
diff --git a/src/contrib/serializers/Akka.Serialization.TestKit/Akka.Serialization.TestKit.csproj b/src/contrib/serializers/Akka.Serialization.TestKit/Akka.Serialization.TestKit.csproj
index a3ebeab5a37..baaf650bb5b 100644
--- a/src/contrib/serializers/Akka.Serialization.TestKit/Akka.Serialization.TestKit.csproj
+++ b/src/contrib/serializers/Akka.Serialization.TestKit/Akka.Serialization.TestKit.csproj
@@ -13,4 +13,9 @@
+
+
+ $(DefineConstants);RELEASE
+
+
\ No newline at end of file
diff --git a/src/contrib/testkits/Akka.TestKit.Xunit/Internals/AkkaEqualException.cs b/src/contrib/testkits/Akka.TestKit.Xunit/Internals/AkkaEqualException.cs
index af5d866b4be..93d153a5554 100644
--- a/src/contrib/testkits/Akka.TestKit.Xunit/Internals/AkkaEqualException.cs
+++ b/src/contrib/testkits/Akka.TestKit.Xunit/Internals/AkkaEqualException.cs
@@ -33,7 +33,6 @@ public AkkaEqualException(object expected, object actual, string format = "", pa
_args = args;
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -43,7 +42,7 @@ protected AkkaEqualException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
-#endif
+
///
/// The message that describes the error.
///
diff --git a/src/contrib/testkits/Akka.TestKit.Xunit2/Internals/AkkaEqualException.cs b/src/contrib/testkits/Akka.TestKit.Xunit2/Internals/AkkaEqualException.cs
index f66ff87be65..c0c21e6224d 100644
--- a/src/contrib/testkits/Akka.TestKit.Xunit2/Internals/AkkaEqualException.cs
+++ b/src/contrib/testkits/Akka.TestKit.Xunit2/Internals/AkkaEqualException.cs
@@ -33,7 +33,6 @@ public AkkaEqualException(object expected, object actual, string format = "", pa
_args = args;
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -43,7 +42,7 @@ protected AkkaEqualException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
-#endif
+
///
/// The message that describes the error.
///
diff --git a/src/contrib/testkits/Akka.TestKit.Xunit2/Internals/Loggers.cs b/src/contrib/testkits/Akka.TestKit.Xunit2/Internals/Loggers.cs
index 55adb6b09b3..4ea59da9e0d 100644
--- a/src/contrib/testkits/Akka.TestKit.Xunit2/Internals/Loggers.cs
+++ b/src/contrib/testkits/Akka.TestKit.Xunit2/Internals/Loggers.cs
@@ -5,6 +5,7 @@
//
//-----------------------------------------------------------------------
+using System;
using Akka.Actor;
using Akka.Event;
using Xunit.Abstractions;
@@ -16,20 +17,44 @@ namespace Akka.TestKit.Xunit2.Internals
///
public class TestOutputLogger : ReceiveActor
{
+ private readonly ITestOutputHelper _output;
+
///
/// Initializes a new instance of the class.
///
/// The provider used to write test output.
public TestOutputLogger(ITestOutputHelper output)
{
- Receive(e => output.WriteLine(e.ToString()));
- Receive(e => output.WriteLine(e.ToString()));
- Receive(e => output.WriteLine(e.ToString()));
- Receive(e => output.WriteLine(e.ToString()));
+ _output = output;
+
+ Receive(HandleLogEvent);
+ Receive(HandleLogEvent);
+ Receive(HandleLogEvent);
+ Receive(HandleLogEvent);
Receive(e =>
{
e.LoggingBus.Subscribe(Self, typeof (LogEvent));
});
}
+
+ private void HandleLogEvent(LogEvent e)
+ {
+ try
+ {
+ _output.WriteLine(e.ToString());
+ }
+ catch (FormatException ex)
+ {
+ if (e.Message is LogMessage msg)
+ {
+ var message =
+ $"Received a malformed formatted message. Log level: [{e.LogLevel()}], Template: [{msg.Format}], args: [{string.Join(",", msg.Args)}]";
+ if(e.Cause != null)
+ throw new AggregateException(message, ex, e.Cause);
+ throw new FormatException(message, ex);
+ }
+ throw;
+ }
+ }
}
}
diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCluster.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCluster.approved.txt
index c8c6f3b7c0e..8f9b3b5ccab 100644
--- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCluster.approved.txt
+++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCluster.approved.txt
@@ -176,6 +176,7 @@ namespace Akka.Cluster
public class ClusterJoinFailedException : Akka.Actor.AkkaException
{
public ClusterJoinFailedException(string message) { }
+ protected ClusterJoinFailedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class ClusterScope : Akka.Actor.Scope
{
diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveClusterTools.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveClusterTools.approved.txt
index df676d7749b..3b2fd70c621 100644
--- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveClusterTools.approved.txt
+++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveClusterTools.approved.txt
@@ -345,6 +345,7 @@ namespace Akka.Cluster.Tools.Singleton
public sealed class ClusterSingletonManagerIsStuckException : Akka.Actor.AkkaException
{
public ClusterSingletonManagerIsStuckException(string message) { }
+ public ClusterSingletonManagerIsStuckException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class ClusterSingletonManagerSettings : Akka.Actor.INoSerializationVerificationNeeded
{
diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCoordination.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCoordination.approved.txt
index 6bda7ca1ed2..1414adb9dde 100644
--- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCoordination.approved.txt
+++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCoordination.approved.txt
@@ -15,6 +15,7 @@ namespace Akka.Coordination
{
public LeaseException(string message) { }
public LeaseException(string message, System.Exception innerEx) { }
+ protected LeaseException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class LeaseProvider : Akka.Actor.IExtension
{
@@ -43,6 +44,7 @@ namespace Akka.Coordination
{
public LeaseTimeoutException(string message) { }
public LeaseTimeoutException(string message, System.Exception innerEx) { }
+ protected LeaseTimeoutException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class LeaseUsageSettings
{
diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt
index 2def445471a..8aee29b1c71 100644
--- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt
+++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt
@@ -151,21 +151,26 @@ namespace Akka.Actor
public ActorInitializationException(string message) { }
public ActorInitializationException(string message, System.Exception cause) { }
public ActorInitializationException(Akka.Actor.IActorRef actor, string message, System.Exception cause = null) { }
+ protected ActorInitializationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public Akka.Actor.IActorRef Actor { get; set; }
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public override string ToString() { }
}
public class ActorInterruptedException : Akka.Actor.AkkaException
{
public ActorInterruptedException(string message = null, System.Exception cause = null) { }
+ protected ActorInterruptedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class ActorKilledException : Akka.Actor.AkkaException
{
public ActorKilledException() { }
public ActorKilledException(string message) { }
+ protected ActorKilledException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class ActorNotFoundException : Akka.Actor.AkkaException
{
public ActorNotFoundException() { }
+ protected ActorNotFoundException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public ActorNotFoundException(string message, System.Exception innerException = null) { }
}
public abstract class ActorPath : Akka.Util.ISurrogated, System.IComparable, System.IEquatable
@@ -384,7 +389,7 @@ namespace Akka.Actor
where T : class, Akka.Actor.IExtension
where TI : Akka.Actor.IExtensionId { }
}
- public sealed class Address : Akka.Util.ISurrogated, System.IComparable, System.IComparable, System.IEquatable
+ public sealed class Address : Akka.Util.ISurrogated, System.ICloneable, System.IComparable, System.IComparable, System.IEquatable
{
public static readonly Akka.Actor.Address AllSystems;
public static readonly System.Collections.Generic.IComparer Comparer;
@@ -424,6 +429,7 @@ namespace Akka.Actor
{
protected AkkaException() { }
protected AkkaException(string message, System.Exception cause = null) { }
+ protected AkkaException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
protected System.Exception Cause { get; }
}
public class AllForOneStrategy : Akka.Actor.SupervisorStrategy, System.IEquatable
@@ -458,6 +464,7 @@ namespace Akka.Actor
public class AskTimeoutException : Akka.Actor.AkkaException
{
public AskTimeoutException(string message) { }
+ protected AskTimeoutException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class BootstrapSetup : Akka.Actor.Setup.Setup
{
@@ -577,7 +584,9 @@ namespace Akka.Actor
public class DeathPactException : Akka.Actor.AkkaException
{
public DeathPactException(Akka.Actor.IActorRef deadActor) { }
+ protected DeathPactException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public Akka.Actor.IActorRef DeadActor { get; }
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class static Decider
{
@@ -1160,10 +1169,12 @@ namespace Akka.Actor
public class IllegalActorNameException : Akka.Actor.AkkaException
{
public IllegalActorNameException(string message) { }
+ protected IllegalActorNameException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class IllegalActorStateException : Akka.Actor.AkkaException
{
public IllegalActorStateException(string message) { }
+ protected IllegalActorStateException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class Inbox : Akka.Actor.ICanWatch, Akka.Actor.IInboxable, System.IDisposable
{
@@ -1204,11 +1215,13 @@ namespace Akka.Actor
{
public InvalidActorNameException(string message) { }
public InvalidActorNameException(string message, System.Exception innerException) { }
+ protected InvalidActorNameException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class InvalidMessageException : Akka.Actor.AkkaException
{
public InvalidMessageException() { }
public InvalidMessageException(string message) { }
+ protected InvalidMessageException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class Kill : Akka.Actor.IAutoReceivedMessage
{
@@ -1293,6 +1306,7 @@ namespace Akka.Actor
public LoggerInitializationException() { }
public LoggerInitializationException(string message) { }
public LoggerInitializationException(string message, System.Exception cause = null) { }
+ protected LoggerInitializationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
[Akka.Annotations.InternalApiAttribute()]
public abstract class MinimalActorRef : Akka.Actor.InternalActorRefBase, Akka.Actor.IActorRefScope
@@ -1374,11 +1388,17 @@ namespace Akka.Actor
public class PostRestartException : Akka.Actor.ActorInitializationException
{
public PostRestartException(Akka.Actor.IActorRef actor, System.Exception cause, System.Exception originalCause) { }
+ protected PostRestartException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public System.Exception OriginalCause { get; }
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
- public class PreRestartException : Akka.Actor.AkkaException
+ public class PreRestartException : Akka.Actor.ActorInitializationException
{
public PreRestartException(Akka.Actor.IActorRef actor, System.Exception restartException, System.Exception cause, object optionalMessage) { }
+ protected PreRestartException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public object OptionalMessage { get; }
+ public System.Exception RestartException { get; }
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class Props : Akka.Util.ISurrogated, System.IEquatable
{
@@ -1577,6 +1597,7 @@ namespace Akka.Actor
public sealed class SchedulerException : Akka.Actor.AkkaException
{
public SchedulerException(string message) { }
+ protected SchedulerException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class static SchedulerExtensions
{
@@ -1692,6 +1713,7 @@ namespace Akka.Actor
public class StashOverflowException : Akka.Actor.AkkaException
{
public StashOverflowException(string message, System.Exception cause = null) { }
+ protected StashOverflowException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public abstract class Status
{
@@ -2206,6 +2228,7 @@ namespace Akka.Configuration
{
public ConfigurationException(string message) { }
public ConfigurationException(string message, System.Exception exception) { }
+ protected ConfigurationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public static Akka.Configuration.ConfigurationException NullOrEmptyConfig(string path = null) { }
}
public class ConfigurationFactory
@@ -2642,6 +2665,7 @@ namespace Akka.Dispatch
public class RejectedExecutionException : Akka.Actor.AkkaException
{
public RejectedExecutionException(string message = null, System.Exception inner = null) { }
+ protected RejectedExecutionException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class ThreadPoolConfig
{
@@ -3192,6 +3216,7 @@ namespace Akka.IO.Buffers
public class BufferPoolAllocationException : Akka.Actor.AkkaException
{
public BufferPoolAllocationException(string message) { }
+ protected BufferPoolAllocationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public interface IBufferPool
{
@@ -3973,6 +3998,7 @@ namespace Akka.Pattern
{
public IllegalStateException(string message) { }
public IllegalStateException(string message, System.Exception innerEx) { }
+ protected IllegalStateException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class OpenCircuitException : Akka.Actor.AkkaException
{
@@ -3983,7 +4009,9 @@ namespace Akka.Pattern
public OpenCircuitException(string message, System.Exception cause, System.TimeSpan remainingDuration) { }
public OpenCircuitException(System.Exception cause) { }
public OpenCircuitException(System.Exception cause, System.TimeSpan remainingDuration) { }
+ protected OpenCircuitException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public System.TimeSpan RemainingDuration { get; }
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class static RetrySupport
{
@@ -3995,6 +4023,7 @@ namespace Akka.Pattern
public class UserCalledFailException : Akka.Actor.AkkaException
{
public UserCalledFailException() { }
+ protected UserCalledFailException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
}
namespace Akka.Routing
diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveDistributedData.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveDistributedData.approved.txt
index fa45f6893cd..56ce958c6a4 100644
--- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveDistributedData.approved.txt
+++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveDistributedData.approved.txt
@@ -42,6 +42,7 @@ namespace Akka.DistributedData
public class DataDeletedException : System.Exception
{
public DataDeletedException(string message) { }
+ protected DataDeletedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class Delete : Akka.Actor.INoSerializationVerificationNeeded, System.IEquatable
{
@@ -981,6 +982,7 @@ namespace Akka.DistributedData.Durable
{
public LoadFailedException(string message) { }
public LoadFailedException(string message, System.Exception cause) { }
+ public LoadFailedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class Store
{
diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApprovePersistence.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApprovePersistence.approved.txt
index 11c5c2a144d..44dce9a7cb9 100644
--- a/src/core/Akka.API.Tests/CoreAPISpec.ApprovePersistence.approved.txt
+++ b/src/core/Akka.API.Tests/CoreAPISpec.ApprovePersistence.approved.txt
@@ -362,6 +362,7 @@ namespace Akka.Persistence
public MaxUnconfirmedMessagesExceededException() { }
public MaxUnconfirmedMessagesExceededException(string message) { }
public MaxUnconfirmedMessagesExceededException(string message, System.Exception innerException) { }
+ protected MaxUnconfirmedMessagesExceededException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class Persistence : Akka.Actor.ExtensionIdProvider
{
@@ -505,6 +506,7 @@ namespace Akka.Persistence
{
public RecoveryTimedOutException() { }
public RecoveryTimedOutException(string message, System.Exception cause = null) { }
+ public RecoveryTimedOutException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class ReplayMessages : Akka.Actor.INoSerializationVerificationNeeded, Akka.Persistence.IJournalMessage, Akka.Persistence.IJournalRequest, Akka.Persistence.IPersistenceMessage, System.IEquatable
{
@@ -827,6 +829,7 @@ namespace Akka.Persistence.Journal
{
public AsyncReplayTimeoutException() { }
public AsyncReplayTimeoutException(string message) { }
+ protected AsyncReplayTimeoutException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public abstract class AsyncWriteJournal : Akka.Persistence.Journal.WriteJournalBase, Akka.Persistence.Journal.IAsyncRecovery
{
@@ -1109,6 +1112,7 @@ namespace Akka.Persistence.Snapshot
public NoSnapshotStoreException() { }
public NoSnapshotStoreException(string message) { }
public NoSnapshotStoreException(string message, System.Exception innerException) { }
+ protected NoSnapshotStoreException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
}
public class SnapshotEntry
diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApprovePersistenceSqlCommon.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApprovePersistenceSqlCommon.approved.txt
index 33f960fce76..5e78ff5e2ea 100644
--- a/src/core/Akka.API.Tests/CoreAPISpec.ApprovePersistenceSqlCommon.approved.txt
+++ b/src/core/Akka.API.Tests/CoreAPISpec.ApprovePersistenceSqlCommon.approved.txt
@@ -74,7 +74,6 @@ namespace Akka.Persistence.Sql.Common.Journal
where TConnection : System.Data.Common.DbConnection
where TCommand : System.Data.Common.DbCommand
{
- protected readonly System.Collections.Generic.Queue Buffer;
protected readonly bool CanPublish;
protected const int IsDeletedIndex = 3;
protected readonly Akka.Event.ILoggingAdapter Log;
@@ -188,6 +187,7 @@ namespace Akka.Persistence.Sql.Common.Journal
{
public static readonly Akka.Persistence.Sql.Common.Journal.JournalBufferOverflowException Instance;
public JournalBufferOverflowException() { }
+ protected JournalBufferOverflowException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class JournalEntry
{
diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveRemote.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveRemote.approved.txt
index f3fc63faff7..766d4f50243 100644
--- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveRemote.approved.txt
+++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveRemote.approved.txt
@@ -284,6 +284,7 @@ namespace Akka.Remote
public class RemoteTransportException : Akka.Actor.AkkaException
{
public RemoteTransportException(string message, System.Exception cause = null) { }
+ protected RemoteTransportException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class RemoteWatcher : Akka.Actor.UntypedActor, Akka.Dispatch.IRequiresMessageQueue
{
@@ -434,11 +435,11 @@ namespace Akka.Remote.Serialization
public override string Manifest(object obj) { }
public override byte[] ToBinary(object obj) { }
}
- public sealed class PrimitiveSerializers : Akka.Serialization.Serializer
+ public sealed class PrimitiveSerializers : Akka.Serialization.SerializerWithStringManifest
{
public PrimitiveSerializers(Akka.Actor.ExtendedActorSystem system) { }
- public override bool IncludeManifest { get; }
- public override object FromBinary(byte[] bytes, System.Type type) { }
+ public override object FromBinary(byte[] bytes, string manifest) { }
+ public override string Manifest(object obj) { }
public override byte[] ToBinary(object obj) { }
}
public class ProtobufSerializer : Akka.Serialization.Serializer
@@ -502,6 +503,7 @@ namespace Akka.Remote.Transport
public class AkkaProtocolException : Akka.Actor.AkkaException
{
public AkkaProtocolException(string message, System.Exception cause = null) { }
+ protected AkkaProtocolException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class AssociateAttempt : Akka.Remote.Transport.Activity
{
@@ -602,6 +604,7 @@ namespace Akka.Remote.Transport
public class InvalidAssociationException : Akka.Actor.AkkaException
{
public InvalidAssociationException(string message, System.Exception cause = null) { }
+ protected InvalidAssociationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class ListenAttempt : Akka.Remote.Transport.Activity
{
diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveStreams.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveStreams.approved.txt
index 1e1b438b049..af1c1fda081 100644
--- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveStreams.approved.txt
+++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveStreams.approved.txt
@@ -12,11 +12,13 @@ namespace Akka.Streams
public sealed class AbruptStageTerminationException : System.Exception
{
public AbruptStageTerminationException(Akka.Streams.Stage.GraphStageLogic logic) { }
+ protected AbruptStageTerminationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class AbruptTerminationException : System.Exception
{
public readonly Akka.Actor.IActorRef Actor;
public AbruptTerminationException(Akka.Actor.IActorRef actor) { }
+ protected AbruptTerminationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class static ActorAttributes
{
@@ -280,11 +282,13 @@ namespace Akka.Streams
public class BindFailedException : Akka.Streams.StreamTcpException
{
public static readonly Akka.Streams.BindFailedException Instance;
+ protected BindFailedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class BufferOverflowException : System.Exception
{
public BufferOverflowException(string message) { }
public BufferOverflowException(string message, System.Exception innerException) { }
+ protected BufferOverflowException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class ClosedShape : Akka.Streams.Shape
{
@@ -298,6 +302,7 @@ namespace Akka.Streams
{
public ConnectionException(string message) { }
public ConnectionException(string message, System.Exception innerException) { }
+ protected ConnectionException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class static Construct
{
@@ -757,12 +762,14 @@ namespace Akka.Streams
public sealed class InvalidPartnerActorException : Akka.Pattern.IllegalStateException
{
public InvalidPartnerActorException(Akka.Actor.IActorRef expectedRef, Akka.Actor.IActorRef gotRef, string message) { }
+ protected InvalidPartnerActorException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public Akka.Actor.IActorRef ExpectedRef { get; }
public Akka.Actor.IActorRef GotRef { get; }
}
public sealed class InvalidSequenceNumberException : Akka.Pattern.IllegalStateException
{
public InvalidSequenceNumberException(long expectedSeqNr, long gotSeqNr, string message) { }
+ protected InvalidSequenceNumberException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public long ExpectedSeqNr { get; }
public long GotSeqNr { get; }
}
@@ -783,6 +790,7 @@ namespace Akka.Streams
public class MaterializationException : System.Exception
{
public MaterializationException(string message, System.Exception innerException) { }
+ protected MaterializationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class NoMaterializer : Akka.Streams.IMaterializer
{
@@ -797,6 +805,7 @@ namespace Akka.Streams
public class NoSuchElementException : System.Exception
{
public NoSuchElementException(string message) { }
+ protected NoSuchElementException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public abstract class OutPort
{
@@ -848,8 +857,9 @@ namespace Akka.Streams
public sealed class RemoteStreamRefActorTerminatedException : System.Exception
{
public RemoteStreamRefActorTerminatedException(string message) { }
+ protected RemoteStreamRefActorTerminatedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
- public abstract class Shape
+ public abstract class Shape : System.ICloneable
{
protected Shape() { }
public abstract System.Collections.Immutable.ImmutableArray Inlets { get; }
@@ -890,9 +900,14 @@ namespace Akka.Streams
public override bool Equals(object obj) { }
public override int GetHashCode() { }
}
+ public class StreamDetachedException : System.Exception
+ {
+ public static readonly Akka.Streams.StreamDetachedException Instance;
+ }
public class StreamLimitReachedException : System.Exception
{
public StreamLimitReachedException(long max) { }
+ protected StreamLimitReachedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class static StreamRefAttributes
{
@@ -941,6 +956,7 @@ namespace Akka.Streams
public sealed class StreamRefSubscriptionTimeoutException : Akka.Pattern.IllegalStateException
{
public StreamRefSubscriptionTimeoutException(string message) { }
+ protected StreamRefSubscriptionTimeoutException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public sealed class StreamSubscriptionTimeoutSettings : System.IEquatable
{
@@ -963,6 +979,7 @@ namespace Akka.Streams
{
public StreamTcpException(string message) { }
public StreamTcpException(string message, System.Exception innerException) { }
+ protected StreamTcpException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public enum SubstreamCancelStrategy
{
@@ -972,6 +989,7 @@ namespace Akka.Streams
public sealed class TargetRefNotInitializedYetException : Akka.Pattern.IllegalStateException
{
public TargetRefNotInitializedYetException() { }
+ protected TargetRefNotInitializedYetException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public enum ThrottleMode
{
@@ -1017,6 +1035,7 @@ namespace Akka.Streams
public class WatchedActorTerminatedException : Akka.Actor.AkkaException
{
public WatchedActorTerminatedException(string stageName, Akka.Actor.IActorRef actorRef) { }
+ protected WatchedActorTerminatedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
}
namespace Akka.Streams.Actors
@@ -1454,6 +1473,7 @@ namespace Akka.Streams.Dsl
public class FramingException : System.Exception
{
public FramingException(string message) { }
+ protected FramingException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
}
public class static GraphDsl
@@ -1688,6 +1708,7 @@ namespace Akka.Streams.Dsl
public class OutputTruncationException : System.Exception
{
public OutputTruncationException() { }
+ protected OutputTruncationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class static PagedSource
{
@@ -1718,6 +1739,7 @@ namespace Akka.Streams.Dsl
public sealed class PartitionOutOfBoundsException : System.Exception
{
public PartitionOutOfBoundsException(string message) { }
+ protected PartitionOutOfBoundsException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class PartitionWith : Akka.Streams.Stage.GraphStage>
{
@@ -2205,6 +2227,7 @@ namespace Akka.Streams.Dsl
public sealed class TcpIdleTimeoutException : System.TimeoutException
{
public TcpIdleTimeoutException(string message, System.TimeSpan duration) { }
+ protected TcpIdleTimeoutException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public System.TimeSpan Duration { get; }
}
public class static TcpStreamExtensions
@@ -2219,6 +2242,7 @@ namespace Akka.Streams.Dsl
public class UnexpectedOutputException : System.Exception
{
public UnexpectedOutputException(object element) { }
+ protected UnexpectedOutputException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class UnzipWith
{
@@ -3160,6 +3184,7 @@ namespace Akka.Streams.Implementation
public class MaterializationPanicException : System.Exception
{
public MaterializationPanicException(System.Exception innerException) { }
+ protected MaterializationPanicException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
}
[Akka.Annotations.InternalApiAttribute()]
@@ -3218,10 +3243,12 @@ namespace Akka.Streams.Implementation
public class NormalShutdownException : Akka.Pattern.IllegalStateException
{
public NormalShutdownException(string message) { }
+ protected NormalShutdownException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class NothingToReadException : System.Exception
{
public static readonly Akka.Streams.Implementation.NothingToReadException Instance;
+ protected NothingToReadException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class OutputBunch
{
@@ -3382,6 +3409,7 @@ namespace Akka.Streams.Implementation
public class SignalThrewException : Akka.Pattern.IllegalStateException, Akka.Streams.Implementation.ISpecViolation
{
public SignalThrewException(string message, System.Exception cause) { }
+ protected SignalThrewException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public class SimpleOutputs
{
@@ -3580,6 +3608,7 @@ namespace Akka.Streams.Implementation
{
public SubscriptionTimeoutException(string message) { }
public SubscriptionTimeoutException(string message, System.Exception innerException) { }
+ protected SubscriptionTimeoutException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
[Akka.Annotations.InternalApiAttribute()]
public class Throttle : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage
@@ -4838,6 +4867,7 @@ namespace Akka.Streams.Stage
public class StageActorRefNotInitializedException : System.Exception
{
public static readonly Akka.Streams.Stage.StageActorRefNotInitializedException Instance;
+ protected StageActorRefNotInitializedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
public abstract class StageState
{
diff --git a/src/core/Akka.Cluster.TestKit/Akka.Cluster.TestKit.csproj b/src/core/Akka.Cluster.TestKit/Akka.Cluster.TestKit.csproj
index 79e457c9e33..5325de65dda 100644
--- a/src/core/Akka.Cluster.TestKit/Akka.Cluster.TestKit.csproj
+++ b/src/core/Akka.Cluster.TestKit/Akka.Cluster.TestKit.csproj
@@ -14,10 +14,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj b/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj
index e1488e9f55b..0635ef67d3f 100644
--- a/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj
+++ b/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj
@@ -23,10 +23,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj b/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj
index 450b6e36d88..ed7152f6bb1 100644
--- a/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj
+++ b/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj
@@ -22,14 +22,6 @@
-
- $(DefineConstants);SERIALIZABLE;
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Cluster/Akka.Cluster.csproj b/src/core/Akka.Cluster/Akka.Cluster.csproj
index d0f36dd09af..de08aa79f62 100644
--- a/src/core/Akka.Cluster/Akka.Cluster.csproj
+++ b/src/core/Akka.Cluster/Akka.Cluster.csproj
@@ -15,10 +15,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Cluster/Cluster.cs b/src/core/Akka.Cluster/Cluster.cs
index a246c163519..973657b88ae 100644
--- a/src/core/Akka.Cluster/Cluster.cs
+++ b/src/core/Akka.Cluster/Cluster.cs
@@ -10,6 +10,7 @@
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
+using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Akka.Actor;
@@ -715,6 +716,16 @@ public class ClusterJoinFailedException : AkkaException
public ClusterJoinFailedException(string message) : base(message)
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected ClusterJoinFailedException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
}
diff --git a/src/core/Akka.Cluster/ClusterRemoteWatcher.cs b/src/core/Akka.Cluster/ClusterRemoteWatcher.cs
index 0bdb8484158..630c59f2429 100644
--- a/src/core/Akka.Cluster/ClusterRemoteWatcher.cs
+++ b/src/core/Akka.Cluster/ClusterRemoteWatcher.cs
@@ -9,6 +9,7 @@
using System.Collections.Immutable;
using System.Linq;
using Akka.Actor;
+using Akka.Dispatch;
using Akka.Remote;
namespace Akka.Cluster
@@ -31,19 +32,21 @@ internal class ClusterRemoteWatcher : RemoteWatcher
/// TBD
/// TBD
/// TBD
- public static Props Props(
+ public new static Props Props(
IFailureDetectorRegistry failureDetector,
TimeSpan heartbeatInterval,
TimeSpan unreachableReaperInterval,
TimeSpan heartbeatExpectedResponseAfter)
{
return new Props(typeof(ClusterRemoteWatcher), new object[]
- {
- failureDetector,
- heartbeatInterval,
- unreachableReaperInterval,
- heartbeatExpectedResponseAfter
- }).WithDeploy(Deploy.Local);
+ {
+ failureDetector,
+ heartbeatInterval,
+ unreachableReaperInterval,
+ heartbeatExpectedResponseAfter
+ })
+ .WithDispatcher(Dispatchers.InternalDispatcherId)
+ .WithDeploy(Deploy.Local);
}
private readonly Cluster _cluster;
diff --git a/src/core/Akka.Coordination.Tests/Akka.Coordination.Tests.csproj b/src/core/Akka.Coordination.Tests/Akka.Coordination.Tests.csproj
index 376da941fd6..21a0b770c56 100644
--- a/src/core/Akka.Coordination.Tests/Akka.Coordination.Tests.csproj
+++ b/src/core/Akka.Coordination.Tests/Akka.Coordination.Tests.csproj
@@ -20,14 +20,6 @@
-
- $(DefineConstants);SERIALIZABLE;
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Coordination/Akka.Coordination.csproj b/src/core/Akka.Coordination/Akka.Coordination.csproj
index c6bef8940a3..60fc6c4a9d2 100644
--- a/src/core/Akka.Coordination/Akka.Coordination.csproj
+++ b/src/core/Akka.Coordination/Akka.Coordination.csproj
@@ -9,10 +9,6 @@
true
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Coordination/LeaseException.cs b/src/core/Akka.Coordination/LeaseException.cs
index 153c8fc25ef..29dec0b4c2a 100644
--- a/src/core/Akka.Coordination/LeaseException.cs
+++ b/src/core/Akka.Coordination/LeaseException.cs
@@ -6,6 +6,7 @@
//-----------------------------------------------------------------------
using System;
+using System.Runtime.Serialization;
namespace Akka.Coordination
{
@@ -32,12 +33,10 @@ public LeaseException(string message, Exception innerEx)
{
}
-#if SERIALIZATION
protected LeaseException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
-#endif
}
}
diff --git a/src/core/Akka.Coordination/LeaseTimeoutException.cs b/src/core/Akka.Coordination/LeaseTimeoutException.cs
index b86f7f0aee7..911ae3e6c8e 100644
--- a/src/core/Akka.Coordination/LeaseTimeoutException.cs
+++ b/src/core/Akka.Coordination/LeaseTimeoutException.cs
@@ -6,6 +6,7 @@
//-----------------------------------------------------------------------
using System;
+using System.Runtime.Serialization;
namespace Akka.Coordination
{
@@ -32,12 +33,10 @@ public LeaseTimeoutException(string message, Exception innerEx)
{
}
-#if SERIALIZATION
protected LeaseTimeoutException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
-#endif
}
}
diff --git a/src/core/Akka.Discovery/Akka.Discovery.csproj b/src/core/Akka.Discovery/Akka.Discovery.csproj
index 0538dc05d49..b1506fc1ef7 100644
--- a/src/core/Akka.Discovery/Akka.Discovery.csproj
+++ b/src/core/Akka.Discovery/Akka.Discovery.csproj
@@ -23,10 +23,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj
index 2202d5e4c4f..52925f37da8 100644
--- a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj
+++ b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj
@@ -27,10 +27,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj b/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj
index bff83b1d9b2..ea0d22b714a 100644
--- a/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj
+++ b/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj
@@ -33,10 +33,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/CompilerErrorCollection.cs b/src/core/Akka.MultiNodeTestRunner.Shared/CompilerErrorCollection.cs
index 86a5f50ef22..9e6889d5467 100644
--- a/src/core/Akka.MultiNodeTestRunner.Shared/CompilerErrorCollection.cs
+++ b/src/core/Akka.MultiNodeTestRunner.Shared/CompilerErrorCollection.cs
@@ -9,7 +9,6 @@
using System.Collections.Generic;
using System.Reflection;
-#if CORECLR
namespace System.CodeDom.Compiler
{
public class CompilerErrorCollection : List
@@ -22,4 +21,3 @@ public class CompilerError
public bool IsWarning { get; set; }
}
}
-#endif
diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Extensions/DateTimeExtension.cs b/src/core/Akka.MultiNodeTestRunner.Shared/Extensions/DateTimeExtension.cs
index a149c39075a..981d7ada914 100644
--- a/src/core/Akka.MultiNodeTestRunner.Shared/Extensions/DateTimeExtension.cs
+++ b/src/core/Akka.MultiNodeTestRunner.Shared/Extensions/DateTimeExtension.cs
@@ -12,7 +12,6 @@
using System.Text;
using System.Threading.Tasks;
-#if CORECLR
namespace Akka.MultiNodeTestRunner.Shared.Extensions
{
internal static class DateTimeExtension
@@ -23,4 +22,3 @@ public static string ToShortTimeString(this DateTime dateTime)
}
}
}
-#endif
diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Extensions/TypeExtension.cs b/src/core/Akka.MultiNodeTestRunner.Shared/Extensions/TypeExtension.cs
index ca6be97f546..6b0b371ff30 100644
--- a/src/core/Akka.MultiNodeTestRunner.Shared/Extensions/TypeExtension.cs
+++ b/src/core/Akka.MultiNodeTestRunner.Shared/Extensions/TypeExtension.cs
@@ -12,7 +12,6 @@
using System.Text;
using System.Threading.Tasks;
-#if CORECLR
namespace Akka.MultiNodeTestRunner.Shared.Extensions
{
internal static class TypeExtension
@@ -23,4 +22,3 @@ public static MethodInfo GetMethod(this Type type, string method, params Type[]
}
}
}
-#endif
diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.cs b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.cs
index 8edb367beab..ed078b136b9 100644
--- a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.cs
+++ b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.cs
@@ -15,10 +15,6 @@
//
// ------------------------------------------------------------------------------
-#if CORECLR
-using Akka.MultiNodeTestRunner.Shared.Extensions;
-#endif
-
namespace Akka.MultiNodeTestRunner.Shared.Persistence
{
using System.Linq;
diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Sinks/ConsoleMessageSinkActor.cs b/src/core/Akka.MultiNodeTestRunner.Shared/Sinks/ConsoleMessageSinkActor.cs
index 22b92aa1f4c..e2a7c0c7877 100644
--- a/src/core/Akka.MultiNodeTestRunner.Shared/Sinks/ConsoleMessageSinkActor.cs
+++ b/src/core/Akka.MultiNodeTestRunner.Shared/Sinks/ConsoleMessageSinkActor.cs
@@ -9,9 +9,6 @@
using System.Linq;
using Akka.Actor;
using Akka.Event;
-#if CORECLR
-using Akka.MultiNodeTestRunner.Shared.Extensions;
-#endif
using Akka.MultiNodeTestRunner.Shared.Reporting;
namespace Akka.MultiNodeTestRunner.Shared.Sinks
diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Sinks/SinkCoordinator.cs b/src/core/Akka.MultiNodeTestRunner.Shared/Sinks/SinkCoordinator.cs
index 1f43f991968..3b9587807a2 100644
--- a/src/core/Akka.MultiNodeTestRunner.Shared/Sinks/SinkCoordinator.cs
+++ b/src/core/Akka.MultiNodeTestRunner.Shared/Sinks/SinkCoordinator.cs
@@ -187,11 +187,7 @@ private void PublishToChildren(RunnerMessage message)
{
foreach (var sink in Sinks)
{
-#if CORECLR
- sink.LogRunnerMessage(message.Message, Assembly.GetEntryAssembly().GetName().Name, LogLevel.InfoLevel);
-#else
sink.LogRunnerMessage(message.Message, Assembly.GetExecutingAssembly().GetName().Name, LogLevel.InfoLevel);
-#endif
}
}
diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Sinks/TeamCityMessageSinkActor.cs b/src/core/Akka.MultiNodeTestRunner.Shared/Sinks/TeamCityMessageSinkActor.cs
index 633f81266df..7280cef69aa 100644
--- a/src/core/Akka.MultiNodeTestRunner.Shared/Sinks/TeamCityMessageSinkActor.cs
+++ b/src/core/Akka.MultiNodeTestRunner.Shared/Sinks/TeamCityMessageSinkActor.cs
@@ -13,9 +13,6 @@
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Event;
-#if CORECLR
-using Akka.MultiNodeTestRunner.Shared.Extensions;
-#endif
using Akka.MultiNodeTestRunner.Shared.Reporting;
using JetBrains.TeamCity.ServiceMessages;
using JetBrains.TeamCity.ServiceMessages.Write.Special;
diff --git a/src/core/Akka.MultiNodeTestRunner/Discovery.cs b/src/core/Akka.MultiNodeTestRunner/Discovery.cs
index 8d6a88cc339..c45bed128b0 100644
--- a/src/core/Akka.MultiNodeTestRunner/Discovery.cs
+++ b/src/core/Akka.MultiNodeTestRunner/Discovery.cs
@@ -20,11 +20,7 @@
namespace Akka.MultiNodeTestRunner
{
-#if CORECLR
- public class Discovery : IMessageSink, IDisposable
-#else
public class Discovery : MarshalByRefObject, IMessageSink, IDisposable
-#endif
{
public Dictionary> Tests { get; set; }
public List Errors { get; } = new List();
@@ -75,12 +71,8 @@ private List LoadTestCaseDetails(ITestCaseDiscoveryMessage testCaseDis
{
try
{
-#if CORECLR
- var specType = testCaseDiscoveryMessage.TestAssembly.Assembly.GetType(testClass.Name).ToRuntimeType();
-#else
var testAssembly = Assembly.LoadFrom(testCaseDiscoveryMessage.TestAssembly.Assembly.AssemblyPath);
var specType = testAssembly.GetType(testClass.Name);
-#endif
var roles = RoleNames(specType);
var details = roles.Select((r, i) => new NodeTest
@@ -118,20 +110,11 @@ internal static ConstructorInfo FindConfigConstructor(Type configUser)
var current = configUser;
while (current != null)
{
-
-#if CORECLR
- var ctorWithConfig = current
- .GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
- .FirstOrDefault(c => null != c.GetParameters().FirstOrDefault(p => p.ParameterType.GetTypeInfo().IsSubclassOf(baseConfigType)));
-
- current = current.GetTypeInfo().BaseType;
-#else
var ctorWithConfig = current
.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
.FirstOrDefault(c => null != c.GetParameters().FirstOrDefault(p => p.ParameterType.IsSubclassOf(baseConfigType)));
current = current.BaseType;
-#endif
if (ctorWithConfig != null) return ctorWithConfig;
}
@@ -143,15 +126,9 @@ private object[] ConfigConstructorParamValues(Type configType)
var ctors = configType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
var empty = ctors.FirstOrDefault(c => !c.GetParameters().Any());
-#if CORECLR
- return empty != null
- ? new object[0]
- : ctors.First().GetParameters().Select(p => p.ParameterType.GetTypeInfo().IsValueType ? Activator.CreateInstance(p.ParameterType) : null).ToArray();
-#else
return empty != null
? new object[0]
: ctors.First().GetParameters().Select(p => p.ParameterType.IsValueType ? Activator.CreateInstance(p.ParameterType) : null).ToArray();
-#endif
}
///
diff --git a/src/core/Akka.Persistence.Query.Tests/Akka.Persistence.Query.Tests.csproj b/src/core/Akka.Persistence.Query.Tests/Akka.Persistence.Query.Tests.csproj
index 18660d72b06..087a19a6c01 100644
--- a/src/core/Akka.Persistence.Query.Tests/Akka.Persistence.Query.Tests.csproj
+++ b/src/core/Akka.Persistence.Query.Tests/Akka.Persistence.Query.Tests.csproj
@@ -23,14 +23,6 @@
-
- $(DefineConstants);SERIALIZABLE
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Persistence.TCK.Tests/Akka.Persistence.TCK.Tests.csproj b/src/core/Akka.Persistence.TCK.Tests/Akka.Persistence.TCK.Tests.csproj
index 2906e799e2c..6ccfccb8b8a 100644
--- a/src/core/Akka.Persistence.TCK.Tests/Akka.Persistence.TCK.Tests.csproj
+++ b/src/core/Akka.Persistence.TCK.Tests/Akka.Persistence.TCK.Tests.csproj
@@ -18,14 +18,6 @@
-
- $(DefineConstants);SERIALIZABLE
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Persistence.TCK/Akka.Persistence.TCK.csproj b/src/core/Akka.Persistence.TCK/Akka.Persistence.TCK.csproj
index a8660db1231..20630676aae 100644
--- a/src/core/Akka.Persistence.TCK/Akka.Persistence.TCK.csproj
+++ b/src/core/Akka.Persistence.TCK/Akka.Persistence.TCK.csproj
@@ -20,14 +20,6 @@
-
- $(DefineConstants);SERIALIZATION
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Persistence.TCK/Journal/JournalSpec.cs b/src/core/Akka.Persistence.TCK/Journal/JournalSpec.cs
index 10248194248..c2d5a0d6237 100644
--- a/src/core/Akka.Persistence.TCK/Journal/JournalSpec.cs
+++ b/src/core/Akka.Persistence.TCK/Journal/JournalSpec.cs
@@ -9,10 +9,12 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
+using System.Runtime.Serialization;
using Akka.Actor;
using Akka.Actor.Setup;
using Akka.Configuration;
using Akka.Persistence.TCK.Serialization;
+using Akka.Serialization;
using Akka.TestKit;
using Xunit;
using Xunit.Abstractions;
@@ -324,7 +326,6 @@ public void Journal_should_serialize_events()
Assertions.AssertEqual(_receiverProbe.ExpectMsg().HighestSequenceNr, 6L);
}
-#if !CORECLR
///
/// JSON serializer should fail on this
///
@@ -343,6 +344,35 @@ public void Journal_optionally_may_reject_non_serializable_events()
{
if (!SupportsRejectingNonSerializableObjects) return;
+ // Test that JSON actually fail
+ var serializer = Sys.Serialization.FindSerializerForType(typeof(NotSerializableEvent));
+ if (!(serializer is NewtonSoftJsonSerializer))
+ {
+ Output.WriteLine("[SKIP] This test only works with NewtonSoftJsonSerializer.");
+ return;
+ }
+
+ var serializerFailed = false;
+ try
+ {
+ var serialized = serializer.ToBinary(new NotSerializableEvent(true));
+ var deserialized = serializer.FromBinary(serialized);
+ if (!(deserialized is NotSerializableEvent))
+ throw new Exception();
+ }
+ catch (Exception)
+ {
+ serializerFailed = true;
+ }
+
+ if (!serializerFailed)
+ {
+ Output.WriteLine("[SKIP] This test assumes that the serializer will fail, but it doesn't.");
+ return;
+ }
+ // End test
+
+ // Start of actual test
var msgs = Enumerable.Range(6, 3).Select(i =>
{
var evt = i == 7 ? (object) new NotSerializableEvent(false) : "b-" + i;
@@ -371,6 +401,5 @@ public void Journal_optionally_may_reject_non_serializable_events()
m.Persistent.WriterGuid.Equals(writerGuid) &&
m.Persistent.Payload.Equals("b-8"));
}
-#endif
}
}
diff --git a/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj b/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj
index f85e0a212d3..904e599ab7e 100644
--- a/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj
+++ b/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj
@@ -23,10 +23,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj
index 6d8d97a6971..c13d632210c 100644
--- a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj
+++ b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj
@@ -25,14 +25,6 @@
-
- $(DefineConstants);SERIALIZABLE
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Persistence/Akka.Persistence.csproj b/src/core/Akka.Persistence/Akka.Persistence.csproj
index 2ca58072544..24509b35af6 100644
--- a/src/core/Akka.Persistence/Akka.Persistence.csproj
+++ b/src/core/Akka.Persistence/Akka.Persistence.csproj
@@ -14,9 +14,6 @@
-
- $(DefineConstants);CORECLR
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Persistence/AtLeastOnceDeliverySemantic.cs b/src/core/Akka.Persistence/AtLeastOnceDeliverySemantic.cs
index 37725cccf39..cd919ab6cec 100644
--- a/src/core/Akka.Persistence/AtLeastOnceDeliverySemantic.cs
+++ b/src/core/Akka.Persistence/AtLeastOnceDeliverySemantic.cs
@@ -225,7 +225,6 @@ public MaxUnconfirmedMessagesExceededException(string message, Exception innerEx
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -234,7 +233,6 @@ public MaxUnconfirmedMessagesExceededException(string message, Exception innerEx
protected MaxUnconfirmedMessagesExceededException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
}
#endregion
diff --git a/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs b/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs
index 920670a9a94..ba4bea1f8d5 100644
--- a/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs
+++ b/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs
@@ -37,7 +37,6 @@ public AsyncReplayTimeoutException(string message)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -47,7 +46,6 @@ protected AsyncReplayTimeoutException(SerializationInfo info, StreamingContext c
: base(info, context)
{
}
-#endif
}
///
diff --git a/src/core/Akka.Persistence/PersistentActor.cs b/src/core/Akka.Persistence/PersistentActor.cs
index 37798bd47a9..66c86ba07b6 100644
--- a/src/core/Akka.Persistence/PersistentActor.cs
+++ b/src/core/Akka.Persistence/PersistentActor.cs
@@ -136,7 +136,6 @@ public RecoveryTimedOutException(string message, Exception cause = null) : base(
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -145,7 +144,6 @@ public RecoveryTimedOutException(string message, Exception cause = null) : base(
public RecoveryTimedOutException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
}
///
diff --git a/src/core/Akka.Persistence/Snapshot/NoSnapshotStore.cs b/src/core/Akka.Persistence/Snapshot/NoSnapshotStore.cs
index 7e448c8b619..cc26c7ea503 100644
--- a/src/core/Akka.Persistence/Snapshot/NoSnapshotStore.cs
+++ b/src/core/Akka.Persistence/Snapshot/NoSnapshotStore.cs
@@ -49,7 +49,6 @@ public NoSnapshotStoreException(string message, Exception innerException) : base
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -58,7 +57,6 @@ public NoSnapshotStoreException(string message, Exception innerException) : base
protected NoSnapshotStoreException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
}
///
diff --git a/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj b/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj
index 432597cd86a..85ff907b309 100644
--- a/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj
+++ b/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj
@@ -23,14 +23,6 @@
-
- $(DefineConstants);SERIALIZABLE
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj
index c81855c34ed..d19e3b81d57 100644
--- a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj
+++ b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj
@@ -22,11 +22,7 @@
-
-
- $(DefineConstants);CORECLR
-
-
+
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Remote.TestKit/Controller.cs b/src/core/Akka.Remote.TestKit/Controller.cs
index ef7ced008dc..2954d07e35b 100644
--- a/src/core/Akka.Remote.TestKit/Controller.cs
+++ b/src/core/Akka.Remote.TestKit/Controller.cs
@@ -98,7 +98,6 @@ public class ClientDisconnectedException : AkkaException
/// The message that describes the error.
public ClientDisconnectedException(string message) : base(message){}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -107,7 +106,6 @@ public ClientDisconnectedException(string message) : base(message){}
protected ClientDisconnectedException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
}
public class GetNodes
diff --git a/src/core/Akka.Remote.TestKit/Internals/TestConductorConfigFactory.cs b/src/core/Akka.Remote.TestKit/Internals/TestConductorConfigFactory.cs
index 19bce8cabe4..e880801c02d 100644
--- a/src/core/Akka.Remote.TestKit/Internals/TestConductorConfigFactory.cs
+++ b/src/core/Akka.Remote.TestKit/Internals/TestConductorConfigFactory.cs
@@ -36,11 +36,7 @@ public static Config Default()
/// The configuration defined in the current executing assembly.
internal static Config FromResource(string resourceName)
{
-#if CORECLR
- var assembly = typeof(TestConductorConfigFactory).GetTypeInfo().Assembly;
-#else
var assembly = typeof(TestConductorConfigFactory).Assembly;
-#endif
using (var stream = assembly.GetManifestResourceStream(resourceName))
{
diff --git a/src/core/Akka.Remote.TestKit/MultiNodeSpec.cs b/src/core/Akka.Remote.TestKit/MultiNodeSpec.cs
index d6ef4b7cca5..9e4c97549e4 100644
--- a/src/core/Akka.Remote.TestKit/MultiNodeSpec.cs
+++ b/src/core/Akka.Remote.TestKit/MultiNodeSpec.cs
@@ -408,13 +408,7 @@ protected MultiNodeSpec(
_roles = roles;
_deployments = deployments;
-#if CORECLR
- var dnsTask = Dns.GetHostAddressesAsync(ServerName);
- dnsTask.Wait();
- var node = new IPEndPoint(dnsTask.Result[0], ServerPort);
-#else
var node = new IPEndPoint(Dns.GetHostAddresses(ServerName)[0], ServerPort);
-#endif
_controllerAddr = node;
AttachConductor(new TestConductor(system));
diff --git a/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj b/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj
index b5c14a11e32..aa0d86570ea 100644
--- a/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj
+++ b/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj
@@ -27,10 +27,6 @@
$(DefineConstants);
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Remote.Tests/ExceptionSupportSpec.cs b/src/core/Akka.Remote.Tests/ExceptionSupportSpec.cs
new file mode 100644
index 00000000000..bac4420101f
--- /dev/null
+++ b/src/core/Akka.Remote.Tests/ExceptionSupportSpec.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Akka.Actor;
+using Akka.Configuration;
+using Akka.Dispatch;
+using Akka.IO.Buffers;
+using Akka.Pattern;
+using Akka.Remote.Serialization;
+using Akka.Remote.Transport;
+using Akka.Serialization;
+using Akka.TestKit;
+using Xunit;
+using Xunit.Abstractions;
+using FluentAssertions;
+
+namespace Akka.Remote.Tests
+{
+ public class ExceptionSupportSpec : AkkaSpec
+ {
+ private readonly ExceptionSupport _serializer;
+ private readonly Exception _innerException = new Exception("inner message");
+ private readonly Exception _innerException2 = new Exception("inner message 2");
+
+ public ExceptionSupportSpec(ITestOutputHelper output) : base(output)
+ {
+ _serializer = new ExceptionSupport((ExtendedActorSystem)Sys);
+ }
+
+ [Theory]
+ [InlineData(new object[]{typeof(ActorInterruptedException)})]
+ [InlineData(new object[]{typeof(ActorNotFoundException)})]
+ [InlineData(new object[]{typeof(InvalidActorNameException)})]
+ [InlineData(new object[]{typeof(LoggerInitializationException)})]
+ [InlineData(new object[]{typeof(StashOverflowException)})]
+ [InlineData(new object[]{typeof(ConfigurationException)})]
+ [InlineData(new object[]{typeof(RejectedExecutionException)})]
+ [InlineData(new object[]{typeof(IllegalStateException)})]
+ [InlineData(new object[]{typeof(RemoteTransportException)})]
+ [InlineData(new object[]{typeof(AkkaProtocolException)})]
+ [InlineData(new object[]{typeof(InvalidAssociationException)})]
+ public void ExceptionSupport_should_serialize_exceptions_with_inner_exception(Type type)
+ {
+ var instance = (Exception) Activator.CreateInstance(type, "TestMessage", _innerException);
+ AssertDefaultsEquals(instance);
+ }
+
+ [Theory]
+ [InlineData(new object[]{typeof(ActorKilledException)})]
+ [InlineData(new object[]{typeof(AskTimeoutException)})]
+ [InlineData(new object[]{typeof(IllegalActorNameException)})]
+ [InlineData(new object[]{typeof(IllegalActorStateException)})]
+ [InlineData(new object[]{typeof(InvalidMessageException)})]
+ [InlineData(new object[]{typeof(SchedulerException)})]
+ [InlineData(new object[]{typeof(BufferPoolAllocationException)})]
+ public void ExceptionSupport_should_serialize_exceptions_with_message(Type type)
+ {
+ var instance = (Exception) Activator.CreateInstance(type, "TestMessage");
+ AssertDefaultsEquals(instance);
+ }
+
+ [Theory]
+ [InlineData(new object[]{typeof(UserCalledFailException)})]
+ public void ExceptionSupport_should_serialize_exceptions(Type type)
+ {
+ var instance = (Exception) Activator.CreateInstance(type, new object[]{});
+ AssertDefaultsEquals(instance);
+ }
+
+ [Fact]
+ public void ExceptionSupport_should_serialize_ActorInitializationException()
+ {
+ var probe = CreateTestProbe();
+ var exception = AssertDefaultsEquals(new ActorInitializationException(probe.Ref, "TestMessage", _innerException));
+
+ exception.Actor.Should().NotBeNull();
+ exception.Actor.Equals(probe).Should().BeTrue();
+ }
+
+ [Fact]
+ public void ExceptionSupport_should_serialize_DeathPactException()
+ {
+ var probe = CreateTestProbe();
+ var exception = AssertDefaultsEquals(new DeathPactException(probe.Ref));
+
+ exception.DeadActor.Should().NotBeNull();
+ exception.DeadActor.Equals(probe).Should().BeTrue();
+ }
+
+ [Fact]
+ public void ExceptionSupport_should_serialize_PostRestartException()
+ {
+ var probe = CreateTestProbe();
+ var exception = AssertDefaultsEquals(new PostRestartException(probe.Ref, _innerException, _innerException2));
+
+ exception.Actor.Should().NotBeNull();
+ exception.Actor.Equals(probe).Should().BeTrue();
+ AssertExceptionEquals(_innerException2, exception.OriginalCause);
+ }
+
+ [Fact]
+ public void ExceptionSupport_should_serialize_PreRestartException()
+ {
+ var probe = CreateTestProbe();
+ var testMessage = new
+ {
+ value = 1
+ };
+ var exception = AssertDefaultsEquals(new PreRestartException(probe.Ref, _innerException2, _innerException, testMessage));
+
+ exception.Actor.Should().NotBeNull();
+ exception.Actor.Equals(probe).Should().BeTrue();
+ AssertExceptionEquals(_innerException2, exception.RestartException);
+ exception.OptionalMessage.Should().BeEquivalentTo(testMessage);
+ }
+
+ [Fact]
+ public void ExceptionSupport_should_serialize_OpenCircuitException()
+ {
+ var remaining = new TimeSpan(1234567);
+ var exception = AssertDefaultsEquals(new OpenCircuitException("TestMessage", _innerException, remaining));
+
+ exception.RemainingDuration.Should().Be(remaining);
+ }
+
+ private T AssertDefaultsEquals(T expected) where T: Exception
+ {
+ var serialized = _serializer.ExceptionToProto(expected);
+ var deserialized = (T)_serializer.ExceptionFromProto(serialized);
+
+ AssertExceptionEquals(expected, deserialized);
+
+ return deserialized;
+ }
+
+ private void AssertExceptionEquals(Exception expected, Exception actual)
+ {
+ actual.Message.Should().Be(expected.Message);
+ // HResult is not serialized
+ // actual.HResult.Should().Be(expected.HResult);
+ actual.Source.Should().Be(expected.Source);
+ actual.StackTrace.Should().Be(expected.StackTrace);
+ actual.TargetSite.Should().BeEquivalentTo(expected.TargetSite);
+ if (actual.InnerException != null)
+ {
+ AssertExceptionEquals(actual.InnerException, expected.InnerException);
+ }
+ }
+ }
+}
diff --git a/src/core/Akka.Remote.Tests/Serialization/PrimitiveSerializersSpec.cs b/src/core/Akka.Remote.Tests/Serialization/PrimitiveSerializersSpec.cs
index aa8fe99a79d..2cc9bbd4561 100644
--- a/src/core/Akka.Remote.Tests/Serialization/PrimitiveSerializersSpec.cs
+++ b/src/core/Akka.Remote.Tests/Serialization/PrimitiveSerializersSpec.cs
@@ -8,6 +8,7 @@
using Akka.Configuration;
using Akka.Remote.Configuration;
using Akka.Remote.Serialization;
+using Akka.Serialization;
using Akka.TestKit;
using FluentAssertions;
using Xunit;
@@ -57,16 +58,29 @@ public void Can_serialize_String(string value)
private T AssertAndReturn(T message)
{
- var serializer = Sys.Serialization.FindSerializerFor(message);
+ var serializer = (SerializerWithStringManifest)Sys.Serialization.FindSerializerFor(message);
serializer.Should().BeOfType();
var serializedBytes = serializer.ToBinary(message);
- return (T)serializer.FromBinary(serializedBytes, typeof(T));
+ var manifest = serializer.Manifest(message);
+ return (T)serializer.FromBinary(serializedBytes, manifest);
+ }
+
+ private T AssertCrossPlatformAndReturn(T message)
+ {
+ var serializer = (SerializerWithStringManifest)Sys.Serialization.FindSerializerFor(message);
+ serializer.Should().BeOfType();
+ var serializedBytes = serializer.ToBinary(message);
+ // GetType() will make sure that each namespace is compatible with the serializer
+ // as the test is run on each platform.
+ return (T)serializer.FromBinary(serializedBytes, message.GetType());
}
private void AssertEqual(T message)
{
var deserialized = AssertAndReturn(message);
Assert.Equal(message, deserialized);
+ deserialized = AssertCrossPlatformAndReturn(message);
+ Assert.Equal(message, deserialized);
}
}
}
diff --git a/src/core/Akka.Remote/AckedDelivery.cs b/src/core/Akka.Remote/AckedDelivery.cs
index bdd1ba1d359..e9ad344d36e 100644
--- a/src/core/Akka.Remote/AckedDelivery.cs
+++ b/src/core/Akka.Remote/AckedDelivery.cs
@@ -341,7 +341,6 @@ public ResendBufferCapacityReachedException(int c)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -351,7 +350,6 @@ protected ResendBufferCapacityReachedException(SerializationInfo info, Streaming
: base(info, context)
{
}
-#endif
}
///
@@ -365,6 +363,17 @@ internal class ResendUnfulfillableException : AkkaException
public ResendUnfulfillableException()
: base("Unable to fulfill resend request since negatively acknowledged payload is no longer in buffer. " +
"The resend states between two systems are compromised and cannot be recovered") { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected ResendUnfulfillableException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+
}
#endregion
diff --git a/src/core/Akka.Remote/Akka.Remote.csproj b/src/core/Akka.Remote/Akka.Remote.csproj
index 24f27dca6f8..5b1f41f9715 100644
--- a/src/core/Akka.Remote/Akka.Remote.csproj
+++ b/src/core/Akka.Remote/Akka.Remote.csproj
@@ -15,9 +15,6 @@
-
- $(DefineConstants);CORECLR
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Remote/Endpoint.cs b/src/core/Akka.Remote/Endpoint.cs
index 77ee4275174..607eef5e67d 100644
--- a/src/core/Akka.Remote/Endpoint.cs
+++ b/src/core/Akka.Remote/Endpoint.cs
@@ -191,7 +191,6 @@ internal class EndpointException : AkkaException
/// The exception that is the cause of the current exception.
public EndpointException(string message, Exception cause = null) : base(message, cause) { }
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -201,7 +200,6 @@ protected EndpointException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
-#endif
}
///
@@ -325,6 +323,16 @@ public EndpointDisassociatedException(string message)
: base(message)
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected EndpointDisassociatedException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
///
@@ -347,6 +355,16 @@ public EndpointAssociationException(string message)
/// The message that describes the error.
/// The exception that is the cause of the current exception.
public EndpointAssociationException(string message, Exception innerException) : base(message, innerException) { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected EndpointAssociationException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
///
@@ -362,6 +380,16 @@ public OversizedPayloadException(string message)
: base(message)
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected OversizedPayloadException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
#endregion
diff --git a/src/core/Akka.Remote/RemoteTransport.cs b/src/core/Akka.Remote/RemoteTransport.cs
index d3243b21327..2798544a919 100644
--- a/src/core/Akka.Remote/RemoteTransport.cs
+++ b/src/core/Akka.Remote/RemoteTransport.cs
@@ -132,7 +132,6 @@ public RemoteTransportException(string message, Exception cause = null)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -142,7 +141,6 @@ protected RemoteTransportException(SerializationInfo info, StreamingContext cont
: base(info, context)
{
}
-#endif
}
}
diff --git a/src/core/Akka.Remote/RemoteWatcher.cs b/src/core/Akka.Remote/RemoteWatcher.cs
index ce8a8e81231..67ed6d7e631 100644
--- a/src/core/Akka.Remote/RemoteWatcher.cs
+++ b/src/core/Akka.Remote/RemoteWatcher.cs
@@ -54,6 +54,7 @@ public static Props Props(
TimeSpan heartbeatExpectedResponseAfter)
{
return Actor.Props.Create(() => new RemoteWatcher(failureDetector, heartbeatInterval, unreachableReaperInterval, heartbeatExpectedResponseAfter))
+ .WithDispatcher(Dispatchers.InternalDispatcherId)
.WithDeploy(Deploy.Local);
}
diff --git a/src/core/Akka.Remote/Serialization/ExceptionSupport.cs b/src/core/Akka.Remote/Serialization/ExceptionSupport.cs
index ca221573d2f..52e6a2b89ab 100644
--- a/src/core/Akka.Remote/Serialization/ExceptionSupport.cs
+++ b/src/core/Akka.Remote/Serialization/ExceptionSupport.cs
@@ -13,9 +13,8 @@
using Akka.Util;
using Akka.Util.Internal;
using Google.Protobuf;
-#if SERIALIZATION
using System.Runtime.Serialization;
-#endif
+using Akka.Remote.Serialization.Proto.Msg;
namespace Akka.Remote.Serialization
{
@@ -23,7 +22,7 @@ internal class ExceptionSupport
{
private readonly WrappedPayloadSupport _wrappedPayloadSupport;
private const BindingFlags All = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
- private HashSet DefaultProperties = new HashSet
+ private readonly HashSet _defaultProperties = new HashSet
{
"ClassName",
"Message",
@@ -54,11 +53,7 @@ public byte[] SerializeException(Exception exception)
internal Proto.Msg.ExceptionData ExceptionToProto(Exception exception)
{
-#if SERIALIZATION
return ExceptionToProtoNet(exception);
-#else
- return ExceptionToProtoNetCore(exception);
-#endif
}
public Exception DeserializeException(byte[] bytes)
@@ -69,15 +64,10 @@ public Exception DeserializeException(byte[] bytes)
internal Exception ExceptionFromProto(Proto.Msg.ExceptionData proto)
{
-#if SERIALIZATION
return ExceptionFromProtoNet(proto);
-#else
- return ExceptionFromProtoNetCore(proto);
-#endif
}
-#if SERIALIZATION
- private FormatterConverter DefaultFormatterConverter = new FormatterConverter();
+ private readonly FormatterConverter _defaultFormatterConverter = new FormatterConverter();
public Proto.Msg.ExceptionData ExceptionToProtoNet(Exception exception)
{
@@ -95,14 +85,22 @@ public Proto.Msg.ExceptionData ExceptionToProtoNet(Exception exception)
message.InnerException = ExceptionToProto(exception.InnerException);
var serializable = exception as ISerializable;
- var serializationInfo = new SerializationInfo(exceptionType, DefaultFormatterConverter);
+ var serializationInfo = new SerializationInfo(exceptionType, _defaultFormatterConverter);
serializable.GetObjectData(serializationInfo, new StreamingContext());
foreach (var info in serializationInfo)
{
- if (DefaultProperties.Contains(info.Name)) continue;
- var preparedValue = _wrappedPayloadSupport.PayloadToProto(info.Value);
- message.CustomFields.Add(info.Name, preparedValue);
+ if (_defaultProperties.Contains(info.Name)) continue;
+ if (info.Value is Exception exceptionValue)
+ {
+ var exceptionPayload = ExceptionToProto(exceptionValue);
+ var preparedValue = _wrappedPayloadSupport.PayloadToProto(exceptionPayload);
+ message.CustomFields.Add(info.Name, preparedValue);
+ } else
+ {
+ var preparedValue = _wrappedPayloadSupport.PayloadToProto(info.Value);
+ message.CustomFields.Add(info.Name, preparedValue);
+ }
}
return message;
@@ -115,22 +113,25 @@ public Exception ExceptionFromProtoNet(Proto.Msg.ExceptionData proto)
Type exceptionType = Type.GetType(proto.TypeName);
- var serializationInfo = new SerializationInfo(exceptionType, DefaultFormatterConverter);
+ var serializationInfo = new SerializationInfo(exceptionType, _defaultFormatterConverter);
serializationInfo.AddValue("ClassName", proto.TypeName);
- serializationInfo.AddValue("Message", proto.Message);
- serializationInfo.AddValue("StackTraceString", proto.StackTrace);
- serializationInfo.AddValue("Source", proto.Source);
+ serializationInfo.AddValue("Message", ValueOrNull(proto.Message));
+ serializationInfo.AddValue("StackTraceString", ValueOrNull(proto.StackTrace));
+ serializationInfo.AddValue("Source", ValueOrNull(proto.Source));
serializationInfo.AddValue("InnerException", ExceptionFromProto(proto.InnerException));
serializationInfo.AddValue("HelpURL", string.Empty);
- serializationInfo.AddValue("RemoteStackTraceString", string.Empty);
+ serializationInfo.AddValue("RemoteStackTraceString", null);
serializationInfo.AddValue("RemoteStackIndex", 0);
- serializationInfo.AddValue("ExceptionMethod", string.Empty);
+ serializationInfo.AddValue("ExceptionMethod", null);
serializationInfo.AddValue("HResult", int.MinValue);
foreach (var field in proto.CustomFields)
{
- serializationInfo.AddValue(field.Key, _wrappedPayloadSupport.PayloadFrom(field.Value));
+ var payload = _wrappedPayloadSupport.PayloadFrom(field.Value);
+ if (payload is ExceptionData exception)
+ payload = ExceptionFromProto(exception);
+ serializationInfo.AddValue(field.Key, payload);
}
Exception obj = null;
@@ -148,71 +149,8 @@ public Exception ExceptionFromProtoNet(Proto.Msg.ExceptionData proto)
return obj;
}
-#else
- private TypeInfo ExceptionTypeInfo = typeof(Exception).GetTypeInfo();
-
- internal Proto.Msg.ExceptionData ExceptionToProtoNetCore(Exception exception)
- {
- var message = new Proto.Msg.ExceptionData();
-
- if (exception == null)
- return message;
-
- var exceptionType = exception.GetType();
-
- message.TypeName = exceptionType.TypeQualifiedName();
- message.Message = exception.Message;
- message.StackTrace = exception.StackTrace ?? "";
- message.Source = exception.Source ?? "";
- message.InnerException = ExceptionToProto(exception.InnerException);
-
- // serialize all public properties
- foreach (var property in exceptionType.GetTypeInfo().DeclaredProperties)
- {
- if (DefaultProperties.Contains(property.Name)) continue;
- if (property.SetMethod != null)
- {
- message.CustomFields.Add(property.Name, _wrappedPayloadSupport.PayloadToProto(property.GetValue(exception)));
- }
- }
-
- return message;
- }
-
- internal Exception ExceptionFromProtoNetCore(Proto.Msg.ExceptionData proto)
- {
- if (string.IsNullOrEmpty(proto.TypeName))
- return null;
-
- Type exceptionType = Type.GetType(proto.TypeName);
-
- var obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(exceptionType);
- if (!string.IsNullOrEmpty(proto.Message))
- ExceptionTypeInfo?.GetField("_message", All)?.SetValue(obj, proto.Message);
-
- if (!string.IsNullOrEmpty(proto.StackTrace))
- ExceptionTypeInfo?.GetField("_stackTraceString", All)?.SetValue(obj, proto.StackTrace);
-
- if (!string.IsNullOrEmpty(proto.Source))
- ExceptionTypeInfo?.GetField("_source", All)?.SetValue(obj, proto.Source);
-
- if (!string.IsNullOrEmpty(proto.InnerException.TypeName))
- ExceptionTypeInfo?.GetField("_innerException", All)?.SetValue(obj, ExceptionFromProto(proto.InnerException));
-
- // deserialize all public properties with setters
- foreach (var property in proto.CustomFields)
- {
- if (DefaultProperties.Contains(property.Key)) continue;
- var prop = exceptionType.GetProperty(property.Key, All);
- if (prop.SetMethod != null)
- {
- prop.SetValue(obj, _wrappedPayloadSupport.PayloadFrom(property.Value));
- }
- }
-
- return (Exception)obj;
- }
-#endif
+ private string ValueOrNull(string value)
+ => string.IsNullOrEmpty(value) ? null : value;
}
}
diff --git a/src/core/Akka.Remote/Serialization/PrimitiveSerializers.cs b/src/core/Akka.Remote/Serialization/PrimitiveSerializers.cs
index 21c7a5665fb..f8716c10f36 100644
--- a/src/core/Akka.Remote/Serialization/PrimitiveSerializers.cs
+++ b/src/core/Akka.Remote/Serialization/PrimitiveSerializers.cs
@@ -13,8 +13,22 @@
namespace Akka.Remote.Serialization
{
- public sealed class PrimitiveSerializers : Serializer
+ public sealed class PrimitiveSerializers : SerializerWithStringManifest
{
+ internal const string StringManifest = "S";
+ internal const string Int32Manifest = "I";
+ internal const string Int64Manifest = "L";
+
+ // .Net Core manifests
+ internal const string StringManifestNetCore = "System.String, System.Private.CoreLib";
+ internal const string Int32ManifestNetCore = "System.Int32, System.Private.CoreLib";
+ internal const string Int64ManifestNetCore = "System.Int64, System.Private.CoreLib";
+
+ // .Net Framework manifests
+ internal const string StringManifestNetFx = "System.String, mscorlib";
+ internal const string Int32ManifestNetFx = "System.Int32, mscorlib";
+ internal const string Int64ManifestNetFx = "System.Int64, mscorlib";
+
///
/// Initializes a new instance of the class.
///
@@ -23,28 +37,58 @@ public PrimitiveSerializers(ExtendedActorSystem system) : base(system)
{
}
- ///
- public override bool IncludeManifest { get; } = true;
-
///
public override byte[] ToBinary(object obj)
{
- var str = obj as string;
- if (str != null) return Encoding.UTF8.GetBytes(str);
- if (obj is int) return BitConverter.GetBytes((int)obj);
- if (obj is long) return BitConverter.GetBytes((long)obj);
-
- throw new ArgumentException($"Cannot serialize object of type [{obj.GetType().TypeQualifiedName()}]");
+ switch (obj)
+ {
+ case string s:
+ return Encoding.UTF8.GetBytes(s);
+ case int i:
+ return BitConverter.GetBytes(i);
+ case long l:
+ return BitConverter.GetBytes(l);
+ default:
+ throw new ArgumentException($"Cannot serialize object of type [{obj.GetType()}]");
+ }
}
///
- public override object FromBinary(byte[] bytes, Type type)
+ public override object FromBinary(byte[] bytes, string manifest)
{
- if (type == typeof(string)) return Encoding.UTF8.GetString(bytes);
- if (type == typeof(int)) return BitConverter.ToInt32(bytes, 0);
- if (type == typeof(long)) return BitConverter.ToInt64(bytes, 0);
+ switch (manifest)
+ {
+ case StringManifest:
+ case StringManifestNetCore:
+ case StringManifestNetFx:
+ return Encoding.UTF8.GetString(bytes);
+ case Int32Manifest:
+ case Int32ManifestNetCore:
+ case Int32ManifestNetFx:
+ return BitConverter.ToInt32(bytes, 0);
+ case Int64Manifest:
+ case Int64ManifestNetCore:
+ case Int64ManifestNetFx:
+ return BitConverter.ToInt64(bytes, 0);
+ default:
+ throw new ArgumentException($"Unimplemented deserialization of message with manifest [{manifest}] in [${GetType()}]");
+ }
+ }
- throw new ArgumentException($"Unimplemented deserialization of message with manifest [{type.TypeQualifiedName()}] in [${nameof(PrimitiveSerializers)}]");
+ ///
+ public override string Manifest(object obj)
+ {
+ switch (obj)
+ {
+ case string _:
+ return StringManifest;
+ case int _:
+ return Int32Manifest;
+ case long _:
+ return Int64Manifest;
+ default:
+ throw new ArgumentException($"Cannot serialize object of type [{obj.GetType()}] in [{GetType()}]");
+ }
}
}
}
diff --git a/src/core/Akka.Remote/Transport/AkkaPduCodec.cs b/src/core/Akka.Remote/Transport/AkkaPduCodec.cs
index bba9c376eed..bde6e0baf27 100644
--- a/src/core/Akka.Remote/Transport/AkkaPduCodec.cs
+++ b/src/core/Akka.Remote/Transport/AkkaPduCodec.cs
@@ -28,7 +28,6 @@ internal class PduCodecException : AkkaException
/// The exception that is the cause of the current exception.
public PduCodecException(string message, Exception cause = null) : base(message, cause) { }
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -38,7 +37,6 @@ protected PduCodecException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
-#endif
}
/*
diff --git a/src/core/Akka.Remote/Transport/AkkaProtocolTransport.cs b/src/core/Akka.Remote/Transport/AkkaProtocolTransport.cs
index 8d00793b9e4..cdb8a62239c 100644
--- a/src/core/Akka.Remote/Transport/AkkaProtocolTransport.cs
+++ b/src/core/Akka.Remote/Transport/AkkaProtocolTransport.cs
@@ -63,7 +63,6 @@ public class AkkaProtocolException : AkkaException
/// The exception that is the cause of the current exception.
public AkkaProtocolException(string message, Exception cause = null) : base(message, cause) { }
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -73,7 +72,6 @@ protected AkkaProtocolException(SerializationInfo info, StreamingContext context
: base(info, context)
{
}
-#endif
}
///
diff --git a/src/core/Akka.Remote/Transport/DotNetty/DotNettyTransport.cs b/src/core/Akka.Remote/Transport/DotNetty/DotNettyTransport.cs
index f5d7db8754f..49f1bbf497c 100644
--- a/src/core/Akka.Remote/Transport/DotNetty/DotNettyTransport.cs
+++ b/src/core/Akka.Remote/Transport/DotNetty/DotNettyTransport.cs
@@ -104,7 +104,6 @@ public DotNettyTransportException(string message, Exception cause = null) : base
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -113,7 +112,6 @@ public DotNettyTransportException(string message, Exception cause = null) : base
protected DotNettyTransportException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
}
internal abstract class DotNettyTransport : Transport
diff --git a/src/core/Akka.Remote/Transport/FailureInjectorTransportAdapter.cs b/src/core/Akka.Remote/Transport/FailureInjectorTransportAdapter.cs
index 5b945814707..61cad66ed6d 100644
--- a/src/core/Akka.Remote/Transport/FailureInjectorTransportAdapter.cs
+++ b/src/core/Akka.Remote/Transport/FailureInjectorTransportAdapter.cs
@@ -48,7 +48,6 @@ public FailureInjectorException(string msg)
Msg = msg;
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -58,7 +57,6 @@ private FailureInjectorException(SerializationInfo info, StreamingContext contex
: base(info, context)
{
}
-#endif
///
/// Retrieves the message of the simulated failure.
diff --git a/src/core/Akka.Remote/Transport/Transport.cs b/src/core/Akka.Remote/Transport/Transport.cs
index 0c52624adae..7fc11d11fa1 100644
--- a/src/core/Akka.Remote/Transport/Transport.cs
+++ b/src/core/Akka.Remote/Transport/Transport.cs
@@ -99,7 +99,6 @@ public InvalidAssociationException(string message, Exception cause = null)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -109,7 +108,6 @@ protected InvalidAssociationException(SerializationInfo info, StreamingContext c
: base(info, context)
{
}
-#endif
}
///
diff --git a/src/core/Akka.Streams.TestKit.Tests/Akka.Streams.TestKit.Tests.csproj b/src/core/Akka.Streams.TestKit.Tests/Akka.Streams.TestKit.Tests.csproj
index ee0f34ae59b..97bb9020904 100644
--- a/src/core/Akka.Streams.TestKit.Tests/Akka.Streams.TestKit.Tests.csproj
+++ b/src/core/Akka.Streams.TestKit.Tests/Akka.Streams.TestKit.Tests.csproj
@@ -25,14 +25,6 @@
-
- $(DefineConstants);SERIALIZATION;AKKAIO
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Streams.TestKit.Tests/ScriptedTest.cs b/src/core/Akka.Streams.TestKit.Tests/ScriptedTest.cs
index e3009182572..903fc39b200 100644
--- a/src/core/Akka.Streams.TestKit.Tests/ScriptedTest.cs
+++ b/src/core/Akka.Streams.TestKit.Tests/ScriptedTest.cs
@@ -27,10 +27,7 @@ public class ScriptException : Exception
public ScriptException() { }
public ScriptException(string message) : base(message) { }
public ScriptException(string message, Exception inner) : base(message, inner) { }
-
-#if SERIALIZATION
protected ScriptException(SerializationInfo info, StreamingContext context) : base(info, context) { }
-#endif
}
public abstract class ScriptedTest : AkkaSpec
diff --git a/src/core/Akka.Streams.TestKit/Akka.Streams.TestKit.csproj b/src/core/Akka.Streams.TestKit/Akka.Streams.TestKit.csproj
index b423898c67f..a550bdd7f82 100644
--- a/src/core/Akka.Streams.TestKit/Akka.Streams.TestKit.csproj
+++ b/src/core/Akka.Streams.TestKit/Akka.Streams.TestKit.csproj
@@ -14,10 +14,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Streams.TestKit/TestSubscriber.cs b/src/core/Akka.Streams.TestKit/TestSubscriber.cs
index 39fee165fa4..ef045d46b00 100644
--- a/src/core/Akka.Streams.TestKit/TestSubscriber.cs
+++ b/src/core/Akka.Streams.TestKit/TestSubscriber.cs
@@ -34,7 +34,7 @@ public OnSubscribe(ISubscription subscription)
public override string ToString() => $"TestSubscriber.OnSubscribe({Subscription})";
}
- public struct OnNext : ISubscriberEvent
+ public struct OnNext : ISubscriberEvent, IEquatable>
{
public readonly T Element;
@@ -44,6 +44,21 @@ public OnNext(T element)
}
public override string ToString() => $"TestSubscriber.OnNext({Element})";
+
+ public bool Equals(OnNext other)
+ {
+ return EqualityComparer.Default.Equals(Element, other.Element);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is OnNext other && Equals(other);
+ }
+
+ public override int GetHashCode()
+ {
+ return EqualityComparer.Default.GetHashCode(Element);
+ }
}
public sealed class OnComplete: ISubscriberEvent
diff --git a/src/core/Akka.Streams.Tests/Akka.Streams.Tests.csproj b/src/core/Akka.Streams.Tests/Akka.Streams.Tests.csproj
index aea0d2dbbcb..b28f8f02ec2 100644
--- a/src/core/Akka.Streams.Tests/Akka.Streams.Tests.csproj
+++ b/src/core/Akka.Streams.Tests/Akka.Streams.Tests.csproj
@@ -35,14 +35,6 @@
-
- $(DefineConstants);SERIALIZATION;CONFIGURATION;AKKAIO
-
-
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Streams.Tests/Dsl/QueueSinkSpec.cs b/src/core/Akka.Streams.Tests/Dsl/QueueSinkSpec.cs
index 1d80932b3e3..e9aefadff79 100644
--- a/src/core/Akka.Streams.Tests/Dsl/QueueSinkSpec.cs
+++ b/src/core/Akka.Streams.Tests/Dsl/QueueSinkSpec.cs
@@ -153,7 +153,7 @@ public void QueueSink_should_timeout_future_when_stream_cannot_provide_data()
}, _materializer);
}
- [Fact(Skip = "Racy, see https://github.com/akkadotnet/akka.net/pull/4424#issuecomment-632284459")]
+ [Fact]
public void QueueSink_should_fail_pull_future_when_stream_is_completed()
{
this.AssertAllStagesStopped(() =>
@@ -170,10 +170,8 @@ public void QueueSink_should_fail_pull_future_when_stream_is_completed()
var result = queue.PullAsync().Result;
result.Should().Be(Option.None);
- ((Task)queue.PullAsync()).ContinueWith(t =>
- {
- t.Exception.InnerException.Should().BeOfType();
- }, TaskContinuationOptions.OnlyOnFaulted).Wait();
+ var exception = Record.ExceptionAsync(async () => await queue.PullAsync()).Result;
+ exception.Should().BeOfType();
}, _materializer);
}
diff --git a/src/core/Akka.Streams.Tests/Dsl/QueueSourceSpec.cs b/src/core/Akka.Streams.Tests/Dsl/QueueSourceSpec.cs
index 11a39f98532..9e1d124236b 100644
--- a/src/core/Akka.Streams.Tests/Dsl/QueueSourceSpec.cs
+++ b/src/core/Akka.Streams.Tests/Dsl/QueueSourceSpec.cs
@@ -261,6 +261,22 @@ public void QueueSource_should_complete_watching_future_with_failure_if_stream_f
}, _materializer);
}
+ [Fact]
+ public void QueueSource_should_complete_watching_future_with_failure_if_materializer_shut_down()
+ {
+ this.AssertAllStagesStopped(() =>
+ {
+ var tempMap = ActorMaterializer.Create(Sys);
+ var s = this.CreateManualSubscriberProbe();
+ var queue = Source.Queue(1, OverflowStrategy.Fail)
+ .To(Sink.FromSubscriber(s))
+ .Run(tempMap);
+ queue.WatchCompletionAsync().PipeTo(TestActor);
+ tempMap.Shutdown();
+ ExpectMsg();
+ }, _materializer);
+ }
+
[Fact]
public void QueueSource_should_return_false_when_element_was_not_added_to_buffer()
{
@@ -322,11 +338,12 @@ public void QueueSource_should_fail_offer_future_when_stream_is_completed()
.Run(_materializer);
var sub = s.ExpectSubscription();
- queue.WatchCompletionAsync().ContinueWith(t => "done").PipeTo(TestActor);
+ queue.WatchCompletionAsync().ContinueWith(t => Done.Instance).PipeTo(TestActor);
sub.Cancel();
- ExpectMsg("done");
+ ExpectMsg(Done.Instance);
- queue.OfferAsync(1).ContinueWith(t => t.Exception.Should().BeOfType());
+ var exception = Record.ExceptionAsync(async () => await queue.OfferAsync(1)).Result;
+ exception.Should().BeOfType();
}, _materializer);
}
diff --git a/src/core/Akka.Streams.Tests/Dsl/StageActorRefSpec.cs b/src/core/Akka.Streams.Tests/Dsl/StageActorRefSpec.cs
index 04e67b704b1..2cd4f9b68dc 100644
--- a/src/core/Akka.Streams.Tests/Dsl/StageActorRefSpec.cs
+++ b/src/core/Akka.Streams.Tests/Dsl/StageActorRefSpec.cs
@@ -178,7 +178,7 @@ public async Task A_Graph_stage_ActorRef_must_ignore_and_log_warnings_for_Poison
warn.Message.ToString()
.Should()
.MatchRegex(
- " message sent to StageActor\\(akka\\://AkkaSpec/user/StreamSupervisor-[0-9]+/\\$\\$[a-z]+\\) will be ignored, since it is not a real Actor. Use a custom message type to communicate with it instead.");
+ $" message sent to StageActor\\(akka\\://{Sys.Name}/user/StreamSupervisor-[0-9]+/\\$\\$[a-z]+\\) will be ignored, since it is not a real Actor. Use a custom message type to communicate with it instead.");
stageRef.Tell(Kill.Instance);
warn = ExpectMsg(TimeSpan.FromSeconds(1));
@@ -186,7 +186,7 @@ public async Task A_Graph_stage_ActorRef_must_ignore_and_log_warnings_for_Poison
warn.Message.ToString()
.Should()
.MatchRegex(
- " message sent to StageActor\\(akka\\://AkkaSpec/user/StreamSupervisor-[0-9]+/\\$\\$[a-z]+\\) will be ignored, since it is not a real Actor. Use a custom message type to communicate with it instead.");
+ $" message sent to StageActor\\(akka\\://{Sys.Name}/user/StreamSupervisor-[0-9]+/\\$\\$[a-z]+\\) will be ignored, since it is not a real Actor. Use a custom message type to communicate with it instead.");
source.SetResult(2);
diff --git a/src/core/Akka.Streams.Tests/Implementation/StreamLayoutSpec.cs b/src/core/Akka.Streams.Tests/Implementation/StreamLayoutSpec.cs
index 7f3f7c5aeec..d8bef953f4b 100644
--- a/src/core/Akka.Streams.Tests/Implementation/StreamLayoutSpec.cs
+++ b/src/core/Akka.Streams.Tests/Implementation/StreamLayoutSpec.cs
@@ -240,7 +240,6 @@ public void StreamLayout_should_be_able_to_materialize_linear_layouts()
CheckMaterialized(runnable);
}
-#if !CORECLR
[Fact(Skip = "We can't catch a StackOverflowException")]
public void StreamLayout_should_fail_fusing_when_value_computation_is_too_complex()
{
@@ -250,7 +249,6 @@ public void StreamLayout_should_fail_fusing_when_value_computation_is_too_comple
(flow, i) => flow.MapMaterializedValue(x => x + i));
g.Invoking(flow => Streams.Fusing.Aggressive(flow)).Should().Throw();
}
-#endif
[Fact]
public void StreamLayout_should_not_fail_materialization_when_building_a_large_graph_with_simple_computation_when_starting_from_a_Source()
diff --git a/src/core/Akka.Streams/ActorMaterializer.cs b/src/core/Akka.Streams/ActorMaterializer.cs
index 5f1666b005b..7392e70d11e 100644
--- a/src/core/Akka.Streams/ActorMaterializer.cs
+++ b/src/core/Akka.Streams/ActorMaterializer.cs
@@ -242,7 +242,6 @@ public AbruptTerminationException(IActorRef actor)
Actor = actor;
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -252,7 +251,6 @@ protected AbruptTerminationException(SerializationInfo info, StreamingContext co
{
Actor = (IActorRef)info.GetValue("Actor", typeof(IActorRef));
}
-#endif
}
///
@@ -267,14 +265,12 @@ public class MaterializationException : Exception
/// The exception that is the cause of the current exception.
public MaterializationException(string message, Exception innerException) : base(message, innerException) { }
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
/// The that holds the serialized object data about the exception being thrown.
/// The that contains contextual information about the source or destination.
protected MaterializationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
-#endif
}
///
@@ -289,6 +285,13 @@ public AbruptStageTerminationException(GraphStageLogic logic)
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected AbruptStageTerminationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
diff --git a/src/core/Akka.Streams/Akka.Streams.csproj b/src/core/Akka.Streams/Akka.Streams.csproj
index ca1b41846f4..e3205c5a705 100644
--- a/src/core/Akka.Streams/Akka.Streams.csproj
+++ b/src/core/Akka.Streams/Akka.Streams.csproj
@@ -65,9 +65,6 @@
-
- $(DefineConstants);CORECLR
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Streams/Dsl/Framing.cs b/src/core/Akka.Streams/Dsl/Framing.cs
index db48898e4ff..d64d20c8f73 100644
--- a/src/core/Akka.Streams/Dsl/Framing.cs
+++ b/src/core/Akka.Streams/Dsl/Framing.cs
@@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
+using System.Runtime.Serialization;
using Akka.IO;
using Akka.Streams.Implementation.Fusing;
using Akka.Streams.Implementation.Stages;
@@ -122,6 +123,13 @@ public class FramingException : Exception
public FramingException(string message) : base(message)
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected FramingException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
private static readonly Func, int, int> BigEndianDecoder = (enumerator, length) =>
diff --git a/src/core/Akka.Streams/Dsl/Graph.cs b/src/core/Akka.Streams/Dsl/Graph.cs
index aa9bd798d67..cba7566f66a 100644
--- a/src/core/Akka.Streams/Dsl/Graph.cs
+++ b/src/core/Akka.Streams/Dsl/Graph.cs
@@ -9,6 +9,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
+using System.Runtime.Serialization;
using Akka.Streams.Implementation;
using Akka.Streams.Implementation.Fusing;
using Akka.Streams.Implementation.Stages;
@@ -1211,6 +1212,13 @@ public PartitionOutOfBoundsException(string message) : base(message)
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected PartitionOutOfBoundsException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
///
diff --git a/src/core/Akka.Streams/Dsl/Keep.cs b/src/core/Akka.Streams/Dsl/Keep.cs
index 5419f23bd2f..09324ad1c51 100644
--- a/src/core/Akka.Streams/Dsl/Keep.cs
+++ b/src/core/Akka.Streams/Dsl/Keep.cs
@@ -56,11 +56,7 @@ public static class Keep
/// TBD
public static NotUsed None(TLeft left, TRight right) => NotUsed.Instance;
-#if !CORECLR
private static readonly RuntimeMethodHandle KeepRightMethodhandle = typeof(Keep).GetMethod(nameof(Right)).MethodHandle;
-#else
- private static readonly MethodInfo KeepRightMethodInfo = typeof(Keep).GetMethod(nameof(Right));
-#endif
///
/// TBD
@@ -72,18 +68,10 @@ public static class Keep
/// TBD
public static bool IsRight(Func fn)
{
-#if !CORECLR
return fn.GetMethodInfo().IsGenericMethod && fn.GetMethodInfo().GetGenericMethodDefinition().MethodHandle.Value == KeepRightMethodhandle.Value;
-#else
- return fn.GetMethodInfo().IsGenericMethod && fn.GetMethodInfo().GetGenericMethodDefinition().Equals(KeepRightMethodInfo);
-#endif
}
-#if !CORECLR
private static readonly RuntimeMethodHandle KeepLeftMethodhandle = typeof(Keep).GetMethod(nameof(Left)).MethodHandle;
-#else
- private static readonly MethodInfo KeepLeftMethodInfo = typeof(Keep).GetMethod(nameof(Left));
-#endif
///
/// TBD
@@ -95,11 +83,7 @@ public static bool IsRight(Func fn)
/// TBD
public static bool IsLeft(Func fn)
{
-#if !CORECLR
return fn.GetMethodInfo().IsGenericMethod && fn.GetMethodInfo().GetGenericMethodDefinition().MethodHandle.Value == KeepLeftMethodhandle.Value;
-#else
- return fn.GetMethodInfo().IsGenericMethod && fn.GetMethodInfo().GetGenericMethodDefinition().Equals(KeepLeftMethodInfo);
-#endif
}
}
}
diff --git a/src/core/Akka.Streams/Dsl/One2OneBidiFlow.cs b/src/core/Akka.Streams/Dsl/One2OneBidiFlow.cs
index 416d9da8cef..1a4b17b16a0 100644
--- a/src/core/Akka.Streams/Dsl/One2OneBidiFlow.cs
+++ b/src/core/Akka.Streams/Dsl/One2OneBidiFlow.cs
@@ -6,6 +6,8 @@
//-----------------------------------------------------------------------
using System;
+using System.Runtime.Serialization;
+using Akka.Pattern;
using Akka.Streams.Stage;
namespace Akka.Streams.Dsl
@@ -41,6 +43,13 @@ public UnexpectedOutputException(object element) : base(element.ToString())
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected UnexpectedOutputException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
///
@@ -48,7 +57,14 @@ public UnexpectedOutputException(object element) : base(element.ToString())
///
public class OutputTruncationException : Exception
{
+ public OutputTruncationException() { }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected OutputTruncationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
///
diff --git a/src/core/Akka.Streams/Dsl/Tcp.cs b/src/core/Akka.Streams/Dsl/Tcp.cs
index e62f13c26df..fb47f267297 100644
--- a/src/core/Akka.Streams/Dsl/Tcp.cs
+++ b/src/core/Akka.Streams/Dsl/Tcp.cs
@@ -8,6 +8,7 @@
using System;
using System.Collections.Immutable;
using System.Net;
+using System.Runtime.Serialization;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Annotations;
@@ -303,6 +304,13 @@ public TcpIdleTimeoutException(string message, TimeSpan duration) : base(message
Duration = duration;
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected TcpIdleTimeoutException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+
public TimeSpan Duration { get; }
}
}
diff --git a/src/core/Akka.Streams/Implementation/ActorPublisher.cs b/src/core/Akka.Streams/Implementation/ActorPublisher.cs
index d0894ade36e..72c764b6772 100644
--- a/src/core/Akka.Streams/Implementation/ActorPublisher.cs
+++ b/src/core/Akka.Streams/Implementation/ActorPublisher.cs
@@ -114,14 +114,12 @@ public class NormalShutdownException : IllegalStateException
/// The message that describes the error.
public NormalShutdownException(string message) : base(message) { }
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
/// The that holds the serialized object data about the exception being thrown.
/// The that contains contextual information about the source or destination.
protected NormalShutdownException(SerializationInfo info, StreamingContext context) : base(info, context) { }
-#endif
}
///
diff --git a/src/core/Akka.Streams/Implementation/ReactiveStreamsCompliance.cs b/src/core/Akka.Streams/Implementation/ReactiveStreamsCompliance.cs
index c3dded30471..cb41aa26b82 100644
--- a/src/core/Akka.Streams/Implementation/ReactiveStreamsCompliance.cs
+++ b/src/core/Akka.Streams/Implementation/ReactiveStreamsCompliance.cs
@@ -30,14 +30,12 @@ public class SignalThrewException : IllegalStateException, ISpecViolation
/// The exception that is the cause of the current exception.
public SignalThrewException(string message, Exception cause) : base(message, cause) { }
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
/// The that holds the serialized object data about the exception being thrown.
/// The that contains contextual information about the source or destination.
protected SignalThrewException(SerializationInfo info, StreamingContext context) : base(info, context) { }
-#endif
}
///
diff --git a/src/core/Akka.Streams/Implementation/ResizableMultiReaderRingBuffer.cs b/src/core/Akka.Streams/Implementation/ResizableMultiReaderRingBuffer.cs
index 43f89471f28..b0ab1226c76 100644
--- a/src/core/Akka.Streams/Implementation/ResizableMultiReaderRingBuffer.cs
+++ b/src/core/Akka.Streams/Implementation/ResizableMultiReaderRingBuffer.cs
@@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.Serialization;
using Akka.Annotations;
using Akka.Streams.Util;
@@ -28,7 +29,6 @@ private NothingToReadException()
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -38,7 +38,6 @@ protected NothingToReadException(SerializationInfo info, StreamingContext contex
: base(info, context)
{
}
-#endif
}
///
diff --git a/src/core/Akka.Streams/Implementation/Sinks.cs b/src/core/Akka.Streams/Implementation/Sinks.cs
index 14356f0f39a..17de6266fb0 100644
--- a/src/core/Akka.Streams/Implementation/Sinks.cs
+++ b/src/core/Akka.Streams/Implementation/Sinks.cs
@@ -624,10 +624,10 @@ public override void OnUpstreamFailure(Exception e)
public override void PostStop()
{
- if(!_completionSignalled)
+ if (!_completionSignalled)
_promise.TrySetException(new AbruptStageTerminationException(this));
}
-
+
public override void PreStart() => Pull(_stage.In);
}
@@ -805,12 +805,8 @@ public override void PreStart()
Pull(_stage.In);
}
- public override void PostStop()
- {
- StopCallback(
- promise =>
- promise.SetException(new IllegalStateException("Stream is terminated. QueueSink is detached")));
- }
+ public override void PostStop() =>
+ StopCallback(promise => promise.SetException(StreamDetachedException.Instance));
private Action>> Callback()
{
@@ -1024,7 +1020,8 @@ private void InitInternalSource(Sink sink, TIn firstElement)
{
var sourceOut = new SubSource(this, firstElement);
- try {
+ try
+ {
var matVal = Source.FromGraph(sourceOut.Source)
.RunWith(sink, Interpreter.SubFusingMaterializer);
_completion.TrySetResult(matVal);
@@ -1034,7 +1031,7 @@ private void InitInternalSource(Sink sink, TIn firstElement)
_completion.TrySetException(ex);
FailStage(ex);
}
-
+
}
#region SubSource
@@ -1176,7 +1173,7 @@ public void Dispose(bool unregister)
}
}
}
-
+
private sealed class ObservableLogic : GraphStageLogic, IObservable
{
private readonly ObservableSinkStage _stage;
@@ -1216,12 +1213,12 @@ public void Remove(IObserver observer)
ImmutableInterlocked.TryRemove(ref _observers, observer, out var _);
}
- public IDisposable Subscribe(IObserver observer) =>
+ public IDisposable Subscribe(IObserver observer) =>
ImmutableInterlocked.GetOrAdd(ref _observers, observer, new ObserverDisposable(this, observer));
}
#endregion
-
+
public ObservableSinkStage()
{
diff --git a/src/core/Akka.Streams/Implementation/Sources.cs b/src/core/Akka.Streams/Implementation/Sources.cs
index f94b0037b62..b4149d36b9c 100644
--- a/src/core/Akka.Streams/Implementation/Sources.cs
+++ b/src/core/Akka.Streams/Implementation/Sources.cs
@@ -7,7 +7,6 @@
using System;
using System.Collections.Generic;
-using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Akka.Annotations;
using Akka.Pattern;
@@ -15,7 +14,6 @@
using Akka.Streams.Implementation.Stages;
using Akka.Streams.Stage;
using Akka.Streams.Supervision;
-using Akka.Streams.Util;
using Akka.Util;
using Akka.Util.Internal;
@@ -170,14 +168,13 @@ public override void PreStart()
public override void PostStop()
{
+ var exception = StreamDetachedException.Instance;
+ _completion.TrySetException(exception);
StopCallback(input =>
{
- var offer = input as Offer;
- if (offer != null)
- {
- var promise = offer.CompletionSource;
- promise.NonBlockingTrySetException(new IllegalStateException("Stream is terminated. SourceQueue is detached."));
- }
+ if (!(input is Offer offer)) return;
+ var promise = offer.CompletionSource;
+ promise.NonBlockingTrySetException(exception);
});
}
diff --git a/src/core/Akka.Streams/Implementation/StreamLayout.cs b/src/core/Akka.Streams/Implementation/StreamLayout.cs
index fe11dea92b9..35ab676c635 100644
--- a/src/core/Akka.Streams/Implementation/StreamLayout.cs
+++ b/src/core/Akka.Streams/Implementation/StreamLayout.cs
@@ -2142,7 +2142,6 @@ public MaterializationPanicException(Exception innerException)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -2152,7 +2151,6 @@ protected MaterializationPanicException(SerializationInfo info, StreamingContext
: base(info, context)
{
}
-#endif
}
///
diff --git a/src/core/Akka.Streams/Implementation/StreamSubscriptionTimeout.cs b/src/core/Akka.Streams/Implementation/StreamSubscriptionTimeout.cs
index 2890edc4468..cd9e6ba3e06 100644
--- a/src/core/Akka.Streams/Implementation/StreamSubscriptionTimeout.cs
+++ b/src/core/Akka.Streams/Implementation/StreamSubscriptionTimeout.cs
@@ -36,7 +36,6 @@ public SubscriptionTimeoutException(string message, Exception innerException) :
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -45,7 +44,6 @@ public SubscriptionTimeoutException(string message, Exception innerException) :
protected SubscriptionTimeoutException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
}
///
diff --git a/src/core/Akka.Streams/OverflowStrategy.cs b/src/core/Akka.Streams/OverflowStrategy.cs
index 5c0994dd28b..123eb357d0a 100644
--- a/src/core/Akka.Streams/OverflowStrategy.cs
+++ b/src/core/Akka.Streams/OverflowStrategy.cs
@@ -110,7 +110,6 @@ public BufferOverflowException(string message, Exception innerException) : base(
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -119,6 +118,5 @@ public BufferOverflowException(string message, Exception innerException) : base(
protected BufferOverflowException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
}
}
diff --git a/src/core/Akka.Streams/Shape.cs b/src/core/Akka.Streams/Shape.cs
index 1d099693ed8..ec32234adb3 100644
--- a/src/core/Akka.Streams/Shape.cs
+++ b/src/core/Akka.Streams/Shape.cs
@@ -173,10 +173,7 @@ public Outlet(string name) : base(name) { }
/// matters from the outside are the connections that can be made with it,
/// otherwise it is just a black box.
///
- public abstract class Shape
-#if CLONEABLE
- : ICloneable
-#endif
+ public abstract class Shape : ICloneable
{
///
/// Gets list of all input ports.
diff --git a/src/core/Akka.Streams/Stage/GraphStage.cs b/src/core/Akka.Streams/Stage/GraphStage.cs
index 8534bc09da0..bb33ad80c6e 100644
--- a/src/core/Akka.Streams/Stage/GraphStage.cs
+++ b/src/core/Akka.Streams/Stage/GraphStage.cs
@@ -2191,14 +2191,12 @@ public class StageActorRefNotInitializedException : Exception
public static readonly StageActorRefNotInitializedException Instance = new StageActorRefNotInitializedException();
private StageActorRefNotInitializedException() : base("You must first call GetStageActorRef(StageActorRef.Receive), to initialize the actor's behavior") { }
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
/// The that holds the serialized object data about the exception being thrown.
/// The that contains contextual information about the source or destination.
protected StageActorRefNotInitializedException(SerializationInfo info, StreamingContext context) : base(info, context) { }
-#endif
}
///
diff --git a/src/core/Akka.Streams/StageException.cs b/src/core/Akka.Streams/StageException.cs
index 5ecbb6265d3..71abcde20ea 100644
--- a/src/core/Akka.Streams/StageException.cs
+++ b/src/core/Akka.Streams/StageException.cs
@@ -6,6 +6,7 @@
//-----------------------------------------------------------------------
using System;
+using System.Runtime.Serialization;
namespace Akka.Streams
{
@@ -22,5 +23,15 @@ public NoSuchElementException(string message) : base(message)
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected NoSuchElementException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
}
diff --git a/src/core/Akka.Streams/StreamLimitReachedException.cs b/src/core/Akka.Streams/StreamLimitReachedException.cs
index b09cfda233b..3fb95a4667d 100644
--- a/src/core/Akka.Streams/StreamLimitReachedException.cs
+++ b/src/core/Akka.Streams/StreamLimitReachedException.cs
@@ -23,7 +23,6 @@ public StreamLimitReachedException(long max) : base($"Limit of {max} reached")
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -32,6 +31,5 @@ public StreamLimitReachedException(long max) : base($"Limit of {max} reached")
protected StreamLimitReachedException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
}
}
diff --git a/src/core/Akka.Streams/StreamRefs.cs b/src/core/Akka.Streams/StreamRefs.cs
index 8c91644d5eb..2d5247bc38b 100644
--- a/src/core/Akka.Streams/StreamRefs.cs
+++ b/src/core/Akka.Streams/StreamRefs.cs
@@ -6,12 +6,14 @@
//-----------------------------------------------------------------------
using System;
+using System.Runtime.Serialization;
using Akka.Actor;
using Akka.Pattern;
using Akka.Streams.Dsl;
using Akka.Streams.Implementation;
using Akka.Util;
+#pragma warning disable 628
namespace Akka.Streams
{
///
@@ -58,6 +60,16 @@ public TargetRefNotInitializedYetException() : base(
"This should not happen due to proper flow-control, please open a ticket on the issue tracker: https://github.com/akkadotnet/akka.net")
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected TargetRefNotInitializedYetException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
public sealed class StreamRefSubscriptionTimeoutException : IllegalStateException
@@ -65,6 +77,16 @@ public sealed class StreamRefSubscriptionTimeoutException : IllegalStateExceptio
public StreamRefSubscriptionTimeoutException(string message) : base(message)
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected StreamRefSubscriptionTimeoutException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
public sealed class RemoteStreamRefActorTerminatedException : Exception
@@ -75,6 +97,16 @@ public sealed class RemoteStreamRefActorTerminatedException : Exception
public RemoteStreamRefActorTerminatedException(string message) : base(message)
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected RemoteStreamRefActorTerminatedException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
public sealed class InvalidSequenceNumberException : IllegalStateException
@@ -88,6 +120,16 @@ public InvalidSequenceNumberException(long expectedSeqNr, long gotSeqNr, string
ExpectedSeqNr = expectedSeqNr;
GotSeqNr = gotSeqNr;
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected InvalidSequenceNumberException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
///
@@ -112,5 +154,15 @@ public InvalidPartnerActorException(IActorRef expectedRef, IActorRef gotRef, str
"Multi-cast such as broadcast etc can be implemented by sharing multiple new stream references. ")
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected InvalidPartnerActorException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
}
diff --git a/src/core/Akka.Streams/StreamTcpException.cs b/src/core/Akka.Streams/StreamTcpException.cs
index 90abae6b157..9ebe2d02564 100644
--- a/src/core/Akka.Streams/StreamTcpException.cs
+++ b/src/core/Akka.Streams/StreamTcpException.cs
@@ -32,7 +32,6 @@ public StreamTcpException(string message, Exception innerException) : base(messa
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -41,7 +40,22 @@ public StreamTcpException(string message, Exception innerException) : base(messa
protected StreamTcpException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
+ }
+
+ ///
+ /// This exception signals that materialized value is already detached from stream. This usually happens
+ /// when stream is completed and an ActorSystem is shut down while materialized object is still available.
+ ///
+ public class StreamDetachedException : Exception
+ {
+ ///
+ /// Initializes a single instance of the class.
+ ///
+ public static readonly StreamDetachedException Instance = new StreamDetachedException();
+
+ private StreamDetachedException() : base("Stream is terminated. Materialized value is detached.")
+ {
+ }
}
///
@@ -58,7 +72,6 @@ private BindFailedException() : base("bind failed")
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -67,7 +80,6 @@ private BindFailedException() : base("bind failed")
protected BindFailedException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
}
///
@@ -92,7 +104,6 @@ public ConnectionException(string message, Exception innerException) : base(mess
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -101,6 +112,5 @@ public ConnectionException(string message, Exception innerException) : base(mess
protected ConnectionException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
-#endif
}
}
diff --git a/src/core/Akka.Streams/WatchedActorTerminatedException.cs b/src/core/Akka.Streams/WatchedActorTerminatedException.cs
index 1af2a78c1b5..d053febeb72 100644
--- a/src/core/Akka.Streams/WatchedActorTerminatedException.cs
+++ b/src/core/Akka.Streams/WatchedActorTerminatedException.cs
@@ -24,7 +24,6 @@ public WatchedActorTerminatedException(string stageName, IActorRef actorRef)
: base($"Actor watched by [{stageName}] has terminated! Was: {actorRef}")
{ }
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -34,6 +33,5 @@ protected WatchedActorTerminatedException(SerializationInfo info, StreamingConte
: base(info, context)
{
}
-#endif
}
}
diff --git a/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj b/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj
index 3bc6331d473..220b17aef65 100644
--- a/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj
+++ b/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj
@@ -20,12 +20,6 @@
-
- $(DefineConstants);SERIALIZATION
-
-
- $(DefineConstants);CORECLR
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.TestKit.Tests/TestEventListenerTests/ExceptionEventFilterTests.cs b/src/core/Akka.TestKit.Tests/TestEventListenerTests/ExceptionEventFilterTests.cs
index 47a490146de..13544350e5a 100644
--- a/src/core/Akka.TestKit.Tests/TestEventListenerTests/ExceptionEventFilterTests.cs
+++ b/src/core/Akka.TestKit.Tests/TestEventListenerTests/ExceptionEventFilterTests.cs
@@ -6,125 +6,170 @@
//-----------------------------------------------------------------------
using System;
+using Akka.Actor;
using Akka.Event;
using Akka.TestKit;
+using Akka.TestKit.Tests.Xunit2.TestEventListenerTests;
using Xunit;
using Xunit.Sdk;
namespace Akka.Testkit.Tests.TestEventListenerTests
{
- //public class ExceptionEventFilterTests : EventFilterTestBase
- //{
- // public ExceptionEventFilterTests()
- // : base("akka.logLevel=ERROR")
- // {
- // }
- // public class TestFinished : Exception { }
- // public class SomeException : Exception { }
-
- // protected override void SendInitLoggerMessage(InitLoggerMessage message)
- // {
- // throw new NotImplementedException();
- // }
-
- // protected override void AfterTest()
- // {
- // //After every test we make sure no uncatched messages have been logged
- // EnsureNoMoreLoggedMessages();
- // base.AfterTest();
- // }
-
- // private void EnsureNoMoreLoggedMessages()
- // {
- // //We log a TestFinished exception. When it arrives to TestActor we know no other message has been logged7
- // //If we receive something else it means another message was logged, and ExpectMsg will fail
- // Log.Error(new TestFinished(), "Finished");
- // ExpectMsg(err => err.Cause is TestFinished,"cause to be ");
- // }
-
- // [Fact]
- // public void SingleExceptionIsIntercepted()
- // {
- // EventFilter.Exception().Intercept(() => Log.Error(new SomeException(), "whatever"));
- // }
-
- // [Fact]
- // public void CanInterceptMessagesWhenStartIsSpecified()
- // {
- // EventFilter.Exception(start: "what").Intercept(() => Log.Error(new SomeException(), "whatever"));
- // }
-
- // [Fact]
- // public void DoNotInterceptMessagesWhenStartDoesNotMatch()
- // {
- // EventFilter.Exception(start: "this is clearly not in message").Intercept(() => Log.Error(new SomeException(), "whatever"));
- // ExpectMsg(err => (string)err.Message == "whatever");
- // }
-
- // [Fact]
- // public void CanInterceptMessagesWhenMessageIsSpecified()
- // {
- // EventFilter.Exception(message: "whatever").Intercept(() => Log.Error(new SomeException(), "whatever"));
- // }
-
- // [Fact]
- // public void DoNotInterceptMessagesWhenMessageDoesNotMatch()
- // {
- // EventFilter.Exception(message: "this is clearly not the message").Intercept(() => Log.Error(new SomeException(), "whatever"));
- // ExpectMsg(err => (string)err.Message == "whatever");
- // }
-
- // [Fact]
- // public void CanInterceptMessagesWhenContainsIsSpecified()
- // {
- // EventFilter.Exception(contains: "ate").Intercept(() => Log.Error(new SomeException(), "whatever"));
- // }
-
- // [Fact]
- // public void DoNotInterceptMessagesWhenContainsDoesNotMatch()
- // {
- // EventFilter.Exception(contains: "this is clearly not in the message").Intercept(() => Log.Error(new SomeException(), "whatever"));
- // ExpectMsg(err => (string)err.Message == "whatever");
- // }
-
-
- // [Fact]
- // public void CanInterceptMessagesWhenSourceIsSpecified()
- // {
- // EventFilter.Exception(source: GetType().FullName).Intercept(() => Log.Error(new SomeException(), "whatever"));
- // }
-
- // [Fact]
- // public void DoNotInterceptMessagesWhenSourceDoesNotMatch()
- // {
- // EventFilter.Exception(source: "this is clearly not the source").Intercept(() => Log.Error(new SomeException(), "whatever"));
- // ExpectMsg(err => (string)err.Message == "whatever");
- // }
-
-
- // [Fact]
- // public void SpecifiedNumbersOfExceptionsCanBeIntercepted()
- // {
- // EventFilter.Exception(occurrences: 2).Intercept(() =>
- // {
- // Log.Error(new SomeException(), "whatever");
- // Log.Error(new SomeException(), "whatever");
- // });
- // }
-
- // [Fact]
- // public void ShouldFailIfMoreExceptionsThenSpecifiedAreLogged()
- // {
- // var exception = XAssert.Throws(() =>
- // EventFilter.Exception(occurrences: 2).Intercept(() =>
- // {
- // Log.Error(new SomeException(), "whatever");
- // Log.Error(new SomeException(), "whatever");
- // Log.Error(new SomeException(), "whatever");
- // }));
- // Assert.Contains("1 messages too many", exception.Message, StringComparison.OrdinalIgnoreCase);
- // }
-
- //}
+ public class ExceptionEventFilterTests : EventFilterTestBase
+ {
+ public ExceptionEventFilterTests()
+ : base("akka.logLevel=ERROR")
+ {
+ }
+ public class SomeException : Exception { }
+
+ protected override void SendRawLogEventMessage(object message)
+ {
+ Sys.EventStream.Publish(new Error(null, nameof(ExceptionEventFilterTests), GetType(), message));
+ }
+
+ [Fact]
+ public void SingleExceptionIsIntercepted()
+ {
+ EventFilter.Exception()
+ .ExpectOne(() => Log.Error(new SomeException(), "whatever"));
+ ExpectNoMsg(TimeSpan.FromMilliseconds(100));
+ }
+
+ [Fact]
+ public void CanInterceptMessagesWhenStartIsSpecified()
+ {
+ EventFilter.Exception(start: "what")
+ .ExpectOne(() => Log.Error(new SomeException(), "whatever"));
+ ExpectNoMsg(TimeSpan.FromMilliseconds(100));
+ }
+
+ [Fact]
+ public void DoNotInterceptMessagesWhenStartDoesNotMatch()
+ {
+ EventFilter.Exception(start: "this is clearly not in message");
+ Log.Error(new SomeException(), "whatever");
+ ExpectMsg(err => (string)err.Message == "whatever");
+ }
+
+ [Fact]
+ public void CanInterceptMessagesWhenMessageIsSpecified()
+ {
+ EventFilter.Exception(message: "whatever")
+ .ExpectOne(() => Log.Error(new SomeException(), "whatever"));
+ ExpectNoMsg(TimeSpan.FromMilliseconds(100));
+ }
+
+ [Fact]
+ public void DoNotInterceptMessagesWhenMessageDoesNotMatch()
+ {
+ EventFilter.Exception(message: "this is clearly not the message");
+ Log.Error(new SomeException(), "whatever");
+ ExpectMsg(err => (string)err.Message == "whatever");
+ }
+
+ [Fact]
+ public void CanInterceptMessagesWhenContainsIsSpecified()
+ {
+ EventFilter.Exception(contains: "ate")
+ .ExpectOne(() => Log.Error(new SomeException(), "whatever"));
+ ExpectNoMsg(TimeSpan.FromMilliseconds(100));
+ }
+
+ [Fact]
+ public void DoNotInterceptMessagesWhenContainsDoesNotMatch()
+ {
+ EventFilter.Exception(contains: "this is clearly not in the message");
+ Log.Error(new SomeException(), "whatever");
+ ExpectMsg(err => (string)err.Message == "whatever");
+ }
+
+
+ [Fact]
+ public void CanInterceptMessagesWhenSourceIsSpecified()
+ {
+ EventFilter.Exception(source: LogSource.Create(this, Sys).Source)
+ .ExpectOne(() =>
+ {
+ Log.Error(new SomeException(), "whatever");
+ });
+ ExpectNoMsg(TimeSpan.FromMilliseconds(100));
+ }
+
+ [Fact]
+ public void DoNotInterceptMessagesWhenSourceDoesNotMatch()
+ {
+ EventFilter.Exception(source: "this is clearly not the source");
+ Log.Error(new SomeException(), "whatever");
+ ExpectMsg(err => (string)err.Message == "whatever");
+ }
+
+
+ [Fact]
+ public void SpecifiedNumbersOfExceptionsCanBeIntercepted()
+ {
+ EventFilter.Exception()
+ .Expect(2, () =>
+ {
+ Log.Error(new SomeException(), "whatever");
+ Log.Error(new SomeException(), "whatever");
+ });
+ ExpectNoMsg(TimeSpan.FromMilliseconds(100));
+ }
+
+ [Fact]
+ public void ShouldFailIfMoreExceptionsThenSpecifiedAreLogged()
+ {
+ var exception = XAssert.Throws(() =>
+ EventFilter.Exception().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);
+ }
+
+ [Fact]
+ public void ShouldReportCorrectMessageCount()
+ {
+ var toSend = "Eric Cartman";
+ var actor = ActorOf( ExceptionTestActor.Props() );
+
+ EventFilter
+ .Exception(source: actor.Path.ToString())
+ // expecting 2 because the same exception is logged in PostRestart
+ .Expect(2, () => actor.Tell( toSend ));
+ }
+
+ internal sealed class ExceptionTestActor : UntypedActor
+ {
+ private ILoggingAdapter Log { get; } = Context.GetLogger();
+
+ protected override void PostRestart(Exception reason)
+ {
+ Log.Error(reason, "[PostRestart]");
+ base.PostRestart(reason);
+ }
+
+ protected override void OnReceive( object message )
+ {
+ switch (message)
+ {
+ case string msg:
+ throw new InvalidOperationException( "I'm sailing away. Set an open course" );
+
+ default:
+ Unhandled( message );
+ break;
+ }
+ }
+
+ public static Props Props()
+ {
+ return Actor.Props.Create( () => new ExceptionTestActor() );
+ }
+ }
+ }
}
diff --git a/src/core/Akka.TestKit/Akka.TestKit.csproj b/src/core/Akka.TestKit/Akka.TestKit.csproj
index ff46c35b560..4c97416d237 100644
--- a/src/core/Akka.TestKit/Akka.TestKit.csproj
+++ b/src/core/Akka.TestKit/Akka.TestKit.csproj
@@ -26,10 +26,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.TestKit/Internal/InternalTestActor.cs b/src/core/Akka.TestKit/Internal/InternalTestActor.cs
index bc7c6c6b94b..04cdd27af90 100644
--- a/src/core/Akka.TestKit/Internal/InternalTestActor.cs
+++ b/src/core/Akka.TestKit/Internal/InternalTestActor.cs
@@ -5,6 +5,7 @@
//
//-----------------------------------------------------------------------
+using System;
using System.Collections.Concurrent;
using Akka.Actor;
using Akka.Event;
@@ -38,7 +39,19 @@ public InternalTestActor(ITestActorQueue queue)
/// TBD
protected override bool Receive(object message)
{
- global::System.Diagnostics.Debug.WriteLine("TestActor received " + message);
+ try
+ {
+ global::System.Diagnostics.Debug.WriteLine("TestActor received " + message);
+ }
+ catch (FormatException)
+ {
+ if (message is LogEvent evt && evt.Message is LogMessage msg)
+ global::System.Diagnostics.Debug.WriteLine(
+ $"TestActor received a malformed formatted message. Template:[{msg.Format}], args:[{string.Join(",", msg.Args)}]");
+ else
+ throw;
+ }
+
var setIgnore = message as TestKit.TestActor.SetIgnore;
if(setIgnore != null)
{
diff --git a/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj b/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj
index 465234b72e3..60651228b04 100644
--- a/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj
+++ b/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj
@@ -17,10 +17,6 @@
-
- $(DefineConstants);CORECLR
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka.Tests.Shared.Internals/AkkaSpec.cs b/src/core/Akka.Tests.Shared.Internals/AkkaSpec.cs
index 078daeaef9a..9b6a2c94e7f 100644
--- a/src/core/Akka.Tests.Shared.Internals/AkkaSpec.cs
+++ b/src/core/Akka.Tests.Shared.Internals/AkkaSpec.cs
@@ -100,10 +100,6 @@ protected virtual void AfterTermination() { }
private static string GetCallerName()
{
-#if CORECLR
- // TODO: CORECLR FIX IT
- var name = "AkkaSpec";
-#else
var systemNumber = Interlocked.Increment(ref _systemNumber);
var stackTrace = new StackTrace(0);
var name = stackTrace.GetFrames().
@@ -112,7 +108,7 @@ private static string GetCallerName()
SkipWhile(m => m.DeclaringType.Name == "AkkaSpec").
Select(m => _nameReplaceRegex.Replace(m.DeclaringType.Name + "-" + systemNumber, "-")).
FirstOrDefault() ?? "test";
-#endif
+
return name;
}
diff --git a/src/core/Akka.Tests/Actor/Dispatch/Bug2640Spec.cs b/src/core/Akka.Tests/Actor/Dispatch/Bug2640Spec.cs
index 2b2b5806483..73a4980df0d 100644
--- a/src/core/Akka.Tests/Actor/Dispatch/Bug2640Spec.cs
+++ b/src/core/Akka.Tests/Actor/Dispatch/Bug2640Spec.cs
@@ -46,6 +46,12 @@ public class ThreadReporterActor : ReceiveActor
{
public ThreadReporterActor()
{
+ // Improve reliability of ForkJoinExecutorShouldShutdownUponAllActorsTerminating
+ // test which intermittently can fail because all messages are actually serviced
+ // by a single thread from the pool. Happens under load, presumably when the processor
+ // finds it more efficient to keep thread locality of the execution.
+ Thread.Sleep(1);
+
Receive(_ => Sender.Tell(Thread.CurrentThread));
}
}
@@ -90,11 +96,10 @@ public void ForkJoinExecutorShouldShutdownUponAllActorsTerminating()
Dictionary threads = null;
Watch(actor);
- var msgCount = 100;
- for (var i = 0; i < msgCount; i++)
+ for (var i = 0; i < 100; i++)
actor.Tell(GetThread.Instance);
- threads = ReceiveN(msgCount).Cast().GroupBy(x => x.ManagedThreadId)
+ threads = ReceiveN(100).Cast().GroupBy(x => x.ManagedThreadId)
.ToDictionary(x => x.Key, grouping => grouping.First());
Sys.Stop(actor);
diff --git a/src/core/Akka.Tests/Akka.Tests.csproj b/src/core/Akka.Tests/Akka.Tests.csproj
index 279e581df92..1c9d08c164f 100644
--- a/src/core/Akka.Tests/Akka.Tests.csproj
+++ b/src/core/Akka.Tests/Akka.Tests.csproj
@@ -21,21 +21,11 @@
-
-
-
-
-
-
-
+
-
- $(DefineConstants);SERIALIZATION;CONFIGURATION
-
-
$(DefineConstants);CORECLR
diff --git a/src/core/Akka.Tests/IO/TcpIntegrationSpec.cs b/src/core/Akka.Tests/IO/TcpIntegrationSpec.cs
index cb8abc1c4d3..0b56cb5c43a 100644
--- a/src/core/Akka.Tests/IO/TcpIntegrationSpec.cs
+++ b/src/core/Akka.Tests/IO/TcpIntegrationSpec.cs
@@ -21,9 +21,7 @@
using Xunit;
using Xunit.Abstractions;
using FluentAssertions;
-#if CORECLR
using System.Runtime.InteropServices;
-#endif
namespace Akka.Tests.IO
{
@@ -174,14 +172,10 @@ public void The_TCP_transport_implementation_should_properly_handle_connection_a
public void The_TCP_transport_implementation_should_properly_support_connecting_to_DNS_endpoints(AddressFamily family)
{
// Aaronontheweb, 9/2/2017 - POSIX-based OSES are still having trouble with IPV6 DNS resolution
-#if CORECLR
- if(!System.Runtime.InteropServices.RuntimeInformation
+ if(!RuntimeInformation
.IsOSPlatform(OSPlatform.Windows) && family == AddressFamily.InterNetworkV6)
- return;
-#else
- if (RuntimeDetector.IsMono && family == AddressFamily.InterNetworkV6) // same as above
return;
-#endif
+
var serverHandler = CreateTestProbe();
var bindCommander = CreateTestProbe();
bindCommander.Send(Sys.Tcp(), new Tcp.Bind(serverHandler.Ref, new IPEndPoint(family == AddressFamily.InterNetwork ? IPAddress.Loopback
diff --git a/src/core/Akka.Tests/Loggers/LoggerSpec.cs b/src/core/Akka.Tests/Loggers/LoggerSpec.cs
new file mode 100644
index 00000000000..17ba5c31a1b
--- /dev/null
+++ b/src/core/Akka.Tests/Loggers/LoggerSpec.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Akka.Actor;
+using Akka.Configuration;
+using Akka.Event;
+using Akka.TestKit;
+using Xunit;
+using Xunit.Abstractions;
+using FluentAssertions;
+
+namespace Akka.Tests.Loggers
+{
+ public class LoggerSpec : AkkaSpec
+ {
+ private static readonly Config Config = ConfigurationFactory.ParseString(@"
+akka.loglevel = DEBUG
+akka.stdout-loglevel = DEBUG");
+
+ public static readonly (string t, string[] p) Case =
+ ("This is {0} a {1} janky formatting. {4}", new []{"also", "very", "not cool"});
+
+ public LoggerSpec(ITestOutputHelper output) : base(Config, output)
+ { }
+
+ [Fact]
+ public void TestOutputLogger_WithBadFormattingMustNotThrow()
+ {
+ // Need to wait until TestOutputLogger initializes
+ Thread.Sleep(200);
+ Sys.EventStream.Subscribe(TestActor, typeof(LogEvent));
+
+ Sys.Log.Error(new FakeException("BOOM"), Case.t, Case.p);
+ ExpectMsg().Cause.Should().BeOfType();
+ ExpectMsg().Cause.Should().BeOfType();
+
+ Sys.Log.Warning(Case.t, Case.p);
+ ExpectMsg();
+ ExpectMsg().Cause.Should().BeOfType();
+
+ Sys.Log.Info(Case.t, Case.p);
+ ExpectMsg();
+ ExpectMsg().Cause.Should().BeOfType();
+
+ Sys.Log.Debug(Case.t, Case.p);
+ ExpectMsg();
+ ExpectMsg().Cause.Should().BeOfType();
+ }
+
+ [Fact]
+ public void DefaultLogger_WithBadFormattingMustNotThrow()
+ {
+ var config = ConfigurationFactory.ParseString("akka.loggers = [\"Akka.Event.DefaultLogger\"]");
+ var sys2 = ActorSystem.Create("DefaultLoggerTest", config.WithFallback(Sys.Settings.Config));
+ var probe = CreateTestProbe(sys2);
+
+ sys2.EventStream.Subscribe(probe, typeof(LogEvent));
+
+ sys2.Log.Error(new FakeException("BOOM"), Case.t, Case.p);
+ probe.ExpectMsg().Cause.Should().BeOfType();
+
+ sys2.Log.Warning(Case.t, Case.p);
+ probe.ExpectMsg();
+
+ sys2.Log.Info(Case.t, Case.p);
+ probe.ExpectMsg();
+
+ sys2.Log.Debug(Case.t, Case.p);
+ probe.ExpectMsg();
+
+ sys2.Terminate().Wait();
+ }
+
+ [Fact]
+ public void StandardOutLogger_WithBadFormattingMustNotThrow()
+ {
+ var config = ConfigurationFactory.ParseString("akka.loggers = [\"Akka.Event.StandardOutLogger\"]");
+ var sys2 = ActorSystem.Create("StandardOutLoggerTest", config.WithFallback(Sys.Settings.Config));
+ var probe = CreateTestProbe(sys2);
+
+ sys2.EventStream.Subscribe(probe, typeof(LogEvent));
+
+ sys2.Log.Error(new FakeException("BOOM"), Case.t, Case.p);
+ probe.ExpectMsg().Cause.Should().BeOfType();
+
+ sys2.Log.Warning(Case.t, Case.p);
+ probe.ExpectMsg();
+
+ sys2.Log.Info(Case.t, Case.p);
+ probe.ExpectMsg();
+
+ sys2.Log.Debug(Case.t, Case.p);
+ probe.ExpectMsg();
+
+ sys2.Terminate().Wait();
+ }
+
+ [Theory]
+ [MemberData(nameof(LogEventFactory))]
+ public void StandardOutLogger_PrintLogEvent_WithBadLogFormattingMustNotThrow(LogEvent @event)
+ {
+ var obj = new object();
+ obj.Invoking(o => StandardOutLogger.PrintLogEvent(@event)).Should().NotThrow();
+ }
+
+ public static IEnumerable
- public sealed class Address : IEquatable, IComparable, IComparable, ISurrogated
-#if CLONEABLE
- , ICloneable
-#endif
+ public sealed class Address : IEquatable, IComparable, IComparable, ISurrogated, ICloneable
{
#region comparer
diff --git a/src/core/Akka/Actor/Exceptions.cs b/src/core/Akka/Actor/Exceptions.cs
index 9a104e247d1..be2080319f1 100644
--- a/src/core/Akka/Actor/Exceptions.cs
+++ b/src/core/Akka/Actor/Exceptions.cs
@@ -32,7 +32,6 @@ protected AkkaException(string message, Exception cause = null)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -42,7 +41,6 @@ protected AkkaException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
-#endif
///
/// The exception that is the cause of the current exception.
@@ -74,7 +72,6 @@ public InvalidActorNameException(string message, Exception innerException)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -84,7 +81,6 @@ protected InvalidActorNameException(SerializationInfo info, StreamingContext con
: base(info, context)
{
}
-#endif
}
///
@@ -101,7 +97,6 @@ public AskTimeoutException(string message)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -111,7 +106,6 @@ protected AskTimeoutException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
-#endif
}
///
@@ -127,6 +121,16 @@ public class ActorInterruptedException : AkkaException
/// TBD
/// TBD
public ActorInterruptedException(string message = null, Exception cause = null) : base(message, cause) { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected ActorInterruptedException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
///
@@ -173,7 +177,6 @@ public ActorInitializationException(IActorRef actor, string message, Exception c
Actor = actor;
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -191,7 +194,6 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont
info.AddValue("Actor", Actor);
base.GetObjectData(info, context);
}
-#endif
///
/// Retrieves the actor whose initialization logic failed.
@@ -243,7 +245,6 @@ public LoggerInitializationException(string message, Exception cause = null)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -253,7 +254,6 @@ protected LoggerInitializationException(SerializationInfo info, StreamingContext
: base(info, context)
{
}
-#endif
}
///
@@ -275,7 +275,6 @@ public ActorKilledException(string message)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -285,7 +284,6 @@ protected ActorKilledException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
-#endif
}
///
@@ -303,7 +301,6 @@ public IllegalActorStateException(string message)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -313,7 +310,6 @@ protected IllegalActorStateException(SerializationInfo info, StreamingContext co
: base(info, context)
{
}
-#endif
}
///
@@ -330,7 +326,6 @@ public IllegalActorNameException(string message)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -340,7 +335,6 @@ protected IllegalActorNameException(SerializationInfo info, StreamingContext con
: base(info, context)
{
}
-#endif
}
///
@@ -349,8 +343,6 @@ protected IllegalActorNameException(SerializationInfo info, StreamingContext con
///
public class DeathPactException : AkkaException
{
- private readonly IActorRef _deadActor;
-
///
/// Initializes a new instance of the class.
///
@@ -358,10 +350,9 @@ public class DeathPactException : AkkaException
public DeathPactException(IActorRef deadActor)
: base("Monitored actor [" + deadActor + "] terminated")
{
- _deadActor = deadActor;
+ DeadActor = deadActor;
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -370,16 +361,20 @@ public DeathPactException(IActorRef deadActor)
protected DeathPactException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
+ DeadActor = (IActorRef)info.GetValue("DeadActor", typeof(IActorRef));
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null) throw new ArgumentNullException(nameof(info));
+ info.AddValue("DeadActor", DeadActor);
+ base.GetObjectData(info, context);
}
-#endif
///
/// Retrieves the actor that has been terminated.
///
- public IActorRef DeadActor
- {
- get { return _deadActor; }
- }
+ public IActorRef DeadActor { get; }
}
///
@@ -390,12 +385,10 @@ public IActorRef DeadActor
/// hence it is only visible as log entry on the event stream.
///
///
- public class PreRestartException : AkkaException
+ public class PreRestartException : ActorInitializationException
{
- private IActorRef Actor;
- private Exception e; //TODO: what is this?
- private Exception exception;
- private object optionalMessage;
+ public Exception RestartException { get; } //TODO: what is this?
+ public object OptionalMessage { get; }
///
/// Initializes a new instance of the class.
@@ -405,14 +398,13 @@ public class PreRestartException : AkkaException
/// The exception which caused the restart in the first place.
/// The message which was optionally passed into .
public PreRestartException(IActorRef actor, Exception restartException, Exception cause, object optionalMessage)
+ :base(actor,"Exception pre restart (" + (restartException == null ?"null" : restartException.GetType().ToString()) + ")", cause)
{
Actor = actor;
- e = restartException;
- exception = cause;
- this.optionalMessage = optionalMessage;
+ RestartException = restartException;
+ OptionalMessage = optionalMessage;
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -421,8 +413,18 @@ public PreRestartException(IActorRef actor, Exception restartException, Exceptio
protected PreRestartException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
+ RestartException = (Exception)info.GetValue("RestartException", typeof(Exception));
+ OptionalMessage = info.GetValue("OptionalMessage", typeof(object));
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null) throw new ArgumentNullException(nameof(info));
+ info.AddValue("RestartException", RestartException);
+ info.AddValue("OptionalMessage", OptionalMessage);
+ base.GetObjectData(info, context);
}
-#endif
+
}
///
@@ -431,8 +433,6 @@ protected PreRestartException(SerializationInfo info, StreamingContext context)
///
public class PostRestartException : ActorInitializationException
{
- private readonly Exception _originalCause;
-
///
/// Initializes a new instance of the class.
///
@@ -442,10 +442,9 @@ public class PostRestartException : ActorInitializationException
public PostRestartException(IActorRef actor, Exception cause, Exception originalCause)
:base(actor,"Exception post restart (" + (originalCause == null ?"null" : originalCause.GetType().ToString()) + ")", cause)
{
- _originalCause = originalCause;
+ OriginalCause = originalCause;
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -454,13 +453,20 @@ public PostRestartException(IActorRef actor, Exception cause, Exception original
protected PostRestartException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
+ OriginalCause = (Exception)info.GetValue("OriginalCause", typeof(Exception));
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null) throw new ArgumentNullException(nameof(info));
+ info.AddValue("OriginalCause", OriginalCause);
+ base.GetObjectData(info, context);
}
-#endif
///
/// Retrieves the exception which caused the restart in the first place.
///
- public Exception OriginalCause { get { return _originalCause; } }
+ public Exception OriginalCause { get; }
}
///
@@ -476,7 +482,6 @@ public ActorNotFoundException()
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -486,7 +491,6 @@ protected ActorNotFoundException(SerializationInfo info, StreamingContext contex
: base(info, context)
{
}
-#endif
///
/// that takes a descriptive and optional .
@@ -522,7 +526,6 @@ public InvalidMessageException(string message)
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -532,7 +535,6 @@ protected InvalidMessageException(SerializationInfo info, StreamingContext conte
: base(info, context)
{
}
-#endif
}
}
diff --git a/src/core/Akka/Actor/Props.cs b/src/core/Akka/Actor/Props.cs
index 61babb75c13..d01ddbe2b07 100644
--- a/src/core/Akka/Actor/Props.cs
+++ b/src/core/Akka/Actor/Props.cs
@@ -768,12 +768,7 @@ private DynamicProps(Props copy, Func invoker)
protected override Props Copy()
{
var initialCopy = base.Copy();
-#if CLONEABLE
var invokerCopy = (Func)invoker.Clone();
-#else
- // TODO: CORECLR FIX IT
- var invokerCopy = invoker;
-#endif
return new DynamicProps(initialCopy, invokerCopy);
}
diff --git a/src/core/Akka/Actor/Scheduler/SchedulerException.cs b/src/core/Akka/Actor/Scheduler/SchedulerException.cs
index 7c110e01b12..a107bc0b936 100644
--- a/src/core/Akka/Actor/Scheduler/SchedulerException.cs
+++ b/src/core/Akka/Actor/Scheduler/SchedulerException.cs
@@ -5,6 +5,8 @@
//
//-----------------------------------------------------------------------
+using System.Runtime.Serialization;
+
namespace Akka.Actor
{
///
@@ -18,6 +20,16 @@ public sealed class SchedulerException : AkkaException
///
/// The message that describes the error.
public SchedulerException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected SchedulerException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
}
diff --git a/src/core/Akka/Actor/Stash/StashOverflowException.cs b/src/core/Akka/Actor/Stash/StashOverflowException.cs
index 87e8f6a4c8a..fbefa038dd1 100644
--- a/src/core/Akka/Actor/Stash/StashOverflowException.cs
+++ b/src/core/Akka/Actor/Stash/StashOverflowException.cs
@@ -22,7 +22,6 @@ public class StashOverflowException : AkkaException
/// The exception that is the cause of the current exception.
public StashOverflowException(string message, Exception cause = null) : base(message, cause) { }
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -32,6 +31,5 @@ protected StashOverflowException(SerializationInfo info, StreamingContext contex
: base(info, context)
{
}
-#endif
}
}
diff --git a/src/core/Akka/Akka.csproj b/src/core/Akka/Akka.csproj
index 28b2abd163d..2f0d47d7804 100644
--- a/src/core/Akka/Akka.csproj
+++ b/src/core/Akka/Akka.csproj
@@ -16,6 +16,8 @@
+
+
@@ -37,10 +39,6 @@
-
- $(DefineConstants);CORECLR;CONFIGURATION;
-
-
$(DefineConstants);RELEASE
diff --git a/src/core/Akka/Configuration/ConfigurationException.cs b/src/core/Akka/Configuration/ConfigurationException.cs
index 2e123d2ab7e..30c20646a5a 100644
--- a/src/core/Akka/Configuration/ConfigurationException.cs
+++ b/src/core/Akka/Configuration/ConfigurationException.cs
@@ -40,7 +40,6 @@ public ConfigurationException(string message, Exception exception): base(message
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -50,7 +49,6 @@ protected ConfigurationException(SerializationInfo info, StreamingContext contex
: base(info, context)
{
}
-#endif
}
}
diff --git a/src/core/Akka/Configuration/ConfigurationFactory.cs b/src/core/Akka/Configuration/ConfigurationFactory.cs
index 220963ec7aa..ac2b9aec733 100644
--- a/src/core/Akka/Configuration/ConfigurationFactory.cs
+++ b/src/core/Akka/Configuration/ConfigurationFactory.cs
@@ -61,12 +61,8 @@ public static Config ParseString(string hocon)
/// The configuration defined in the configuration file.
public static Config Load()
{
-#if CONFIGURATION
var section = (AkkaConfigurationSection)System.Configuration.ConfigurationManager.GetSection("akka") ?? new AkkaConfigurationSection();
return section.AkkaConfig;
-#else
- return ConfigurationFactory.Empty;
-#endif
}
///
diff --git a/src/core/Akka/Configuration/Hocon/AkkaConfigurationSection.cs b/src/core/Akka/Configuration/Hocon/AkkaConfigurationSection.cs
index 687d8bb2b31..2b9f2dba518 100644
--- a/src/core/Akka/Configuration/Hocon/AkkaConfigurationSection.cs
+++ b/src/core/Akka/Configuration/Hocon/AkkaConfigurationSection.cs
@@ -5,7 +5,6 @@
//
//-----------------------------------------------------------------------
-#if CONFIGURATION
using System.Configuration;
namespace Akka.Configuration.Hocon
@@ -67,4 +66,3 @@ public HoconConfigurationElement Hocon
}
}
}
-#endif
diff --git a/src/core/Akka/Configuration/Hocon/CDataConfigurationElement.cs b/src/core/Akka/Configuration/Hocon/CDataConfigurationElement.cs
index deb49e041ef..ea9a839d498 100644
--- a/src/core/Akka/Configuration/Hocon/CDataConfigurationElement.cs
+++ b/src/core/Akka/Configuration/Hocon/CDataConfigurationElement.cs
@@ -5,7 +5,6 @@
//
//-----------------------------------------------------------------------
-#if CONFIGURATION
using System.Configuration;
using System.Xml;
@@ -64,4 +63,3 @@ protected override void DeserializeElement(XmlReader reader, bool serializeColle
}
}
}
-#endif
diff --git a/src/core/Akka/Configuration/Hocon/HoconConfigurationElement.cs b/src/core/Akka/Configuration/Hocon/HoconConfigurationElement.cs
index c8ab219be96..177863060a4 100644
--- a/src/core/Akka/Configuration/Hocon/HoconConfigurationElement.cs
+++ b/src/core/Akka/Configuration/Hocon/HoconConfigurationElement.cs
@@ -5,7 +5,6 @@
//
//-----------------------------------------------------------------------
-#if CONFIGURATION
using System.Configuration;
namespace Akka.Configuration.Hocon
@@ -42,4 +41,3 @@ public string Content
}
}
}
-#endif
diff --git a/src/core/Akka/Dispatch/ExecutorService.cs b/src/core/Akka/Dispatch/ExecutorService.cs
index adc68395b89..6864e970b86 100644
--- a/src/core/Akka/Dispatch/ExecutorService.cs
+++ b/src/core/Akka/Dispatch/ExecutorService.cs
@@ -6,6 +6,7 @@
//-----------------------------------------------------------------------
using System;
+using System.Runtime.Serialization;
using Akka.Actor;
using Akka.Annotations;
@@ -70,6 +71,13 @@ public class RejectedExecutionException : AkkaException
/// TBD
/// TBD
public RejectedExecutionException(string message = null, Exception inner = null) : base(message, inner) { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected RejectedExecutionException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
}
diff --git a/src/core/Akka/Event/EventBusUnsubscriber.cs b/src/core/Akka/Event/EventBusUnsubscriber.cs
index ba332dd9273..3bd9b3fd7e5 100644
--- a/src/core/Akka/Event/EventBusUnsubscriber.cs
+++ b/src/core/Akka/Event/EventBusUnsubscriber.cs
@@ -8,6 +8,7 @@
using Akka.Actor;
using Akka.Actor.Internal;
using Akka.Annotations;
+using Akka.Dispatch;
using Akka.Util.Internal;
namespace Akka.Event
@@ -176,7 +177,7 @@ public static EventStreamUnsubscribersProvider Instance
/// TBD
public void Start(ActorSystemImpl system, EventStream eventStream, bool debug)
{
- system.SystemActorOf(Props.Create(eventStream, system, debug),
+ system.SystemActorOf(Props.Create(eventStream, system, debug).WithDispatcher(Dispatchers.InternalDispatcherId),
string.Format("EventStreamUnsubscriber-{0}", _unsubscribersCounter.IncrementAndGet()));
}
}
diff --git a/src/core/Akka/Event/StandardOutLogger.cs b/src/core/Akka/Event/StandardOutLogger.cs
index e99280d120e..6493c136fc4 100644
--- a/src/core/Akka/Event/StandardOutLogger.cs
+++ b/src/core/Akka/Event/StandardOutLogger.cs
@@ -135,24 +135,26 @@ public static void PrintLogEvent(LogEvent logEvent)
StandardOutWriter.WriteLine(logEvent.ToString(), color);
}
- catch (FormatException)
+ catch (FormatException ex)
{
/*
- * If we've reached this point, the `logEvent` itself is informatted incorrectly.
+ * If we've reached this point, the `logEvent` itself is formatted incorrectly.
* Therefore we have to treat the data inside the `logEvent` as suspicious and avoid throwing
* a second FormatException.
*/
var sb = new StringBuilder();
- sb.AppendFormat("[ERROR][{0}][Thread {1}][StandardOutLogger] ", logEvent.Timestamp, 0);
- sb.AppendFormat("Encoutered System.FormatException while recording log: [" +
- logEvent.LogLevel().PrettyNameFor() + "]")
- .AppendFormat("[" + logEvent.LogSource + "][" + logEvent.Message + "]");
+ sb.AppendFormat("[ERROR][{0}]", logEvent.Timestamp)
+ .AppendFormat("[Thread {0}]", logEvent.Thread.ManagedThreadId.ToString().PadLeft(4, '0'))
+ .AppendFormat("[{0}] ", nameof(StandardOutLogger))
+ .AppendFormat("Encountered System.FormatException while recording log: [{0}]", logEvent.LogLevel().PrettyNameFor())
+ .AppendFormat("[{0}]. ", logEvent.LogSource)
+ .Append(ex.Message);
string msg;
switch (logEvent.Message)
{
case LogMessage formatted: // a parameterized log
- msg = "str=[" + formatted.Format + "],args=["+ string.Join(",", formatted.Args) +"]";
+ msg = " str=[" + formatted.Format + "], args=["+ string.Join(",", formatted.Args) +"]";
break;
case string unformatted: // pre-formatted or non-parameterized log
msg = unformatted;
@@ -163,7 +165,7 @@ public static void PrintLogEvent(LogEvent logEvent)
}
sb.Append(msg)
- .Append("Please take a look at the logging call where this occurred and fix your format string.");
+ .Append(" Please take a look at the logging call where this occurred and fix your format string.");
StandardOutWriter.WriteLine(sb.ToString(), ErrorColor);
}
diff --git a/src/core/Akka/IO/Buffers/DirectBufferPool.cs b/src/core/Akka/IO/Buffers/DirectBufferPool.cs
index 48095da2706..1e5315913bc 100644
--- a/src/core/Akka/IO/Buffers/DirectBufferPool.cs
+++ b/src/core/Akka/IO/Buffers/DirectBufferPool.cs
@@ -21,6 +21,16 @@ public class BufferPoolAllocationException : AkkaException
public BufferPoolAllocationException(string message) : base(message)
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected BufferPoolAllocationException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
}
///
diff --git a/src/core/Akka/Pattern/IllegalStateException.cs b/src/core/Akka/Pattern/IllegalStateException.cs
index 22b337294da..d2a6c19ba94 100644
--- a/src/core/Akka/Pattern/IllegalStateException.cs
+++ b/src/core/Akka/Pattern/IllegalStateException.cs
@@ -33,7 +33,6 @@ public IllegalStateException(string message, Exception innerEx) : base(message,
{
}
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -43,6 +42,5 @@ protected IllegalStateException(SerializationInfo info, StreamingContext context
: base(info, context)
{
}
-#endif
}
}
diff --git a/src/core/Akka/Pattern/OpenCircuitException.cs b/src/core/Akka/Pattern/OpenCircuitException.cs
index 1743595eba1..14ebda07378 100644
--- a/src/core/Akka/Pattern/OpenCircuitException.cs
+++ b/src/core/Akka/Pattern/OpenCircuitException.cs
@@ -82,7 +82,6 @@ public OpenCircuitException(Exception cause, TimeSpan remainingDuration)
: this("Circuit Breaker is open; calls are failing fast", cause, remainingDuration)
{ }
-#if SERIALIZATION
///
/// Initializes a new instance of the class.
///
@@ -91,7 +90,15 @@ public OpenCircuitException(Exception cause, TimeSpan remainingDuration)
protected OpenCircuitException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
+ var duration = (string)info.GetValue("RemainingDuration", typeof(string));
+ RemainingDuration = TimeSpan.Parse(duration);
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null) throw new ArgumentNullException(nameof(info));
+ info.AddValue("RemainingDuration", RemainingDuration);
+ base.GetObjectData(info, context);
}
-#endif
}
}
diff --git a/src/core/Akka/Pattern/UserCalledFailException.cs b/src/core/Akka/Pattern/UserCalledFailException.cs
index b07fa431fa4..86260140a3e 100644
--- a/src/core/Akka/Pattern/UserCalledFailException.cs
+++ b/src/core/Akka/Pattern/UserCalledFailException.cs
@@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
+using System.Runtime.Serialization;
using System.Text;
using Akka.Actor;
@@ -16,5 +17,12 @@ public class UserCalledFailException : AkkaException
{
public UserCalledFailException() : base($"User code caused [{nameof(CircuitBreaker)}] to fail because it calls the [{nameof(CircuitBreaker.Fail)}()] method.")
{ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ protected UserCalledFailException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
}
diff --git a/src/core/Akka/Routing/TailChopping.cs b/src/core/Akka/Routing/TailChopping.cs
index c0704b2f940..a54f59d32cb 100644
--- a/src/core/Akka/Routing/TailChopping.cs
+++ b/src/core/Akka/Routing/TailChopping.cs
@@ -122,7 +122,14 @@ public override void Send(object message, IActorRef sender)
try
{
- completion.TrySetResult(await (_routees[currentIndex].Ask(message, _within)).ConfigureAwait(false));
+ completion.TrySetResult(
+ await (_routees[currentIndex].Ask(message, _within)).ConfigureAwait(false));
+ }
+ catch (AskTimeoutException)
+ {
+ completion.TrySetResult(
+ new Status.Failure(
+ new AskTimeoutException($"Ask timed out on {sender} after {_within}")));
}
catch (TaskCanceledException)
{
diff --git a/src/core/Akka/Util/MatchHandler/CachedMatchCompiler.cs b/src/core/Akka/Util/MatchHandler/CachedMatchCompiler.cs
index 45daa4b7594..48b3e5c72df 100644
--- a/src/core/Akka/Util/MatchHandler/CachedMatchCompiler.cs
+++ b/src/core/Akka/Util/MatchHandler/CachedMatchCompiler.cs
@@ -71,27 +71,6 @@ private Delegate CompileToDelegate(IReadOnlyList handlers, IReadOnl
delegateArguments = result.Arguments;
return compiledLambda;
}
-
-#if !CORECLR
- ///
- /// TBD
- ///
- /// TBD
- /// TBD
- /// TBD
- /// TBD
- /// TBD
- /// TBD
- /// TBD
- public void CompileToMethod(IReadOnlyList handlers, IReadOnlyList capturedArguments, MatchBuilderSignature signature, TypeBuilder typeBuilder, string methodName, MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.Static)
- {
- var result = _expressionBuilder.BuildLambdaExpression(handlers);
- var lambdaExpression = result.LambdaExpression;
- var parameterTypes = lambdaExpression.Parameters.Select(p => p.Type).ToArray();
- var method = typeBuilder.DefineMethod(methodName, methodAttributes, typeof(bool), parameterTypes);
- _expressionCompiler.CompileToMethod(lambdaExpression, method);
- }
-#endif
}
}
diff --git a/src/core/Akka/Util/MatchHandler/ILambdaExpressionCompiler.cs b/src/core/Akka/Util/MatchHandler/ILambdaExpressionCompiler.cs
index 1a874995707..e7ee61bbfc1 100644
--- a/src/core/Akka/Util/MatchHandler/ILambdaExpressionCompiler.cs
+++ b/src/core/Akka/Util/MatchHandler/ILambdaExpressionCompiler.cs
@@ -22,15 +22,6 @@ internal interface ILambdaExpressionCompiler
/// The expression to compile
/// A delegate containing the compiled version of the lambda.
Delegate Compile(LambdaExpression expression);
-
-#if !CORECLR
- ///
- /// Compiles the lambda into a method definition.
- ///
- /// The expression to compile
- /// A which will be used to hold the lambda's IL.
- void CompileToMethod(LambdaExpression expression, MethodBuilder method);
-#endif
}
}
diff --git a/src/core/Akka/Util/MatchHandler/IMatchCompiler.cs b/src/core/Akka/Util/MatchHandler/IMatchCompiler.cs
index 4d597cf4b13..b06e99381f3 100644
--- a/src/core/Akka/Util/MatchHandler/IMatchCompiler.cs
+++ b/src/core/Akka/Util/MatchHandler/IMatchCompiler.cs
@@ -25,20 +25,6 @@ internal interface IMatchCompiler
/// TBD
/// TBD
PartialAction Compile(IReadOnlyList handlers, IReadOnlyList capturedArguments, MatchBuilderSignature signature);
-
-#if !CORECLR
- ///
- /// TBD
- ///
- /// TBD
- /// TBD
- /// TBD
- /// TBD
- /// TBD
- /// TBD
- /// TBD
- void CompileToMethod(IReadOnlyList handlers, IReadOnlyList capturedArguments, MatchBuilderSignature signature, TypeBuilder typeBuilder, string methodName, MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.Static);
-#endif
}
}
diff --git a/src/core/Akka/Util/MatchHandler/LambdaExpressionCompiler.cs b/src/core/Akka/Util/MatchHandler/LambdaExpressionCompiler.cs
index 205bb2a8f92..c1357d07a8f 100644
--- a/src/core/Akka/Util/MatchHandler/LambdaExpressionCompiler.cs
+++ b/src/core/Akka/Util/MatchHandler/LambdaExpressionCompiler.cs
@@ -25,19 +25,6 @@ public Delegate Compile(LambdaExpression expression)
{
return expression.Compile();
}
-
-#if !CORECLR
- ///
- /// TBD
- ///
- /// TBD
- ///
- /// TBD
- public void CompileToMethod(LambdaExpression expression, MethodBuilder method)
- {
- expression.CompileToMethod(method);
- }
-#endif
}
}
diff --git a/src/core/Akka/Util/MatchHandler/MatchBuilder.cs b/src/core/Akka/Util/MatchHandler/MatchBuilder.cs
index 40ed83b6a2d..62b415b79ec 100644
--- a/src/core/Akka/Util/MatchHandler/MatchBuilder.cs
+++ b/src/core/Akka/Util/MatchHandler/MatchBuilder.cs
@@ -171,21 +171,6 @@ public PartialAction Build()
return partialAction;
}
-#if !CORECLR
- ///
- /// TBD
- ///
- /// TBD
- /// TBD
- /// TBD
- /// TBD
- public void BuildToMethod(TypeBuilder typeBuilder, string methodName, MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.Static)
- {
- _compiler.CompileToMethod(_typeHandlers, _arguments, new MatchBuilderSignature(_signature), typeBuilder, methodName, methodAttributes: attributes);
- _state = State.Built;
- }
-#endif
-
private static void EnsureCanHandleType(Type handlesType)
{
if(!_itemType.IsAssignableFrom(handlesType))
diff --git a/src/core/Akka/Util/RuntimeDetector.cs b/src/core/Akka/Util/RuntimeDetector.cs
index 7953d416f70..11190800623 100644
--- a/src/core/Akka/Util/RuntimeDetector.cs
+++ b/src/core/Akka/Util/RuntimeDetector.cs
@@ -37,12 +37,7 @@ public static class RuntimeDetector
/// true if the current runtime is Windows
private static bool _IsWindows()
{
-#if CORECLR
- return System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
-#else
- return System.Environment.OSVersion.Platform != PlatformID.MacOSX &&
- System.Environment.OSVersion.Platform != PlatformID.Unix;
-#endif
+ return RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
}
}
}