コード例 #1
0
        public async Task SaveStateAsync(SaveStateIntent intent, CancellationToken ct)
        {
            var serviceId = await GetServiceIdAsync(ct);

            if (intent.ServiceState != null)
            {
#warning Save Service state
                //var serviceStateRecord = GetOrCreateServiceStateRecord(intent.ServiceId);
                //serviceStateRecord.StateJson = _serializer.Serialize(intent.ServiceState);
                throw new NotImplementedException("Service state is not implemented yet due to non-finalized design.");
            }

            if (intent.RoutineState != null || intent.RoutineResult != null)
            {
                var transitionDescriptor = await GetTransitionDescriptorAsync(ct);

                var routineDescriptor = await GetRoutineDescriptorAsync(ct);

                RoutineRecord routineRecord;
                if (transitionDescriptor.Type == TransitionType.InvokeRoutine)
                {
                    routineRecord = new RoutineRecord
                    {
                        PartitionKey = serviceId.ServiceName,
                        RowKey       = routineDescriptor.RoutineId
                    };
                }
                else
                {
                    routineRecord = await TryLoadRoutineRecordAsync(ct);

                    if (routineRecord == null)
                    {
                        throw new InvalidOperationException("missing routine record");
                    }
                }

                if (intent.RoutineResult != null)
                {
                    routineRecord.State        = null;
                    routineRecord.Continuation = null;
                    routineRecord.Result       = _serializer.SerializeToString(intent.RoutineResult);
                    routineRecord.Status       = (int)RoutineStatus.Complete;
                }
                else if (intent.AwaitedRoutine != null)
                {
                    routineRecord.Status        = (int)RoutineStatus.Awaiting;
                    routineRecord.AwaitService  = intent.AwaitedRoutine.ServiceId?.ServiceName;
                    routineRecord.AwaitMethod   = intent.AwaitedRoutine.MethodId?.MethodName;
                    routineRecord.AwaitIntentId = intent.AwaitedRoutine.Id;
                }
                else
                {
                    routineRecord.Status = (int)RoutineStatus.Scheduled;
                }

                if (routineRecord.Status != (int)RoutineStatus.Complete && intent.RoutineState != null)
                {
                    routineRecord.State = _serializer.SerializeToString(intent.RoutineState);
                }

                // Copy over the continuation from the message to the routine record
                //  on first transition, unless routine is already completed.
                if (routineRecord.Status != (int)RoutineStatus.Complete &&
                    string.IsNullOrEmpty(routineRecord.Continuation) && EventData.Continuation != null)
                {
                    routineRecord.Continuation = JsonConvert.SerializeObject(
                        EventData.Continuation, CloudEventsSerialization.JsonSerializerSettings);
                }

                routineRecord.Method = intent.Routine?.MethodId?.MethodName;

                if (EventData.Caller != null)
                {
                    routineRecord.CallerService   = EventData.Caller.ServiceId?.ServiceName;
                    routineRecord.CallerMethod    = EventData.Caller.Routine?.MethodId?.MethodName;
                    routineRecord.CallerRoutineId = EventData.Caller.Routine?.RoutineId;
                }

                while (true)
                {
                    try
                    {
                        if (string.IsNullOrEmpty(routineRecord.ETag))
                        {
                            try
                            {
                                await _routinesTable.InsertAsync(routineRecord, ct);
                            }
                            catch (TableRowAlreadyExistsException)
                            {
                                throw new ConcurrentTransitionException();
                            }
                        }
                        else
                        {
                            try
                            {
                                await _routinesTable.ReplaceAsync(routineRecord, ct);
                            }
                            catch (TableRowETagMismatchException)
                            {
                                throw new ConcurrentTransitionException();
                            }
                        }
                        break;
                    }
                    catch (TableDoesNotExistException)
                    {
                        await _routinesTable.CreateAsync(ct);
                    }
                }
            }
        }