0

I am trying to achieve cancel tasks feature in service fabric stateful services.

Plan is using cancellation token to propagate notices to linked threads / Tasks.

The problem is, while there are these long running tasks and threads waiting for this signal, I am not sure how I can find the right cancellation tokens based on another Web API calls.

I was thinking of using reliable dictionary, then even before trying it out, I assume this will hit deadend because cancellationToken can't be serialized / deserialized.

Please help me what could be good solution to solve this issue.

Update (I didn't want to create a new thread losing some of important contexts mentioned in this thread so updating in this post.)

Confirmed that below link description does show Reliable service and actor methods can support cancellation token. However typical use case would be receiving cancellation request directly via web API with user triggering such as click refresh, go to another page, etc. In such scenario, the exact same end point needs to receive the request while previous http requst is lingering with some long running task or stuck. That is not the scenario in this thread.

From link: https://blogs.msdn.microsoft.com/azureservicefabric/2016/02/23/service-fabric-sdk-v1-5-175-and-the-adoption-of-virtual-machine-scale-sets/

CancellationToken support for IService/IActor

Reliable Service and Reliable Actor methods now support a cancellation token that can be remoted via ActorProxy and ServiceProxy, allowing you to implement cooperative cancellation. Clients that want to cancel a long running service or actor method can signal the cancellation token and that cancellation intent will be propagated to the actor/service method. That method can then determine when to stop execution by looking at the state of its cancellation token argument.

For example, an actor’s contract that has a possibly long-running method can be modelled as shown below:

        public interface IPrimeNumberActorInterface : IActor
        {

            Task<ulong> FindNextPrimeNumberAsync
                (ulong previous, CancellationToken cancellationToken);

        }

The client code that wishes to cancel the method execution can communicate its intent by canceling the cancellation token.

swcraft
  • 2,014
  • 3
  • 22
  • 43

1 Answers1

3

CancellationToken & CancellationTokenSource are not serializable and doesn't flow across service calls or Data Replication in SF. It can only be used to tell the handler within the same process that an operation has been cancelled and should stop any processing or ignore any continuation in case a response is received.

If you want to be able to start and cancel an operation in another service, you should split the operation in two calls.

  • The first will generate an Operation ID to be returned to the client, and Create a CancellationTokenSource for this operation to generate a CancellationToken to be passed to the Task\Thread running in the background
  • The second will receive and OperationID and identify if a CancellationTokenSource exists and cancel it, so that the token provided to any Task\Thread can stop any processing, if not already completed or cancelled.

You could simply store it as a Dictionary<Guid, CancellationTokenSource> in the process\partition running the task.

In case you are running these tasks in multiple partitions in SF, and is planning to store it in a Reliable Dictionary, it is not a good idea, because as said previously, you can't serialize the cancellation to other partitions.

In this case you can store the OperationID and the PartitionID, so all partitions know where an operation is running, when you receive a call for cancellation on any of the partitions, the service will lookup in this reliable dictionary where the operation is running and forward the cancellation to the right partition.

Diego Mendes
  • 10,631
  • 2
  • 32
  • 36
  • I found an article using ISerializationSurrogate. https://blogs.msdn.microsoft.com/schlepticons/2008/08/24/work-around-your-asp-net-session-serialization-issues/ Not sure yet if this would work and achieve serializing custom-serialized cancellationtoken.. if not then probably what you suggested would be an option.. – swcraft Oct 25 '18 at 23:35
  • It is unfortunate that the deserialized cancellationtoken using above link methodology loses all callback registered, probably it won't even be the same reference as the one passed down to other threads.. worth checking though. – swcraft Oct 26 '18 at 00:49
  • In what you wrote "In this case you can store the OperationID and the PartitionID,", do you mean to the reliable dictionary? In my case, cancellation token is not the one coming down to the in-built provided function such as RunAsync(cancellationtoken) but one I have to create in spawned thread(new cancellationtoken to kill actor / Tasks).. wonder how I can reach these tokens to invoke Cancel(). Also it would be great help if you can explain with little more details what you mean by forwarding the cancellation to right partition.. – swcraft Oct 26 '18 at 04:31
  • 1
    Only the process(service partition) running the operation can cancel it, in this case you will store the dictionary with the cancellation token within the same process. The reliable dictionary with the operationID and PartitionID can be stored anywhere,for example, in the API, because you will have to send the cancellation request to the process(service partition) that is running the operation. The client\caller will send the cancellation command to the API, and the API will find which partition has the process and send a call to the service, the service receive the request cancel the token – Diego Mendes Oct 26 '18 at 08:24
  • I have been searching for information on how to get OperationID / PartitionID, it would be great if you can guide me for such information.. service fabric is especially hard to learn or figure out due to lack of information / good learning material. – swcraft Oct 28 '18 at 22:08
  • 1
    OperationId is not something you find, in the proposed idea above, OperationID is an ID generated by you to identify a running operation, int is not generated by Service Fabric, service fabric is just the orchestrator of your service and it has very little impact on the design mentioned above. Because your original question was asking how to fix a "Solution" instead of "how to solve a problem", is hard to answer with something that is totally different from what you asked. I would recommend you make another question on "How to cancel a remote operation using Service Fabric" – Diego Mendes Oct 29 '18 at 09:56
  • Thanks for keep helping on this thread, probably the last piece of puzzle would be "forward the cancellation to the right partition" in your explanation. How do you forward from API request received to the right partition? I guess once request has been forward from Web API to right partition then it seems all make sense because at that point then you should be simply able to call cancellationtokensource.cancel(). – swcraft Oct 29 '18 at 14:27
  • Can you make this as an extra question, will be easier to answer than put in this box – Diego Mendes Oct 29 '18 at 15:42
  • sure thing, I have created a new thread: https://stackoverflow.com/questions/53050219/forward-the-cancellation-to-the-right-partition – swcraft Oct 29 '18 at 16:49
  • OK, Once I get some spare time I will try to answer with some sample code. I am a bit busy today – Diego Mendes Oct 30 '18 at 12:38