public async Task CreateTaskOrchestration(TaskMessage creationMessage, OrchestrationStatus[] dedupeStatuses) { if (!(creationMessage.Event is ExecutionStartedEvent executionStartEvent)) { throw new InvalidOperationException("Invalid creation task message"); } string orchestrationId = creationMessage.OrchestrationInstance.InstanceId; // Lock so that two clients can't create the same orchestrationId at the same time. await this.orchestrationCurrentStateLock.WaitAsync(); IDatabase redisDB = this.redisConnection.GetDatabase(); string orchestrationHistoryKey = RedisKeyNameResolver.GetOrchestrationStateKey(this.taskHub, this.partition, orchestrationId); string currentStateJson = await redisDB.StringGetAsync(orchestrationHistoryKey); if (currentStateJson != null) { OrchestrationState currentState = RedisSerializer.DeserializeObject <OrchestrationState>(currentStateJson); if (dedupeStatuses == null || dedupeStatuses.Contains(currentState.OrchestrationStatus)) { // An orchestration with same instance id is already running throw new OrchestrationAlreadyExistsException($"An orchestration with id '{creationMessage.OrchestrationInstance.InstanceId}' already exists. It is in state {currentState.OrchestrationStatus}"); } } RedisTransactionBuilder transactionBuilder = this.CreateNonExistingOrchestrationTransaction(orchestrationId); var state = new OrchestrationState { OrchestrationInstance = new OrchestrationInstance { InstanceId = creationMessage.OrchestrationInstance.InstanceId, ExecutionId = creationMessage.OrchestrationInstance.ExecutionId, }, CreatedTime = DateTime.UtcNow, OrchestrationStatus = OrchestrationStatus.Pending, Version = executionStartEvent.Version, Name = executionStartEvent.Name, Input = executionStartEvent.Input, }; transactionBuilder.AddOrchestrationToSet(orchestrationId); transactionBuilder.AddOrchestrationStateToHistory(orchestrationId, state); transactionBuilder.SendControlQueueMessage(creationMessage); bool transactionSucceeded = await transactionBuilder.CommitTransactionAsync(); string logMessage; if (transactionSucceeded) { logMessage = "Succeeded in transaction of creating task orchestration"; } else { logMessage = "Failed in transaction of creating task orchestration"; } await this.logger.LogAsync(logMessage); this.orchestrationCurrentStateLock.Release(); }
public async Task <OrchestrationState> GetOrchestrationState(string orchestrationId) { IDatabase redisDatabase = this.redisConnection.GetDatabase(); string orchestrationStateKey = RedisKeyNameResolver.GetOrchestrationStateKey(this.taskHub, this.partition, orchestrationId); string orchestrationStateJson = await redisDatabase.StringGetAsync(orchestrationStateKey); if (orchestrationStateJson == null) { return(null); } return(RedisSerializer.DeserializeObject <OrchestrationState>(orchestrationStateJson)); }
public RedisTransactionBuilder AddOrchestrationStateToHistory(string orchestrationId, OrchestrationState state) { if (this.partition == null) { throw new ArgumentNullException($"Cannot call {nameof(AddOrchestrationStateToHistory)} without a partition set."); } string orchestrationStateKey = RedisKeyNameResolver.GetOrchestrationStateKey(this.taskHub, this.partition, orchestrationId); string stateJson = RedisSerializer.SerializeObject(state); // Add to front of list so history in latest to oldest order transaction.StringSetAsync(orchestrationStateKey, stateJson); return(this); }