How to pass data to `OnActivateAsync()` to initialize my stateful actor? - c#

I am creating a reliable, stateful, service actor.
Question:
Is there a way to pass initialization data during the actor proxy creation (ActorProxy.Create())? Basically an equivalent to a constructor for my actor.
Current thoughts:
I can achieve this by following up the proxy creation call with an actor method call in charge of initializing the state.
E.g.
//Danger, the following calls are not atomic
ITokenManager tokenActor = ActorProxy.Create<IMyActor>(actorId, "AppName");
//Something could happen here and leave my actor in an unknown state
await tokenActor.InitializeAsync(desiredInitialState);
My concern with such approach:
This operation is not atomic. It may leave my actor in an inconsistent state
This initialization method is now available throughout the life of the actor, which is undesired.

A couple thoughts for you here. For one, is the data that you need to do initialization really not available to the actor itself during OnActivateAsync? Normally if I rely on getting some initial data into my actor's state this is how I would do it.
protected override Task OnActivateAsync()
{
if (State == null)
{
var initialState = await externalSource.GetSomeState();
// simplified here but map the values properly onto the actual actor state
this.State = initialState;
return base.OnActivateAsync();
}
}
The other thought is that if you truly can't have the actor retrieve the data during it's own activation it's very easy for you to create a boolean property that is part of the actor state indicating whether or the other activation you're talking about has ever occurred.
public Task InitializeAsync(State someState)
{
if (State.IsActivated)
{
// log out here that someone is attempting to reactivate when they shouldn't
return Task.CompletedTask;
}
State = someState;
State.IsActivated = true;
return Task.CompletedTask;
}
This way while technically the method will be available to be called for the lifetime of the actor, you have a single threaded guarantee that it will only actually do something the very first time it is called.

It seems like the best approach to have an atomic initialization is keep the initialization data in some external store, and during OnActivateAsync() consume this data from that store.

Proxy creation is not equivalent to constructor. In Service Fabric the client is not supposed to know whether the actor has already been created or not, and the lifecycle is managed by the runtime.
So the actor itself should initialize to some default state. It's the job of actor implementation to prevent other calls before initialization calls and prevent multiple initialization if needed. As actors are always single-threaded, it can be easily achieved with something like boolean flags.

Related

How to clean up instances created by SimpleInjector during verification?

