private async Task <RoutineRecord> TryLoadRoutineRecordAsync(CancellationToken ct) { if (_routineRecord == null) { var serviceId = await GetServiceIdAsync(ct); var routineDescriptor = await GetRoutineDescriptorAsync(ct); try { _routineRecord = await _routinesTable.TryRetrieveAsync <RoutineRecord>( serviceId.ServiceName, routineDescriptor.RoutineId, RoutineRecordPropertiesToRequest, ct); } catch (TableDoesNotExistException) { } if (_routineRecord != null) { routineDescriptor.ETag = _routineRecord.ETag; } } return(_routineRecord); }
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); } } } }