public ServiceWorkerActor(IActorRef parent)
 {
     Receive <SetWorkMessage>(message =>
     {
         var senderClosure = Sender;
         var parentClosure = parent;// todo probably dont need to close over parent
         IConcurrentExecutorResponseMessage resultMessage;
         try
         {
             var workFactory = message.WorkFactory;
             if (workFactory.RunAsyncMethod)
             {
                 workFactory.ExecuteAsync(message.Command)
                 .ContinueWith(r =>
                 {
                     if (r.IsFaulted)
                     {
                         resultMessage = new SetWorkErrorMessage("Unable to complete operation", message.Id);
                     }
                     else
                     {
                         var result = r.Result;
                         if (workFactory.IsAFailedResult(result))
                         {
                             resultMessage = new SetWorkErrorMessage("operation completed but client said its was a failed operation", message.Id);
                         }
                         else
                         {
                             resultMessage = new SetWorkSucceededMessage(result, message.Id);
                         }
                     }
                     parentClosure.Tell(resultMessage);    // because  There is no active ActorContext, this is most likely due to use of async operations from within this actor.
                     senderClosure.Tell(resultMessage);
                     return(resultMessage);
                 },
                               TaskContinuationOptions.AttachedToParent & TaskContinuationOptions.ExecuteSynchronously)
                 ;// .PipeTo(senderClosure).PipeTo(parentClosure);
             }
             else
             {
                 workFactory.Execute();
             }
         }
         catch (Exception e)
         {
             resultMessage = new SetWorkErrorMessage(e.Message + " " + e.InnerException?.Message, message.Id);
             senderClosure.Tell(resultMessage);
             Context.Parent.Tell(resultMessage);
         }
     });
 }
Beispiel #2
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <typeparam name="TCommand"></typeparam>
        /// <param name="id"></param>
        /// <param name="operation"></param>
        /// <param name="hasFailed"></param>
        /// <param name="returnExistingResultWhenDuplicateId"></param>
        /// <param name="maxExecutionTimePerAskCall"></param>
        /// <param name="transformResult">Also passed boolean if error contains existing result</param>
        /// <returns></returns>
        private async Task <ExecutionResult <TResult> > Execute <TResult, TCommand>(string id, TCommand command, Func <TCommand, Task <TResult> > operation, Func <TResult, bool> hasFailed = null, bool returnExistingResultWhenDuplicateId = true, TimeSpan?maxExecutionTimePerAskCall = null, Func <ExecutionResult <TResult>, TResult> transformResult = null, bool storeCommands = false) where TResult : class
        {
            if (operation == null)
            {
                throw new ArgumentNullException(nameof(operation));
            }
            if (id == null)
            {
                throw new ArgumentNullException(nameof(id));
            }

            IConcurrentExecutorResponseMessage result;
            var maxExecTime = maxExecutionTimePerAskCall ?? MaxExecutionTimePerAskCall;

            try
            {
                result = await ReceptionActorRef.Ask <IConcurrentExecutorResponseMessage>(new SetWorkMessage(id, command, new WorkFactory(async(o) => await operation((TCommand)o), (r) => hasFailed?.Invoke((TResult)r) ?? false), storeCommands), maxExecTime).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                result = new SetWorkErrorMessage($"Operation execution timed out . execution time exceeded the set max execution time of {maxExecTime.TotalMilliseconds} ms to worker id: {id} ", id);
            }
            var finalResult = new ExecutionResult <TResult>();

            if (result is SetWorkErrorMessage)
            {
                finalResult.Errors.Add((result as SetWorkErrorMessage).Error);
            }
            else if (result is SetCompleteWorkErrorMessage)
            {
                finalResult.Errors.Add((result as SetCompleteWorkErrorMessage).Error);
                if (returnExistingResultWhenDuplicateId)
                {
                    finalResult.Result = (result as SetCompleteWorkErrorMessage)?.LastSuccessfullResult as TResult;
                }
            }
            else
            {
                finalResult.Succeeded = true;
                finalResult.Result    = (result as SetWorkSucceededMessage)?.Result as TResult;
            }
            finalResult.Result = transformResult == null ? finalResult.Result : transformResult(finalResult);
            return(finalResult);
        }