As a part of creating my SimpleInjector container, I've followed recommended practices and called container.Verify() to check that my type registrations make sense.
This works well and has caught a number of errors that I've made - but it also creates debris that lingers around afterwards that I'd like to clean up.
One of my classes is a singleton event hub that's used to route messages between other transient components; these other components accept the event hub in their constructor, create a subscription to receive the messages they're interested in receiving, then Dispose() the subscription when they're finished.
The call to container.Verify() creates one of each kind of object, resulting in a number of these otherwise transient instances lingering around because the event hub still knows about their subscriptions.
At the moment I've worked around the problem by manually terminating all subscriptions immediately after the Verify() call, before the application starts up. However, this feels like a problem that must be already solved, though I haven't been able to find an answer in the docs, here on Stack Overflow, or by searching.
Perhaps using a scoped lifestyle is the solution? They didn't seem relevant because I'm building a WPF application, but if I knew the answer I wouldn't be asking here!
Update, 12 Jan - As requested by #steven, here's some code to demonstrate my issue.
I tried (and failed) to demonstrate the issue with something that was both compilable and short enough to share inline; instead I'm showing some code excerpts from the actual project. If you want to see the whole thing, the WordTutor project is on GitHub.
At the core of my application I have a singleton IReduxStore<T> which both encapsulates application state and acts as a kind of event hub. Other classes subscribe to the store in order to be proactively notified when the application state changes.
Here is IReduxStore<T>, pared down to the essentials:
// IReduxStore.cs
public interface IReduxStore<T>
{
T State { get; }
void Dispatch(IReduxMessage message);
IDisposable SubscribeToReference<V>(
Func<T, V?> referenceReader,
Action<V?> whenChanged)
where V : class, IEquatable<V>?;
}
Subscriptions implement IDisposable as a convenient and idiomatic way for deterministic cleanup when the subscription is no longer required.
The store is registered as a singleton, bound to a specific type of state:
// Program.cs
container.RegisterSingleton<
IReduxStore<WordTutorApplication>,
ReduxStore<WordTutorApplication>>();
The implementation of IReduxStore<T> stores all the subscriptions:
private readonly HashSet<ReduxSubscription<T>> _subscriptions
= new HashSet<ReduxSubscription<T>>();
They're removed from the HashSet when disposed.
Many of my ViewModels accept IReduxStore<WordTutorApplication> to their constructors so they can subscribe to updates:
// VocabularyBrowserViewModel.cs
public sealed class VocabularyBrowserViewModel : ViewModelBase
{
private readonly IReduxStore<WordTutorApplication> _store;
private readonly IDisposable _screenSubscription;
private readonly IDisposable _vocabularySubscription;
public VocabularyBrowserViewModel(IReduxStore<WordTutorApplication> store)
{
_store = store ?? throw new ArgumentNullException(nameof(store));
// ... elided ...
_screenSubscription = _store.SubscribeToReference(
app => app.CurrentScreen as VocabularyBrowserScreen,
RefreshFromScreen);
_vocabularySubscription = _store.SubscribeToReference(
app => app.VocabularySet,
RefreshFromVocabularySet);
// ... elided ...
}
// ... elided ...
}
ViewModels are registered as transient because each window needs a unique instance:
// Program.cs
var desktopAssembly = typeof(WordTutorWindow).Assembly;
container.Collection.Register<ViewModelBase>(desktopAssembly);
The ViewModels release their subscriptions proactively when they are no longer needed:
// VocabularyBrowserViewModel.cs
private void RefreshFromScreen(VocabularyBrowserScreen? screen)
{
if (screen == null)
{
_screenSubscription.Dispose();
_vocabularySubscription.Dispose();
return;
}
Selection = screen.Selection;
Modified = screen.Modified;
}
When Verify() is called on the SimpleInjector container, an exemplar of every object is created, including the singleton IReduxStore<T>. The transient viewmodels (such as VocabularyBrowserViewModel shown above) are also created, but those instances remain live because their subscriptions are still held by the store.
I tried implementing IDisposable on the ViewModels, but because their lifestyle is transient, the only effect was to generate an additional warning when Verify() was called.
Update II, 12 Jan:
The workaround I have at the moment is to manually clear all the subscriptions as a part of application startup, after the container has been successfully initialized:
var store = (ReduxStore<WordTutorApplication>)
container.GetInstance<IReduxStore<WordTutorApplication>>();
store.ClearSubscriptions();
This feels like a nasty hack. First it needs to explicitly cast to the implementation type, then it calls a method that otherwise wouldn't need to exist at all.
Try setting EnableAutoVerification to false in Simple Injector 5.0 (https://simpleinjector.org/ReferenceLibrary/html/P_SimpleInjector_ContainerOptions_EnableAutoVerification.htm)

Does WCF Run the session on more than one thread?

I have a wcf service (hosted in IIS) that is setup to use sessions. It seems to work. When Application_PostAcquireRequestState is called I have a session ID.
I end up using it like this (in my Global.asax):
if (Context.Handler is IRequiresSessionState)
{
log4net.ThreadContext.Properties["sessionId"] = Session.SessionID;
}
That seems to work fine. The value is stored off into my log4net property.
But when my service operation begins (my actual WCF service code) the log4net property is null again.
Since the property is stored per thread (ThreadContext), I can only assume that this means that the session is setup on one thread then executed on another thread. Am I right?
Is there anyway to get my log4net property set on the on the correct thread (without having to remember to make the above call at the start of every single service operation)?
Yes, IIS may use multiple thread to service multiple WCF requests. See http://msdn.microsoft.com/en-us/library/cc512374.aspx for more detail.
You might consider using different instances of a logger for each WCF request.
There are multiple scenarios where WCF might change threads on you:
The Global.asx thread is not guaranteed to be used for a service call (in fact its unlikely).
If there are multiple calls during the same session, the thread may also change between calls to the same service instance.
In theory state information like this should be stored in an Operation Context object. However because log4net uses thread local storage it becomes an awkward solution.
Is there anyway to get my log4net property set on the on the correct
thread (without having to remember to make the above call at the start
of every single service operation)?
Yes. Create a custom IOperationInvoker. The best example I know of is Carlos Figueira's blog. If you apply this as a service behavior your log4net property should always be defined for the service code.
One warning: When adding to thread local storage be sure to clean up. That's why log4net.ThreadContext.Stacks[].Push() returns a IDisposable. In other words your Invoke method should look like (incomplete and untested):
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
using (log4net.ThreadContext.Stacks[key].Push(value))
{
return this.originalInvoker.Invoke(instance, inputs, out outputs);
}
}
See Carlos' blog to understand why you are calling the "originalInvoker". Note that if you want to support async operations that you need to implement additional methods.
Custom properties do not need to be strings. So you could store an instance of the following class in the global context:
public class SessionIdProperty
{
public override string ToString()
{
// error handling omitted
return Session.SessionID;
}
}
This way log4net can access the Session object directly when it logs a message. Log4net calls the ToString() method on non-string properties.

How do I spawn child thread processes when using shared entities injected via Unity?

