private async Task ProcessQueueItemsAsync() { await this.controlQueueLock.WaitAsync(); IDatabase database = this.redisConnection.GetDatabase(); RedisValue[] messagesJson = await database.ListRangeAsync(this.partitionControlQueueKey); foreach (string messageJson in messagesJson) { TaskMessage taskMessage = RedisSerializer.DeserializeObject <TaskMessage>(messageJson); string instanceId = taskMessage.OrchestrationInstance.InstanceId; string orchestrationStateKey = RedisKeyNameResolver.GetOrchestrationRuntimeStateHashKey(this.taskHub, this.partition); string orchestrationInstanceQueueKey = RedisKeyNameResolver.GetOrchestrationQueueKey(this.taskHub, this.partition, instanceId); // Enter empty runtime state if it is an execution start event if (taskMessage.Event is ExecutionStartedEvent startedEvent) { OrchestrationRuntimeState emptyState = GetEmptyState(taskMessage); await database.HashSetAsync(orchestrationStateKey, instanceId, RedisSerializer.SerializeObject(emptyState.Events), When.NotExists); } await database.ListRightPopLeftPushAsync(this.partitionControlQueueKey, orchestrationInstanceQueueKey); this.activeOrchestrationLocks.TryAdd(instanceId, new SemaphoreSlim(1, 1)); } //Release lock so another notification can be handled this.controlQueueLock.Release(); }
private async Task <OrchestrationRuntimeState> GetOrchestrationRuntimeState(string orchestrationId) { IDatabase redisDatabase = this.redisConnection.GetDatabase(); string orchestrationRuntimeState = RedisKeyNameResolver.GetOrchestrationRuntimeStateHashKey(this.taskHub, this.partition); string eventListJson = await redisDatabase.HashGetAsync(orchestrationRuntimeState, orchestrationId); return(RedisSerializer.DeserializeRuntimeState(eventListJson)); }
public RedisTransactionBuilder SetOrchestrationRuntimeState(string orchestrationId, OrchestrationRuntimeState state) { if (this.partition == null) { throw new ArgumentNullException($"Cannot call {nameof(SetOrchestrationRuntimeState)} without a partition set."); } string orchestrationStateKey = RedisKeyNameResolver.GetOrchestrationRuntimeStateHashKey(this.taskHub, this.partition); // Do not want to serialize new events; state.NewEvents.Clear(); string stateJson = RedisSerializer.SerializeObject(state.Events); transaction.HashSetAsync(orchestrationStateKey, orchestrationId, stateJson); return(this); }
private async Task RestoreLocks() { IDatabase redisDatabase = this.redisConnection.GetDatabase(); string runtimeEventsKey = RedisKeyNameResolver.GetOrchestrationRuntimeStateHashKey(this.taskHub, this.partition); HashEntry[] runtimeEvents = await redisDatabase.HashGetAllAsync(runtimeEventsKey); foreach (var hashEntry in runtimeEvents) { OrchestrationRuntimeState state = RedisSerializer.DeserializeRuntimeState(hashEntry.Value); if (state.OrchestrationStatus == OrchestrationStatus.Pending || state.OrchestrationStatus == OrchestrationStatus.ContinuedAsNew || state.OrchestrationStatus == OrchestrationStatus.Running) { // Still running, so add lock this.activeOrchestrationLocks[hashEntry.Name] = new SemaphoreSlim(1); } } }