Example #1
0
        internal override void Enter <TKey>(Process process, TKey localkey, Stopwatch stopwatch, out bool isExiting)
        {
            var completed = Execute <TKey>(process, localkey, out var result);

            if (!completed)
            {           // we did not actually execute, but are waiting for initialization ack
                isExiting = false;
                return; // keep lock
            }

            if (MessageType != MessageType.ForkUpdate)
            {
                process.Send(process.GetOrigin(Opid), new RespondToLocal()
                {
                    Opid = Opid, Parent = Parent, Result = result
                });
            }
            else
            {
                process.CheckForUnhandledException(result);
            }

            process.Telemetry?.OnApplicationEvent(
                processId: process.ProcessId,
                id: Opid.ToString(),
                name: LabelForTelemetry,
                parent: Parent.ToString(),
                opSide: OperationSide.Callee,
                opType: OperationType.Local,
                duration: stopwatch.Elapsed.TotalMilliseconds
                );

            isExiting = true;
        }
        public async Task Run()
        {
            Stopwatch messageProcessingTimer = new Stopwatch();

            messageProcessingTimer?.Start();

            if (info.RequiresLocks(Request, out var locks))
            {
                LockSet = locks;
                if (!LockedByCaller)
                {
                    await AcquireLocks();
                }
            }

            object result;

            try
            {
                if (Request is IReadOrchestration <TReturn> ro)
                {
                    result = await ro.Execute(this);
                }
                else
                {
                    result = await((IOrchestration <TReturn>)Request).Execute(this);
                }

                if (Continuations.Count > 0)
                {
                    throw new RuntimeException("Operation completed prematurely. Must await all spawned tasks, or use ForkXXX or ScheduleXXX for detached operations.");
                }
            }
            catch (Exception e)
            {
                result = process.Serializer.SerializeException(e);
            }

            if (LockSet != null && !LockedByCaller)
            {
                ReleaseLocks();
            }

            messageProcessingTimer.Stop();
            var elapsed = messageProcessingTimer.Elapsed.TotalMilliseconds;

            process.Telemetry?.OnApplicationEvent(
                processId: process.ProcessId,
                id: Opid.ToString(),
                name: Request.ToString(),
                parent: Parent.ToString(),
                opSide: OperationSide.Callee,
                opType: OperationType.Orchestration,
                duration: elapsed
                );

            switch (OrchestrationType)
            {
            case OrchestrationType.Perform:
                var response = new RespondToOrchestration()
                {
                    Opid   = Opid,
                    Result = result,
                    Clock  = Clock,
                    Parent = Parent,
                };
                process.Send(process.GetOrigin(Opid), response);
                break;

            case OrchestrationType.Fork:
                process.CheckForUnhandledException(result);
                if (process.FinishStates.TryGetValue(Parent, out var finishState))
                {
                    finishState.RemovePending(Opid);
                }
                break;

            case OrchestrationType.Initialize:
                process.CheckForUnhandledException(result);
                var initializationRequest = (IInitializationRequest)Request;
                initializationRequest.SetStateToFinalResult(process);
                var initresponse = new AckInitialization()
                {
                    OriginalOpid = Parent,
                    PartitionKey = initializationRequest.GetPartitionKey(),
                    Opid         = Opid,
                    Clock        = Clock,
                    Parent       = Parent,
                };
                process.Send(process.GetOrigin(Opid), initresponse);
                break;
            }
        }