I have an ASP.Net MVC3 solution running a batch import process which fetches data from a web-service. For each row/loop, the process needs to send up to four emails. I'd like to fire these emails off in background threads so that the main thread doesn't have to wait for the emails to be sent. The child email thread needs to update the database audit table on email send completion or failure.
The issue I'm having is that I use Unity to inject the IEmailer class into my main process thread, which also assigns the 'main process thread' datacontext into the emailer class. So I get errors when the datacontext has already been closed when the emailer tries to update the audit table if the main loop has already finished (a plausible scenario).
How do I tell Unity to assign a new datacontext to my new emailer threads, or how do I tell my emailer class to use a different unity container (configured with Transient datacontext, I guess?)?
Here's my stripped down code. (I realise I could just instantiate a 'new MyDataContext()' inside the emailer but there is definitely a better way).
Any help, suggestions, ideas or comments will be greatly appreciated - thank you!
IOC Container
this.unityContainer = new UnityContainer()
.RegisterType<IDataProvider, DataProvider>()
.RegisterType(typeof(IEmailer), typeof(Emailer))
.RegisterType<DbContext, MyDataContext>(new HierarchicalLifetimeManager());
Import class (main thread)
public class DataSyncer : IDataSyncer
{
public DataSyncer(IDataProvider dataProvider, IEmailer emailer) {
this.dataProvider = dataProvider;
this.emailer = emailer;
}
public void Import(Guid key) {
// some import code
emailer.EmailAddress = "someone#somewhere.com";
emailer.Subject = "subject line";
new Thread(emailer.SendMail).Start(); // send email in new thread
}
}
Emailer class (for child threads)
public class Emailer : IEmailer
{
[Dependency]
public IDataProvider DataProvider { get; set; }
// etc
}
DataProvider (contains datacontext via ctor injection)
public DataProvider(MyDataContext context, // etc) { // etc }
I'm trying to rephrase your explanation to see if I got it right.
Your importer runs on the main thread. You fire of emails for every row you import. Your emailer needs to write audit information to the database upon success or failure of the process.
The emailer is injected into your importer and both have a dependency on a class derived from DbContext? Is that the same instance of the DbContext? If so: Why do you share that instance? Isn't each task of sending an email independent from all other tasks? If so, remove the HierarchicalLifetimeManager.
You use property injection for your IDataProvider. I understood that this is a must-have dependency. If that is the case you should use constructor injection like you already do for the other classes. By the way: Don't use the DependencyAttribute. You can also configure property injection using InjectionProperty in your call to RegisterType.
Update
As far as I know Unity never cleans up after itself. Meaning I would not expect it to call Dispose on your DbContext anyway. Do you have a reference where it says that the HierarchicalLifetimeManager disposes objects properly? I would be very interested to read it!
HierarchicalLifetimeManager works the same way as ContainerControlledLifetimeManager as long as you don't deal with child containers. That basically means that you have a single instance of your context across all threads. If you just remove that lifetime manager you would get a new instance whenever one is needed as a dependency. That should solve your problem.
If you need to take care of the disposal of your context instances I would inject a factory for the context instead of an instance. Just declare a ctor parameter of Type Func<MyDataContext> Unity will automatically generate the delegate for you (that feature is called automatic factories btw.). Then you can use using(var ctx = dbContextFactory()) { ... }.

How to separate the layer of the communication and processing?

I created an application that provides several services. Each service provides a specific processing capabilities, except one service (that is the main service) that returns true or false to the clients which request if the specified processing capabilities is available or not.
Now I would modify the application, leaving the main service unchanged and adding the support for the installation of plugin with new processing capabilities: each plugin should add new processing capabilities without the need of implement a new service, but after installing the new plugin, a new service should be avaible. In this way, a plugin should not handle the communication layer. In other words, I would like to separate the layer of the communication and processing, in order to simplify the creation of new plugins.
Is it possible?
I could create two services: the main service and the service for processing.
The first service may be used by clients to know if a certain feature is present on the server (for example, clients may ask the server if it has installed the plugin that provides the functionality for solving differential equations).
The second service could be used to send a generic task and to receive a general result, for example:
Result executeTask(Task task);
where Result and Task are abstract classes...
For example, if I develop a plugin to solve the differential equations, I first create the classes for transferring data:
public class DifferentialEquationTask : Task
// This class contains the data of the differential equation to be solved.
...
public class DifferentialEquationResult : Result
// This class contains the the result.
...
Therefore, the client should instantiate a new object DifferentialEquationTask and pass it to the method of the second service:
DifferentialEquationTask myTask = new DifferentialEquationTask(...);
...
Result result = executeTask(myTask); // called by basic application
// The second service receives myTask as a Task object.
// This Task object also contains the destination plugin, so myTask is send
// to the correct plugin, which converts it to DifferentialEquationTask
...
myResult = result as DifferentialEquationResult;
// received by the client
Moreover, each plugin should have a version for the application server and a version for the client application.
An alternative would be to include the service in the plugin itself: in this way, a new plugin should implement a new functionality and expose it via an additional service.
In summary, I thought the following two alternatives:
a main service to ask the server if it has a plugin or not, and a second service to deliver tasks at the correct plugin;
a main service to ask if the server has a plugin or not, and various additional services (an additional service for each plugin installed).
In order to choose the best approach, I could use the following requirements:
Which of the two alternatives may provide better performance?
What advantages would be obtained using a new service for each plugin than using a single service that delivers tasks at the correct plugin?
Which of the two alternatives simplifies the development of a new plugin?
Being a novice, I was wondering if there was a better approach...
Thanks a lot!
It seems like the main service could maintain a dictionary of plugins, indexed by name. Then for a client to see if the server provides a particular service, all the main service has to do is look up the name in the dictionary. And to process, the service just has to call a method on the object that's in the value portion of the dictionary entry. An example:
You have three abstract classes: Service, ServiceResult, and ServiceTask. The contents of ServiceTask and ServiceResult aren't really important for this discussion. Service must have a parameterless constructor and a method called Process that takes a ServiceTask as its sole parameter. So your differential equation solver would look like:
public class DiffeqSolver : Service
{
public DiffeqSolver()
{
// do any required initialization here
}
public ServiceResult Process(ServiceTask task)
{
DiffeqTask dtask = task as DiffeqTask;
if (dtask == null)
{
// Error. User didn't pass a DiffeqTask.
// Somehow communicate error back to client.
}
// Here, solve the diff eq and return the result.
}
}
The main service is somehow notified of existing plugins. It maintains a dictionary:
Dictionary<string, Service> Services = new Dictionary<string, Service>();
I assume you have some idea how you're going to load the plugins. What you want, in effect, is for the dictionary to contain:
Key = "DiffeqSolver", Value = new DiffeqSolver();
Key = "ServiceType1", Value = new ServiceType1();
etc., etc.
You can then have two methods for the main service: ServiceIsSupported and Process:
bool ServiceIsSupported(string serviceName)
{
return Services.ContainsKey(serviceName);
}
ServiceResult Process(string serviceName, ServiceTask task)
{
Service srv;
if (Services.TryGetValue(serviceName, out srv))
{
return srv.Process(task);
}
else
{
// The service isn't supported.
// Return a failure result
return FailedServiceResult;
}
}
I've simplified that to some extent. In particular, I'm using a Dictionary, which is not thread safe. You'd want to use a ConcurrentDictionary, or use locks to synchronize access to your dictionary.
The more difficult part, I think, will be loading the plugins. But there are many available examples of creating a plugin architecture. I think you can find what you need.

C# Async call garbage collection

I am working on a Silverlight/WCF application and of course have numerous async calls throughout the Silverlight program. I was wondering on how is the best way to handle the creation of the client classes and subscribing. Specifically, if I subscribe to an event in a method, after it returns does it fall out of scope?
internal MyClass
{
public void OnMyButtonClicked()
{
var wcfClient = new WcfClient();
wcfClient.SomeMethodFinished += OnMethodCompleted;
wcfClient.SomeMethodAsync();
}
private void OnMethodCompleted(object sender, EventArgs args)
{
//Do something with the result
//After this method does the subscription to the event
//fall out of scope for garbage collection?
}
}
Will I run into problems if I call the function again and create another subscription?
Thanks in advance to anyone who responds.
You shouldn't let WCF client proxies simply fall out of scope like this. Your code will work but it will also leak resources. WCF clients all implement IDisposable, but this is one case where you can't just use using or Dispose; the Service Proxy Helper can be used for synchronous operations but the cleanup code in there demonstrates how to safely dispose of the client in any context.
When making async operations like this, something needs to be managing the lifetime of that client in a similar fashion. Normally whatever class "owns" the WCF client should implement IDisposable itself, keep a reference to that client in a private field somewhere, and invoke Close/Abort on the client in its disposal method.
Generally, whichever class actually implements the async callback method is going to be the owner, and so that class should be managing the lifetime; therefore, if you really need an "on-demand" client, it may also make sense to perform the cleanup after the callback is finished.
WCF clients are not cheap to create, either, so you should actually try to keep them around as long as possible and not create them ad-hoc like this; think of them as application-wide dependencies.
If you just keep the client instance around, then you don't need to keep subscribing to its events, either; the question effectively goes away.
You won't run into problems. It will generate a new WcfClient instance, and both will call your OnMethodCompleted callback on completion.

Categories

Resources