Aaronontheweb on 1.4.14
Aaronontheweb on master
Bump Mongo2Go from 2.2.14 to 2.… Bump MongoDB.Driver from 2.11.4… Bump Microsoft.NET.Test.Sdk fro… and 4 more (compare)
Aaronontheweb on 1.4.14
Aaronontheweb on dev
Added v1.4.14 release notes (#1… (compare)
Aaronontheweb on dev
ensure that all recovered Times… (compare)
Aaronontheweb on 1.4.14
Added v1.4.14 release notes (compare)
Ok got rid of the ask pattern and instead used a message scheduler to time out. here is the new code and config on the sender side:
CODE:
//Attempt to get a list of supervisors from the SupervisorRegistry
SupervisorRegistryGetListRequest request = new SupervisorRegistryGetListRequest(Self);
_SupervisorRegistry.Tell(request);
var timeout = Context.System.Scheduler.ScheduleTellOnceCancelable(1000, Self, new SupervisorRegistryGetListEvent(request, null, false), Self);
Receive<SupervisorRegistryGetListEvent>(e => {
if(e.Success)
{
_logger.Info("{0} Received supervisor list.", Self.Path.ToStringWithAddress());
timeout.Cancel();
// Save the list for internal use
_AreaToSupervisorActor = e.ResponseGetList.SupervisorDictionary;
_logger.Debug("Actor {0} is Initialized, moving to Ready state.", _ActorType);
Become(Ready);
}
else
{
_logger.Warning("{0} Cannot retrieve list of supervisors. Unable to initialize. {1} retries.", Self.Path.ToStringWithAddress(), _FetchSupervisorListReties);
// retry the request and increase the timeout
_FetchSupervisorListReties++;
// Set up the timeout
timeout = Context.System.Scheduler.ScheduleTellOnceCancelable(1000*_FetchSupervisorListReties, Self, new SupervisorRegistryGetListEvent(request, null, false), Self);
// Send the request again
_SupervisorRegistry.Tell(request);
}
and the config on the sender side:
akka {
# here we are configuring log levels
log-config-on-start = off
stdout-loglevel = DEBUG
loglevel = DEBUG
// Define an Nlog logger for the Akka system
loggers = ["Akka.Logger.NLog.NLogLogger, Akka.Logger.NLog"]
actor {
provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
}
remote {
log-remote-lifecycle-events = DEBUG
log-received-messages = on
helios.tcp {
hostname = "127.0.0.1"
port = 8777
}
}
private void HandleGetListRequest(SupervisorRegistryGetListRequest r)
{
ImmutableDictionary<MicroServices.Area,IActorRef> immutableDictOfSupervisorsActors =
_KnownSupervisorsActors.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.SupervisorActorReference);
Sender.Tell(new SupervisorRegistryGetListResponse(r.Requestor,immutableDictOfSupervisorsActors,r));
}
akka {
# here we are configuring log levels
log-config-on-start = off
stdout-loglevel = DEBUG
loglevel = DEBUG
// Define an Nlog logger for the Akka system
loggers = ["Akka.Logger.NLog.NLogLogger, Akka.Logger.NLog"]
// Enables connectivity to the remote ActorSystemBridge
actor {
provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
}
remote {
helios.tcp {
port = 8888
hostname = "127.0.0.1"
}
}
}
@Horusiath I took out the cluster
Ok got rid of the ask pattern and instead used a message scheduler to time out. here is the new code and config on the sender side:
CODE
//Attempt to get a list of supervisors from the SupervisorRegistry
SupervisorRegistryGetListRequest request = new SupervisorRegistryGetListRequest(Self);
_SupervisorRegistry.Tell(request);
var timeout = Context.System.Scheduler.ScheduleTellOnceCancelable(1000, Self, new SupervisorRegistryGetListEvent(request, null, false), Self);
Receive<SupervisorRegistryGetListEvent>(e => {
if(e.Success)
{
_logger.Info("{0} Received supervisor list.", Self.Path.ToStringWithAddress());
timeout.Cancel();
// Save the list for internal use
_AreaToSupervisorActor = e.ResponseGetList.SupervisorDictionary;
_logger.Debug("Actor {0} is Initialized, moving to Ready state.", _ActorType);
Become(Ready);
}
else
{
_logger.Warning("{0} Cannot retrieve list of supervisors. Unable to initialize. {1} retries.", Self.Path.ToStringWithAddress(), _FetchSupervisorListReties);
// retry the request and increase the timeout
_FetchSupervisorListReties++;
// Set up the timeout
timeout = Context.System.Scheduler.ScheduleTellOnceCancelable(1000*_FetchSupervisorListReties, Self, new SupervisorRegistryGetListEvent(request, null, false), Self);
// Send the request again
_SupervisorRegistry.Tell(request);
}
and the config on the sender side:
akka {
# here we are configuring log levels
log-config-on-start = off
stdout-loglevel = DEBUG
loglevel = DEBUG
// Define an Nlog logger for the Akka system
loggers = ["Akka.Logger.NLog.NLogLogger, Akka.Logger.NLog"]
actor {
provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
}
remote {
log-remote-lifecycle-events = DEBUG
log-received-messages = on
helios.tcp {
hostname = "127.0.0.1"
port = 8777
}
}
To handle remote disconnection I did something like this
signalRSelection = Context.ActorSelection("akka.tcp://api@127.0.0.1:4545/user/signalr");
signalRSelection.Tell(message);
So, I am forcing a Context.ActorSelection before tell. I am thinking this should work although there could be performance issue.
However, this doesn't seems to work all the time. (It works the first time the remote disconnected).
Anyway to do this kind of if(disconneted){ connect(); }
?
(I am aware the watch for Terminated method. However, I have trouble finding the right time to ActorSelection again, because the remote could be still not available. )
akka {
persistence {
journal {
sql-server {
class = "Akka.Persistence.SqlServer.Journal.SqlServerJournal, Akka.Persistence.SqlServer"
plugin-dispatcher = "akka.actor.default-dispatcher"
connection-string = "Data Source=(local);Initial Catalog=HelloClusterSharding;Integrated Security=SSPI"
connection-timeout = 30s
schema-name = Sharding
table-name = EventJournal
auto-initialize = on
timestamp-provider = "Akka.Persistence.Sql.Common.Journal.DefaultTimestampProvider, Akka.Persistence.Sql.Common"
metadata-table-name = Metadata
}
}
}
}
this works..
I'm trying to use a different sql server persistence for cluster sharding.
I have my sharding config set up like this:
cluster {
sharding {
least-shard-allocation-strategy.rebalance-threshold = 3
journal-plugin-id = "akka.persistence.journal.sql-server"
snapshot-plugin-id = "akka.persistence.snapshot-store.sql-server"
}
}
but I would like to replace the "sql-server" name with, let's say "sql-server-sharding"
To handle remote disconnection I did something like this
signalRSelection = Context.ActorSelection("akka.tcp://api@127.0.0.1:4545/user/signalr"); signalRSelection.Tell(message);
So, I am forcing a Context.ActorSelection before tell. I am thinking this should work although there could be performance issue.
However, this doesn't seems to work all the time. (It works the first time the remote disconnected).
Anyway to do this kind ofif(disconneted){ connect(); }
?
(I am aware the watch for Terminated method. However, I have trouble finding the right time to ActorSelection again, because the remote could be still not available. )
Association to [akka.tcp://api@127.0.0.1:4545] having UID [221449129] is irrecoverably failed. UID is now quarantined and all messages to this UID will be delivered to dead letters. Remote actorsystem must be restarted to recover from this situation.
It seems that the remote server is quarantined, is there a way to prevent the remote server being quarantined?
Akka.Persistence.SqlServer.Journal.SqlServerJournal, Akka.Persistence.SqlServer
) and replace it's type as a class name for configuration section used by cluster sharding
@morioma i would use the actor selection to get the remote actor ref once on example on Actor.PreStart()
and watch for the termination of the remote actor, when the remote actor dies, you can introduce a behavior like Reconnecting/ Registering and schedule the reconnect within some interval like 5secs on example.
here is some code which comes out of my mind now:
protected override void PreStart()
{
Context.Become(Registering());
Self.Tell(new LookupForServiceProvider());//LookupForService provider is just a simple message to tell yourself to start the actor selection
}
private UntypedReceive Registering()
{
return message =>
{
if (message is RegisteredToServiceProvider)
{
var registered = (RegisteredToServiceProvider) message;
Console.WriteLine("Registered to the service provider, Path: {0}",registered.ServiceProviderRef.Path);
//do some useful things here, mb switch to a different behavior where you can operate normaly
Context.Watch(registered.ServiceProviderRef);
Context.Become(Registered(registered.ServiceProviderRef));
}
else if (message is UnableToRegister)
{
// we are not able to connect now, try reconnect within some time, and also stay into the same behavior.
Context.System.Scheduler.ScheduleTellOnce(_lookupTimeout,Self, new LookupForServiceProvider(), Self);
}
else if (message is LookupForServiceProvider)
{
var self = Context.Self;
try
{
Context.ActorSelection(sericeProviderPath)
.ResolveOne(_lookupTimeout)
.ContinueWith<IServiceLookupResult>(x =>
{
try
{
var serviceProvider = x.Result;
return new RegisteredToServiceProvider(serviceProvider);
}
catch (AggregateException ex)
{
return new UnableToRegister();
}
}).PipeTo(self);
}
catch (Exception)
{
Self.Tell(new UnableToRegister());
}
}
}
}
private UntypedReceive Registered(IActorRef serviceProvider)
{
return message =>
{
if (message is Terminated)
{
var terminated = (Terminated)message;
if (terminated.ActorRef.Equals(serviceProvider))
{
Context.Become(Registering());
Self.Tell(new LookupForServiceProvider());
Console.WriteLine("Message Service provider is down, auto reconnect in {0} secs.", _lookupTimeout.TotalSeconds);
}
}