public async Task <ShardData> GetDataAsync(string type, Guid objectId) { switch (type) { case nameof(User): return(await _entitiesRepository.GetFirstOrDefaultAsync <User>(s => s.Id == objectId)); case nameof(BotKey): return(await _entitiesRepository.GetFirstOrDefaultAsync <BotKey>(w => w.Id == objectId)); case nameof(GlobalValue): return(await _entitiesRepository.GetFirstOrDefaultAsync <GlobalValue>(s => s.Id == objectId)); case nameof(StepTemplate): return(await _entitiesRepository.GetFirstOrDefaultAsync <StepTemplate>(s => s.Id == objectId)); case nameof(WorkflowTemplate): return(await _entitiesRepository.GetFirstOrDefaultAsync <WorkflowTemplate>(s => s.Id == objectId)); case nameof(Step): return(await _entitiesRepository.GetFirstOrDefaultAsync <Step>(s => s.Id == objectId)); case nameof(Workflow): return(await _entitiesRepository.GetFirstOrDefaultAsync <Workflow>(w => w.Id == objectId)); case nameof(ExecutionTemplate): return(await _entitiesRepository.GetFirstOrDefaultAsync <ExecutionTemplate>(w => w.Id == objectId)); case nameof(ExecutionSchedule): return(await _entitiesRepository.GetFirstOrDefaultAsync <ExecutionSchedule>(w => w.Id == objectId)); default: return(null); } }
public async Task <CommandResult> Handle(ExecuteExecutionTemplateCommand request, CancellationToken cancellationToken) { var executionTemplate = await _entitiesRepository.GetFirstOrDefaultAsync <ExecutionTemplate>(et => et.Name == request.Name); if (executionTemplate == null) { throw new InvalidExecutionRequestException("Execution template " + request.Name + " does not exits."); } if (executionTemplate.ExecutionTemplateType == ExecutionTemplateTypes.Step) { return(await _mediator.Send(new CreateStepCommand() { Name = executionTemplate.Name + " execution", StepTemplateId = executionTemplate.ReferenceId, ExecutionTemplateId = executionTemplate.Id, Inputs = executionTemplate.Inputs, CreatedBy = request.CreatedBy, ExecutionScheduleId = request.ExecutionScheduleId })); } else { return(await _mediator.Send(new CreateWorkflowCommand() { Name = executionTemplate.Name + " execution", WorkflowTemplateId = executionTemplate.ReferenceId, ExecutionTemplateId = executionTemplate.Id, Inputs = executionTemplate.Inputs, CreatedBy = request.CreatedBy, ExecutionScheduleId = request.ExecutionScheduleId })); } }
public async Task <CommandResult> Handle(AuthenticateUserCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); var user = await _entitiesRepository.GetFirstOrDefaultAsync <User>(u => u.Username == request.Username.ToLower()); if (user != null) { if (!user.IsDisabled) { if (SecurityUtility.IsMatchingHash(request.Password, user.HashedPassword, user.Salt)) { return(new CommandResult() { ObjectRefId = user.Username, ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.None }); } } } return(new CommandResult() { ElapsedMs = stopwatch.ElapsedMilliseconds, ObjectRefId = null, Type = CommandResultTypes.None }); }
public async Task <CommandResult> Handle(RecalculateExecutionScheduleCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); ExecutionSchedule schedule = await _entitiesRepository.GetFirstOrDefaultAsync <ExecutionSchedule>(st => st.Name == request.Name); if (schedule == null) { throw new InvalidExecutionScheduleException("Execution Schedule with name " + request.Name + " is invalid."); } var executionScheduleLock = await _node.Handle(new RequestDataShard() { Type = schedule.ShardType, ObjectId = schedule.Id, CreateLock = true, LockTimeoutMs = 10000 }); ExecutionSchedule existingValue; if (executionScheduleLock.IsSuccessful && executionScheduleLock.AppliedLocked) { existingValue = (ExecutionSchedule)executionScheduleLock.Data; existingValue.UpdateJournal(new Domain.Entities.JournalEntries.JournalEntry() { CreatedOn = DateTime.UtcNow, Updates = new List <Domain.ValueObjects.Update>() { new Update() { Type = UpdateType.Override, FieldName = "nextrun", Value = SchedulerUtility.NextOccurence(existingValue.Schedule, DateTime.UtcNow) } } }); var result = await _node.Handle(new AddShardWriteOperation() { Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Update, WaitForSafeWrite = true, Data = existingValue, RemoveLock = true }); } stopwatch.Stop(); return(new CommandResult <ExecutionSchedule>() { ObjectRefId = schedule.Id.ToString(), ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.Update, Result = schedule }); }
public async Task <QueryResult <string> > Handle(UnencryptStepFieldQuery request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); if (request.Type != StepEncryptionTypes.Inputs && request.Type != StepEncryptionTypes.Outputs) { throw new InvalidUnencryptionRequestException("No such encryption type " + request.Type); } var step = await _entitiesRepository.GetFirstOrDefaultAsync <Step>(s => s.Id == request.StepId); if (step.CreatedBy != request.UserId) { throw new InvalidStepPermissionException("Only the creating user can decrypt the step secret."); } var stepTemplate = await _entitiesRepository.GetFirstOrDefaultAsync <StepTemplate>(st => st.ReferenceId == step.StepTemplateId); //Compare the to lower of inputs, TODO - this is inefficient if (!stepTemplate.InputDefinitions.ContainsKey(request.FieldName.ToLower())) { throw new InvalidUnencryptionRequestException("Field " + request.FieldName + " does not exist on step template " + stepTemplate.Id); } DynamicDataDescription kv = request.Type == StepEncryptionTypes.Inputs ? stepTemplate.InputDefinitions[request.FieldName.ToLower()] : stepTemplate.OutputDefinitions[request.FieldName.ToLower()]; if (kv.Type != InputDataTypes.Secret) { throw new InvalidUnencryptionRequestException("Field " + request.FieldName + " is not a secret type."); } var decryptedInput = DynamicDataUtility.DecryptDynamicData(stepTemplate.InputDefinitions, request.Type == StepEncryptionTypes.Inputs ? step.Inputs : step.Outputs, EncryptionProtocol.AES256, ClusterStateService.GetEncryptionKey(), false); stopwatch.Stop(); return(new QueryResult <string>() { ElapsedMs = stopwatch.ElapsedMilliseconds, Count = 1, Result = (string)decryptedInput[request.FieldName.ToLower()] }); }
public async Task <QueryResult <T> > Handle(GetEntityQuery <T> request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); var result = await _entitiesRepository.GetFirstOrDefaultAsync <T>(request.Expression); stopwatch.Stop(); return(new QueryResult <T>() { Result = result, Count = result == null ? 0 : 1, ElapsedMs = stopwatch.ElapsedMilliseconds }); }
public async Task <QueryResult <object> > Handle(GetMetricsQuery request, CancellationToken cancellationToken) { var foundMetric = await _entitiesRepository.GetFirstOrDefaultAsync <Metric>(m => m.MetricName == request.MetricName); if (foundMetric == null) { throw new NotImplementedException("No metric " + request.MetricName); } var result = await _metricTicksRepository.GetMetricTicksAsync(request.From, request.To, foundMetric.MetricId, request.Aggs, request.Interval, null, null, request.IncludeSubcategories); return(new QueryResult <object>() { Result = result }); }
public async Task <CommandResult> Handle(AppendStepLogCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); var step = await _entitiesRepository.GetFirstOrDefaultAsync <Step>(e => e.Id == request.StepId); if (StepStatuses.IsCompleteStatus(step.Status)) { throw new InvalidStepStatusException("Cannot append log to step, step status is complete with " + step.Status); } step.UpdateJournal(new Domain.Entities.JournalEntries.JournalEntry() { CreatedBy = request.CreatedBy, CreatedOn = DateTime.UtcNow, Updates = new List <Domain.ValueObjects.Update>() { new Update() { Type = UpdateType.Append, FieldName = "logs", Value = new StepLog() { CreatedOn = DateTime.UtcNow, Message = request.Log }, } } }); //await _entitiesRepository.UpdateStep(step); var createdWorkflowTemplateId = await _node.Handle(new AddShardWriteOperation() { Data = step, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Update }); return(new CommandResult() { ElapsedMs = stopwatch.ElapsedMilliseconds, ObjectRefId = step.Id.ToString(), Type = CommandResultTypes.Update }); }
public async Task <CommandResult <Step> > Handle(CreateStepCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); var resolvedTemplate = await _entitiesRepository.GetFirstOrDefaultAsync <StepTemplate>(st => st.ReferenceId == request.StepTemplateId); if (resolvedTemplate == null) { throw new StepTemplateNotFoundException("Step template " + request.StepTemplateId + " not found."); } var newStep = resolvedTemplate.GenerateStep(request.StepTemplateId, request.CreatedBy, request.Name, request.Description, request.Inputs, request.Tests, request.WorkflowId, ClusterStateService.GetEncryptionKey(), request.ExecutionTemplateId, request.ExecutionScheduleId); /* var createdStepId = await _entitiesRepository.InsertStepAsync( * newStep * );*/ await _node.Handle(new AddShardWriteOperation() { Data = newStep, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Create }); stopwatch.Stop(); return(new CommandResult <Step>() { ObjectRefId = newStep.Id.ToString(), ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.Create, Result = newStep }); }
public async Task <CommandResult <Workflow> > Handle(CreateWorkflowCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); WorkflowTemplate template = await _entitiesRepository.GetFirstOrDefaultAsync <WorkflowTemplate>(wft => wft.ReferenceId == request.WorkflowTemplateId); if (template == null) { throw new WorkflowTemplateNotFoundException("Workflow Template " + request.WorkflowTemplateId + " not found."); } if (template.InputDefinitions.Count() < request.Inputs.Count()) { throw new InvalidInputsException("Invalid number of inputs, number passed was " + request.Inputs.Count() + " which is less then defined " + template.InputDefinitions.Count()); } var verifiedWorkflowInputs = new Dictionary <string, object>(); if (template.InputDefinitions != null) { foreach (var input in template.InputDefinitions) { if (!request.Inputs.ContainsKey(input.Key)) { throw new MissingInputException("Workflow input data is missing " + input.Key); } } foreach (var input in request.Inputs) { if (template.InputDefinitions.ContainsKey(input.Key) && template.InputDefinitions[input.Key].Type == InputDataTypes.Secret && !InputDataUtility.IsInputReference(input, out _, out _)) { verifiedWorkflowInputs.Add(input.Key.ToLower(), SecurityUtility.SymmetricallyEncrypt((string)input.Value, ClusterStateService.GetEncryptionKey())); } else { verifiedWorkflowInputs.Add(input.Key.ToLower(), input.Value); } } } var createdWorkflowId = Guid.NewGuid(); var startingLogicBlock = template.LogicBlocks.Where(lb => lb.Value.Dependencies.Evaluate(new List <Step>())).ToList(); var createdWorkflowTemplateId = await _node.Handle(new AddShardWriteOperation() { Data = new Domain.Entities.Workflows.Workflow( createdWorkflowId, request.WorkflowTemplateId, verifiedWorkflowInputs, //Encrypted inputs request.Name, request.CreatedBy, DateTime.UtcNow, request.ExecutionTemplateId, request.ExecutionScheduleId ), WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Create }); var workflow = await _entitiesRepository.GetFirstOrDefaultAsync <Workflow>(w => w.Id == createdWorkflowId); //When there are no conditions to be met // Needs to happen before first step is added DateTimeOffset WorkflowStartTime = DateTime.Now; foreach (var block in startingLogicBlock) { try { foreach (var subBlock in block.Value.SubsequentSteps) { var newStepTemplate = await _entitiesRepository.GetFirstOrDefaultAsync <StepTemplate>(st => st.ReferenceId == subBlock.Value.StepTemplateId); if (newStepTemplate == null) { throw new StepTemplateNotFoundException("Template " + subBlock.Value.StepTemplateId + " not found."); } var verifiedInputs = new Dictionary <string, object>(); foreach (var mapping in subBlock.Value.Mappings) { string mappedValue = ""; if ((mapping.Value.DefaultValue != null && (mapping.Value.OutputReferences == null || mapping.Value.OutputReferences.Count() == 0)) || (mapping.Value.DefaultValue != null && mapping.Value.OutputReferences.First() != null && mapping.Value.DefaultValue.Priority > mapping.Value.OutputReferences.First().Priority)) { // Change the ID to match the output verifiedInputs.Add(mapping.Key, mapping.Value.DefaultValue.Value); } else if (mapping.Value.OutputReferences != null) { verifiedInputs.Add(mapping.Key, DynamicDataUtility.GetData(request.Inputs, mapping.Value.OutputReferences.First().OutputId).Value); } } await _mediator.Send(new CreateStepCommand() { StepTemplateId = subBlock.Value.StepTemplateId, CreatedBy = SystemUsers.QUEUE_MANAGER, Description = null, Inputs = verifiedInputs, WorkflowId = createdWorkflowId, Name = subBlock.Key }); } workflow.UpdateJournal( new JournalEntry() { CreatedBy = request.CreatedBy, CreatedOn = DateTime.UtcNow, Updates = new List <Update>() { new Update() { FieldName = "completedlogicblocks", Type = UpdateType.Append, Value = block.Key //Add the logic block } } }); await _node.Handle(new AddShardWriteOperation() { Data = workflow, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Update }); } catch (Exception e) { _logger.LogCritical("Failed to action logic block " + block.Key + " with error " + e.Message + Environment.NewLine + e.StackTrace); } } stopwatch.Stop(); return(new CommandResult <Workflow>() { Result = workflow, ObjectRefId = createdWorkflowId.ToString(), ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.Create }); }
public async Task <CommandResult <ExecutionTemplate> > Handle(CreateExecutionTemplateCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); ExecutionTemplate template = await _entitiesRepository.GetFirstOrDefaultAsync <ExecutionTemplate>(st => st.Name == request.Name); if (template != null) { throw new InvalidExecutionTemplateException("Template with name " + request.Name + " is invalid."); } if (request.ExecutionTemplateType == ExecutionTemplateTypes.Step) { var stepTemplate = await _entitiesRepository.GetFirstOrDefaultAsync <StepTemplate>(st => st.ReferenceId == request.ReferenceId); if (stepTemplate == null) { throw new InvalidExecutionTemplateException("Failed to create execution template as " + request.ReferenceId + " does not exist."); } else { foreach (var input in request.Inputs) { if (!stepTemplate.IsStepInputValid(input)) { throw new InvalidExecutionTemplateException("Input " + input.Key + " is invalid."); } } } } else if (request.ExecutionTemplateType == ExecutionTemplateTypes.Workflow) { var workflowTemplate = await _entitiesRepository.GetFirstOrDefaultAsync <WorkflowTemplate>(st => st.ReferenceId == request.ReferenceId); if (workflowTemplate == null) { throw new InvalidExecutionTemplateException("Failed to create execution template as " + request.ReferenceId + " does not exist."); } else { foreach (var input in request.Inputs) { if (!workflowTemplate.IsWorkflowInputValid(input)) { throw new InvalidExecutionTemplateException("Input " + input.Key + " is invalid."); } } } } else { throw new InvalidExecutionTemplateException("Execution Template Type is Invalid."); } var executionTemplate = new ExecutionTemplate( Guid.NewGuid(), request.Name, request.ReferenceId, request.ExecutionTemplateType, request.Description, request.CreatedBy, request.Inputs); var executionTemplateResponse = await _node.Handle(new AddShardWriteOperation() { Data = executionTemplate, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Create }); stopwatch.Stop(); return(new CommandResult <ExecutionTemplate>() { ObjectRefId = executionTemplate.Id.ToString(), ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.Create, Result = executionTemplate }); }
public async Task <CommandResult> Handle(CreateWorkflowTemplateCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); var existingWorkflowTemplate = await _entitiesRepository.GetFirstOrDefaultAsync <WorkflowTemplate>(wft => wft.ReferenceId == request.Name + ":" + request.Version); if (existingWorkflowTemplate != null) { return(new CommandResult() { ObjectRefId = existingWorkflowTemplate.ReferenceId, ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.None }); } //Check that all step templates exists foreach (var lg in request.LogicBlocks) { foreach (var ss in lg.Value.SubsequentSteps) { var st = await _entitiesRepository.GetFirstOrDefaultAsync <StepTemplate>(stepTemplate => stepTemplate.ReferenceId == ss.Value.StepTemplateId); if (st == null) { throw new StepTemplateNotFoundException("Template " + ss.Value.StepTemplateId + " cannot be found."); } } } //Detect duplicates workflow step ref Id List <StepTemplate> allStepTemplates = new List <StepTemplate>(); HashSet <string> stepRefs = new HashSet <string>(); foreach (var block in request.LogicBlocks) { foreach (var subStep in block.Value.SubsequentSteps) { if (stepRefs.Contains(subStep.Key)) { throw new DuplicateWorkflowStepRefException("Found duplicate step refs for " + subStep.Key); } else { stepRefs.Add(subStep.Key); } allStepTemplates.Add(await _entitiesRepository.GetFirstOrDefaultAsync <StepTemplate>(stepTemplate => stepTemplate.ReferenceId == subStep.Value.StepTemplateId)); } } //Dictionary<int, HashSet<int>> ValidatedSubsequentSteps = new Dictionary<int, HashSet<int>>(); //ValidatedSubsequentSteps.Add(-1, new HashSet<int>()); //There should be at least one pre-requisite that returns as true var startingLogicBlock = request.LogicBlocks.Where(lb => lb.Value.Dependencies.Evaluate(new List <Domain.Entities.Steps.Step>())).ToList(); if (startingLogicBlock.Count() == 0) { throw new NoValidStartingLogicBlockException(); } var validatedLogicBlock = true; List <string> validatedLogicBlockIds = new List <string>(); validatedLogicBlockIds.AddRange(startingLogicBlock.Select(slb => slb.Key)); Dictionary <string, ConditionGroupValidation> validations = new Dictionary <string, ConditionGroupValidation>(); foreach (var lb in request.LogicBlocks) { validations.Add(lb.Key, null); } foreach (var startingLb in startingLogicBlock) { validations[startingLb.Key] = new ConditionGroupValidation() { IsValid = true, Reason = "Starting logic block" }; } while (validatedLogicBlock) { //reset to true validatedLogicBlock = false; //Only evaluate unvalidatedlogicblocks foreach (var block in request.LogicBlocks.Where(lb => !validatedLogicBlockIds.Contains(lb.Key))) { var validation = block.Value.Dependencies.ValidateConditionGroup(request.LogicBlocks.Where(lb => validatedLogicBlockIds.Contains(lb.Key)).Select(vlb => vlb.Value)); if (validations[block.Key] == null || !validations[block.Key].IsValid) { validations[block.Key] = validation; } if (validation.IsValid) { // Mark to re-evaluate the rest of the logicblocks validatedLogicBlock = true; validatedLogicBlockIds.Add(block.Key); foreach (var step in block.Value.SubsequentSteps) { //Check whether the step template exists var result = await _entitiesRepository.GetFirstOrDefaultAsync <StepTemplate>(stepTemplate => stepTemplate.ReferenceId == step.Value.StepTemplateId); foreach (var mapping in step.Value.Mappings) { WorkflowTemplate.ValidateMapping(mapping.Value); } if (result == null) { throw new StepTemplateNotFoundException("Step Template does not exist " + step.Value.StepTemplateId); } var flatMappedSubsequentSteps = request.LogicBlocks.Where(lb => validatedLogicBlockIds.Contains(lb.Key)).SelectMany(lb => lb.Value.SubsequentSteps.Select(ss => ss.Key)).ToList(); //Add start as a valid step flatMappedSubsequentSteps.Add("start"); foreach (var mapping in step.Value.Mappings) { if (mapping.Value.OutputReferences != null) { foreach (var reference in mapping.Value.OutputReferences) { if (!flatMappedSubsequentSteps.Contains(reference.StepName)) { throw new MissingStepException("Defined mapping for substep " + step.Key + " for mapping " + mapping.Key + " is missing " + reference.StepName); } else { if (reference.StepName != ReservedValues.WorkflowStartStepName) { var foundBlock = request.LogicBlocks.Where(st => st.Value.SubsequentSteps.Where(ss => ss.Key == reference.StepName).Count() > 0).First(); var resolvedSubstep = foundBlock.Value.SubsequentSteps.Where(ss => ss.Key == reference.StepName).First(); var foundTemplates = (allStepTemplates.Where(template => template.ReferenceId == resolvedSubstep.Value.StepTemplateId)); if (foundTemplates.Count() != 0) { var foundTemplate = foundTemplates.First(); if (foundTemplate.OutputDefinitions.Where(id => id.Key.ToLower() == reference.OutputId.ToLower()).Count() == 0) { throw new MissingOutputException("Missing output " + reference.OutputId + " for step " + step.Key + " from step template " + foundTemplate.Id); } } } else { var foundDefinition = request.InputDefinitions.Where(id => id.Key.ToLower() == reference.OutputId.ToLower()); if (foundDefinition.Count() == 0) { throw new MissingInputException("Missing input " + reference.OutputId + " for step " + step.Key + " from workflow input."); } } } } } else { if (mapping.Value.DefaultValue == null) { throw new MissingOutputException("Neither Value or Output References exist. If neither is required, this is a redundant output reference"); } } } } } } } // This is done inefficiently /*foreach (var block in request.LogicBlocks) * { * foreach (var substep in block.SubsequentSteps) * { * foreach (var mapping in substep.Mappings) * { * if (mapping.OutputReferences != null) * { * foreach (var reference in mapping.OutputReferences) * { * if (!ValidatedSubsequentSteps.ContainsKey(reference.WorkflowStepId)) * { * throw new MissingStepException("Defined mapping for substep " + substep.WorkflowStepId + " for mapping " + mapping.StepInputId + " is missing " + reference.WorkflowStepId); * } * else * { * if (reference.WorkflowStepId != -1) * { * var foundBlock = request.LogicBlocks.Where(st => st.SubsequentSteps.Where(ss => ss.WorkflowStepId == reference.WorkflowStepId).Count() > 0).First(); * * var resolvedSubstep = foundBlock.SubsequentSteps.Where(ss => ss.WorkflowStepId == reference.WorkflowStepId).First(); * * var foundTemplates = (allStepTemplates.Where(template => template.ReferenceId == resolvedSubstep.StepTemplateId)); * * if (foundTemplates.Count() != 0) * { * var foundTemplate = foundTemplates.First(); * if (foundTemplate.InputDefinitions.Where(id => id.Key.ToLower() != reference.OutputId.ToLower()).Count() == 0) * { * throw new MissingInputException("Missing input " + reference.OutputId + " for step " + substep.WorkflowStepId + " from step template " + foundTemplate.Id); * } * } * } * else * { * var foundDefinition = request.InputDefinitions.Where(id => id.Key.ToLower() == reference.OutputId.ToLower()); * if (foundDefinition.Count() == 0) * { * throw new MissingInputException("Missing input " + reference.OutputId + " for step " + substep.WorkflowStepId + " from workflow input."); * } * } * } * } * } * else * { * if (mapping.DefaultValue == null) * { * throw new MissingOutputException("Neither Value or Output References exist. If neither is required, this is a redundant output reference"); * } * } * } * } * }*/ var newId = Guid.NewGuid(); var newWorkflowTemplate = new WorkflowTemplate(newId, request.Name + ":" + request.Version, request.Description, request.InputDefinitions, request.LogicBlocks, request.CreatedBy, DateTime.UtcNow ); var createdWorkflowTemplateId = await _node.Handle(new AddShardWriteOperation() { Data = newWorkflowTemplate, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Create }); stopwatch.Stop(); return(new CommandResult() { ObjectRefId = newWorkflowTemplate.ReferenceId, ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.Create }); }
public async Task <CommandResult> Handle(UnassignStepCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); Step step; if ((step = await _entitiesRepository.GetFirstOrDefaultAsync <Step>(e => (e.Status == StepStatuses.Suspended || e.Status == StepStatuses.Assigned) && e.Id == request.StepId)) == null) { Logger.LogWarning("Step " + request.StepId + " has a status that cannot be unassigned."); return(new CommandResult() { ElapsedMs = stopwatch.ElapsedMilliseconds, ObjectRefId = request.StepId.ToString(), Type = CommandResultTypes.None }); } var stepLockResult = await _node.Handle(new RequestDataShard() { Type = "Step", ObjectId = request.StepId, CreateLock = true, LockTimeoutMs = 10000 }); if (stepLockResult.IsSuccessful && stepLockResult.AppliedLocked) { step = (Step)stepLockResult.Data; if (step.Status != StepStatuses.Suspended && step.Status != StepStatuses.Assigned) { Logger.LogWarning("Step " + request.StepId + " has status " + step.Status + ". Only suspended steps can be unassigned."); return(new CommandResult() { ElapsedMs = stopwatch.ElapsedMilliseconds, ObjectRefId = step.Id.ToString(), Type = CommandResultTypes.None }); } step.UpdateJournal(new Domain.Entities.JournalEntries.JournalEntry() { CreatedOn = DateTime.UtcNow, CreatedBy = request.CreatedBy, Updates = new List <Domain.ValueObjects.Update>() { new Update() { Type = UpdateType.Override, FieldName = "status", Value = StepStatuses.Unassigned, }, new Update() { FieldName = "assignedto", Type = UpdateType.Override, Value = null } } }); var result = await _node.Handle(new AddShardWriteOperation() { Data = step, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Update, RemoveLock = true }); if (result.IsSuccessful) { return(new CommandResult() { ElapsedMs = stopwatch.ElapsedMilliseconds, ObjectRefId = step.Id.ToString(), Type = CommandResultTypes.Update }); } else { throw new FailedClusterOperationException("Failed to apply cluster operation with for step " + step.Id); } } else { throw new FailedClusterOperationException("Step " + request.StepId + " failed to have a lock applied."); } }
public async Task <CommandResult> Handle(UpdateExecutionScheduleCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); ExecutionSchedule schedule = await _entitiesRepository.GetFirstOrDefaultAsync <ExecutionSchedule>(st => st.Name == request.Name); if (schedule == null) { throw new InvalidExecutionScheduleException("Execution Schedule with name " + request.Name + " is invalid."); } if (request.Schedule != null) { foreach (var scheduleString in request.Schedule) { var isValid = SchedulerUtility.IsValidScheduleString(scheduleString); if (!isValid) { throw new InvalidExecutionScheduleException("Schedule " + scheduleString + " is invalid."); } } } var executionScheduleLock = await _node.Handle(new RequestDataShard() { Type = schedule.ShardType, ObjectId = schedule.Id, CreateLock = true }); ExecutionSchedule existingValue; List <Update> updates = new List <Update>(); if (request.IsDisabled != null && schedule.IsDisabled != request.IsDisabled) { updates.Add(new Update() { Type = UpdateType.Override, FieldName = "isdisabled", Value = request.IsDisabled }); } if (request.Schedule != null && schedule.Schedule != request.Schedule) { updates.Add(new Update() { Type = UpdateType.Override, FieldName = "nextrun", Value = SchedulerUtility.NextOccurence(request.Schedule, DateTime.UtcNow) }); updates.Add(new Update() { Type = UpdateType.Override, FieldName = "schedule", Value = request.Schedule }); } if (request.Description != null && schedule.Description != request.Description) { updates.Add(new Update() { Type = UpdateType.Override, FieldName = "description", Value = request.Description }); } if (executionScheduleLock.IsSuccessful && executionScheduleLock.AppliedLocked && updates.Count > 0) { existingValue = (ExecutionSchedule)executionScheduleLock.Data; existingValue.UpdateJournal(new Domain.Entities.JournalEntries.JournalEntry() { CreatedOn = DateTime.UtcNow, Updates = updates }); var result = await _node.Handle(new AddShardWriteOperation() { Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Update, WaitForSafeWrite = true, Data = existingValue, RemoveLock = true }); } stopwatch.Stop(); return(new CommandResult <ExecutionSchedule>() { ObjectRefId = schedule.Id.ToString(), ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.Update, Result = schedule }); }
public async Task <CommandResult <GlobalValue> > Handle(UpdateGlobalValueCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); GlobalValue existingValue; if ((existingValue = await _entitiesRepository.GetFirstOrDefaultAsync <GlobalValue>(gv => gv.Name == request.Name)) == null) { throw new InvalidGlobalValuesException("The global value name " + request.Name + " does not exist."); } var globalValueLock = await _node.Handle(new RequestDataShard() { Type = existingValue.ShardType, ObjectId = existingValue.Id, CreateLock = true }); if (globalValueLock.IsSuccessful && globalValueLock.AppliedLocked) { existingValue = (GlobalValue)globalValueLock.Data; existingValue.UpdateJournal(new Domain.Entities.JournalEntries.JournalEntry() { CreatedBy = request.CreatedBy, CreatedOn = DateTime.UtcNow, Updates = new List <Domain.ValueObjects.Update>() { new Update() { Type = UpdateType.Override, FieldName = "value", Value = request.Value, }, new Update() { Type = UpdateType.Override, FieldName = "description", Value = request.Description, } } }); var result = await _node.Handle(new AddShardWriteOperation() { Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Update, WaitForSafeWrite = true, Data = existingValue, RemoveLock = true }); stopwatch.Stop(); return(new CommandResult <GlobalValue>() { ObjectRefId = existingValue.Id.ToString(), ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.Update, Result = existingValue }); } else { throw new FailedClusterOperationException("Global Value " + request.Name + " failed to have a lock applied."); } }
public async Task <CommandResult> Handle(SuspendStepCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); Step step = await _entitiesRepository.GetFirstOrDefaultAsync <Step>(e => e.Id == request.StepId); if (step == null) { throw new Exception("Failed to find step " + step.Id); } if (step.Status == StepStatuses.Suspended) { return(new CommandResult() { ElapsedMs = stopwatch.ElapsedMilliseconds, ObjectRefId = request.StepId.ToString(), Type = CommandResultTypes.None }); } var stepLockResult = await _node.Handle(new RequestDataShard() { Type = "Step", ObjectId = request.StepId, CreateLock = true, LockTimeoutMs = 10000 }); // Applied the lock successfully if (stepLockResult.IsSuccessful && stepLockResult.AppliedLocked) { Logger.LogInformation("Applied lock on step " + request.StepId + " with lock id " + stepLockResult.LockId); step = (Step)stepLockResult.Data; if (step.Status == StepStatuses.Unassigned || step.Status == StepStatuses.Suspended || step.Status == StepStatuses.Assigned // You should only be suspending a assigned step if it is being suspended by the bot assigned, check to be done in presentation ) { step.UpdateJournal(new Domain.Entities.JournalEntries.JournalEntry() { CreatedOn = DateTime.UtcNow, CreatedBy = request.CreatedBy, Updates = new List <Domain.ValueObjects.Update>() { new Update() { Type = UpdateType.Override, FieldName = "status", Value = StepStatuses.Suspended }, new Update() { Type = UpdateType.Override, FieldName = "suspendeduntil", Value = request.SuspendedUntil }, new Update() { FieldName = "assignedto", Type = UpdateType.Override, Value = null } } }); var result = await _node.Handle(new AddShardWriteOperation() { Data = step, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Update, RemoveLock = true, LockId = stepLockResult.LockId.Value }); if (result.IsSuccessful) { return(new CommandResult() { ElapsedMs = stopwatch.ElapsedMilliseconds, ObjectRefId = step.Id.ToString(), Type = CommandResultTypes.Update }); } else { throw new FailedClusterOperationException("Failed to apply cluster operation with for step " + step.Id); } } else { throw new InvalidStepStatusException("Step " + request.StepId + " could not be paused as it has status " + step.Status); } } else { throw new FailedClusterOperationException("Step " + request.StepId + " failed to have a lock applied."); } }
public async Task <CommandResult> Handle(ScanWorkflowCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); List <string> messages = new List <string>(); bool workflowStillRunning = false; var workflow = await _entitiesRepository.GetFirstOrDefaultAsync <Workflow>(w => w.Id == request.WorkflowId); if (workflow == null) { throw new MissingWorkflowException("Failed to find workflow " + request.WorkflowId + " as workflow does not exist."); } //Get the workflow template var workflowTemplate = await _entitiesRepository.GetFirstOrDefaultAsync <WorkflowTemplate>(wt => wt.ReferenceId == workflow.WorkflowTemplateId); if (workflowTemplate == null) { throw new WorkflowTemplateNotFoundException("Failed to scan workflow " + request.WorkflowId + " workflow template " + workflow.WorkflowTemplateId + "."); } //Get all the steps related to this task var workflowSteps = (await _entitiesRepository.GetAsync <Step>(s => s.WorkflowId == request.WorkflowId)).ToList(); foreach (var workflowStep in workflowSteps) { workflowStep.Outputs = DynamicDataUtility.DecryptDynamicData((await _entitiesRepository.GetFirstOrDefaultAsync <StepTemplate>(st => st.ReferenceId == workflowStep.StepTemplateId)).OutputDefinitions, workflowStep.Outputs, EncryptionProtocol.AES256, ClusterStateService.GetEncryptionKey()); if (!workflowStep.IsComplete()) { messages.Add("Workflow step " + workflowStep.Id + " (" + workflowStep.Name + ")" + " is running."); workflowStillRunning = true; } } bool stepCreated = false; if (!workflowStillRunning) { if (workflow.CompletedLogicBlocks == null) { workflow.CompletedLogicBlocks = new List <string>(); } //Evaluate all logic blocks that have not been completed var logicBlocks = workflowTemplate.LogicBlocks.Where(lb => !workflow.CompletedLogicBlocks.Contains(lb.Key)).ToList(); foreach (var logicBlock in logicBlocks) { var lockId = Guid.NewGuid(); bool lockObtained = false; while (!lockObtained) { while (_clusterStateService.IsLogicBlockLocked(request.WorkflowId, logicBlock.Key)) { Console.WriteLine("Found " + ("workflow:" + request.WorkflowId + ">logicBlock:" + logicBlock) + " Lock"); await Task.Delay(1000); } int entryNumber = await _clusterStateService.LockLogicBlock(lockId, request.WorkflowId, logicBlock.Key); //Check whether you got the lock lockObtained = _clusterStateService.WasLockObtained(lockId, request.WorkflowId, logicBlock.Key); } //When the logic block is released, recheck whether this logic block has been evaluated workflow = await _entitiesRepository.GetFirstOrDefaultAsync <Workflow>(w => w.Id == request.WorkflowId); workflow.Inputs = DynamicDataUtility.DecryptDynamicData(workflowTemplate.InputDefinitions, workflow.Inputs, EncryptionProtocol.AES256, ClusterStateService.GetEncryptionKey()); if (workflow.CompletedLogicBlocks == null) { workflow.CompletedLogicBlocks = new List <string>(); } //If the logic block is ready to be processed, submit the steps if (logicBlock.Value.Dependencies.Evaluate(workflowSteps) && !workflow.CompletedLogicBlocks.Contains(logicBlock.Key)) { foreach (var substep in logicBlock.Value.SubsequentSteps) { if (workflowSteps.Where(s => s.Name == substep.Key).Count() == 0) { var verifiedInputs = new Dictionary <string, object>(); foreach (var mapping in substep.Value.Mappings) { //find the mapping with the highest priority var highestPriorityReference = WorkflowTemplateUtility.GetHighestPriorityReference(mapping.Value.OutputReferences, workflowSteps.ToArray()); //if the highest priority reference is null, there are no mappings if (highestPriorityReference == null && mapping.Value.DefaultValue == null) { } // If default value is higher priority else if (mapping.Value.DefaultValue != null && (highestPriorityReference == null || highestPriorityReference.Priority < mapping.Value.DefaultValue.Priority)) { verifiedInputs.Add(mapping.Key, mapping.Value.DefaultValue.Value); } // If the step ref is not -1 it is a step in the array but the workflow else if (highestPriorityReference.StepName != ReservedValues.WorkflowStartStepName) { var parentStep = workflowSteps.Where(ss => ss.Name == highestPriorityReference.StepName).FirstOrDefault(); //If there is a AND and there is no parent step, throw a error if (parentStep == null) { throw new InvalidWorkflowProcessingException("Missing source for mapping " + mapping.Key + " from step " + highestPriorityReference.StepName); } else { if (parentStep != null) { try { // Get the output value based on the pre-requisite id var outPutValue = DynamicDataUtility.GetData(parentStep.Outputs, highestPriorityReference.OutputId); // Validate it is in the definition verifiedInputs.Add(mapping.Key, outPutValue.Value); } catch (Exception e) { //TO DO Move this to logger Console.WriteLine("Found error at mapping " + mapping.Key + " for step " + substep.Key); throw e; } } } } //Get the value from the workflow ref else { // Validate it is in the definition verifiedInputs.Add(mapping.Key, DynamicDataUtility.GetData(workflow.Inputs, highestPriorityReference.OutputId).Value); } } stepCreated = true; //Add the step TODO, add step priority await _mediator.Send(new CreateStepCommand() { StepTemplateId = substep.Value.StepTemplateId, CreatedBy = SystemUsers.QUEUE_MANAGER, Inputs = verifiedInputs, WorkflowId = workflow.Id, Name = substep.Key //create the step with the right subsequent step }); messages.Add("Started workflow step " + substep.Key); } } //Mark it as evaluated workflow.UpdateJournal( new JournalEntry() { CreatedBy = request.CreatedBy, CreatedOn = DateTime.UtcNow, Updates = new List <Update>() { new Update() { FieldName = "completedlogicblocks", Type = UpdateType.Append, Value = logicBlock.Key } } }); //await _workflowsRepository.UpdateWorkflow(workflow); await _node.Handle(new AddShardWriteOperation() { Data = workflow, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Update }); } await _clusterStateService.UnlockLogicBlock(lockId, request.WorkflowId, logicBlock.Key); } //Check if there are no longer any steps that are unassigned or assigned var workflowStatus = workflow.Status; workflowSteps = (await _entitiesRepository.GetAsync <Step>(s => s.WorkflowId == request.WorkflowId)).ToList(); var highestStatus = StepStatuses.GetHighestPriority(workflowSteps.Select(s => s.Status).ToArray()); var newWorkflowStatus = stepCreated ? WorkflowStatuses.ConvertStepStatusToWorkflowStatus(StepStatuses.Unassigned) : WorkflowStatuses.ConvertStepStatusToWorkflowStatus(highestStatus); if (newWorkflowStatus != workflow.Status) { workflow.UpdateJournal( new JournalEntry() { CreatedBy = request.CreatedBy, CreatedOn = DateTime.UtcNow, Updates = new List <Update>() { new Update() { FieldName = "status", Type = UpdateType.Override, Value = newWorkflowStatus } } }); //await _workflowsRepository.UpdateWorkflow(workflow); await _node.Handle(new AddShardWriteOperation() { Data = workflow, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Update }); messages.Add("Updated workflow status " + newWorkflowStatus + "."); } } return(new CommandResult() { ObjectRefId = request.WorkflowId.ToString(), ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.Update, IsSuccessful = true, Messages = messages.ToArray() }); }
public async Task <CommandResult <Step> > Handle(AssignStepCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); List <Guid> ignoreUnassignedSteps = new List <Guid>(); if (_clusterStateService.GetSettings.AssignmentEnabled) { var assignedStepSuccessfully = false; Step unassignedStep = null; var dateChecked = DateTime.UtcNow; BotKey botkey; if (!_cache.TryGetValue(request.BotId, out botkey)) { // Set cache options. var cacheEntryOptions = new MemoryCacheEntryOptions() // Keep in cache for this time, reset time if accessed. .SetSlidingExpiration(TimeSpan.FromSeconds(10)); botkey = await _entitiesRepository.GetFirstOrDefaultAsync <BotKey>(bk => bk.Id == request.BotId); // Save data in cache. _cache.Set(request.BotId, botkey, cacheEntryOptions); } if (botkey.IsDisabled) { return(new CommandResult <Step>(new BotKeyAssignmentException("Bot " + botkey.Id + " is disabled.")) { Type = CommandResultTypes.Update, ElapsedMs = stopwatch.ElapsedMilliseconds }); } ignoreUnassignedSteps.AddRange(_clusterStateService.GetState().Locks.Where(l => l.Key.Contains("_object")).Select(ol => new Guid(ol.Key.Split(':').Last()))); do { unassignedStep = (await _entitiesRepository.GetAsync <Step>(s => s.Status == StepStatuses.Unassigned && request.StepTemplateIds.Contains(s.StepTemplateId) && !ignoreUnassignedSteps.Contains(s.Id), null, "CreatedOn:1", 1, 0)).FirstOrDefault(); if (unassignedStep != null) { var assigned = await _node.Handle(new RequestDataShard() { Type = unassignedStep.ShardType, ObjectId = unassignedStep.Id, CreateLock = true, LockTimeoutMs = 10000 }); //Apply a lock on the item if (assigned != null && assigned.IsSuccessful && assigned.AppliedLocked) { //Real values to pass to the Microservice Dictionary <string, object> realAssignedValues = new Dictionary <string, object>(); //Inputs that have been converted to reference expression Dictionary <string, object> convertedInputs = new Dictionary <string, object>(); var template = await _entitiesRepository.GetFirstOrDefaultAsync <StepTemplate>(st => st.ReferenceId == unassignedStep.StepTemplateId); try { //This should not throw a error externally, the server should loop to the next one and log a error if (unassignedStep.Status != StepStatuses.Unassigned) { throw new InvalidStepQueueException("You cannot assign step " + unassignedStep.Id + " as it is not unassigned."); } bool inputsUpdated = false; foreach (var input in unassignedStep.Inputs) { string convertedValue = ""; bool isReferenceByValue = false; var isReference = InputDataUtility.IsInputReference(input, out convertedValue, out isReferenceByValue); if (input.Value is string && ((string)input.Value).Length > 1) { if (isReference) { //Copy by reference if (isReferenceByValue) { var foundGlobalValue = await _entitiesRepository.GetFirstOrDefaultAsync <GlobalValue>(gv => gv.Name == convertedValue); if (foundGlobalValue == null) { Logger.LogWarning("No global value was found for value " + input.Value); realAssignedValues.Add(input.Key, null); convertedInputs.Add(input.Key, input.Value + ":?"); } else if (foundGlobalValue.Type != template.InputDefinitions[input.Key].Type) { Logger.LogWarning("Global value was found for value " + input.Value + " however they are different types. " + template.InputDefinitions[input.Key].Type + " vs " + foundGlobalValue.Type); realAssignedValues.Add(input.Key, null); convertedInputs.Add(input.Key, input.Value + ":?"); } else { realAssignedValues.Add(input.Key, foundGlobalValue.Value); convertedInputs.Add(input.Key, input.Value + ":" + foundGlobalValue.Journal.GetCurrentChainId()); } } //copy by value else { var foundGlobalValue = await _entitiesRepository.GetFirstOrDefaultAsync <GlobalValue>(gv => gv.Name == convertedValue); if (foundGlobalValue == null) { Logger.LogWarning("No global value was found for value " + input.Value); realAssignedValues.Add(input.Key, null); convertedInputs.Add(input.Key, null); } else if (foundGlobalValue.Type != template.InputDefinitions[input.Key].Type) { Logger.LogWarning("Global value was found for value " + input.Value + " however they are different types. " + template.InputDefinitions[input.Key].Type + " vs " + foundGlobalValue.Type); realAssignedValues.Add(input.Key, null); convertedInputs.Add(input.Key, null); } else { realAssignedValues.Add(input.Key, foundGlobalValue.Value); convertedInputs.Add(input.Key, foundGlobalValue.Value); } } inputsUpdated = true; } else if (input.Value is string && ((string)input.Value).Length > 1 && ((string)input.Value).First() == '\\') { var escapedCommand = ((string)input.Value); //The $ is escaped realAssignedValues.Add(input.Key, ((string)input.Value).Substring(1, escapedCommand.Length - 1)); convertedInputs.Add(input.Key, input.Value); inputsUpdated = true; } else { realAssignedValues.Add(input.Key, input.Value); convertedInputs.Add(input.Key, input.Value); } } else { realAssignedValues.Add(input.Key, input.Value); convertedInputs.Add(input.Key, input.Value); } } //If a update was detected then add it to the journal updates if (inputsUpdated) { unassignedStep.UpdateJournal(new Domain.Entities.JournalEntries.JournalEntry() { CreatedBy = SystemUsers.QUEUE_MANAGER, CreatedOn = DateTime.UtcNow, Updates = new List <Update>() { new Update() { Type = UpdateType.Override, FieldName = "status", Value = StepStatuses.Assigned }, new Update() { FieldName = "inputs", Type = UpdateType.Override, Value = convertedInputs }, new Update() { FieldName = "assignedto", Type = UpdateType.Override, Value = request.BotId } } }); } else { unassignedStep.UpdateJournal(new Domain.Entities.JournalEntries.JournalEntry() { CreatedBy = SystemUsers.QUEUE_MANAGER, CreatedOn = DateTime.UtcNow, Updates = new List <Update>() { new Update() { Type = UpdateType.Override, FieldName = "status", Value = StepStatuses.Assigned } } }); } await _node.Handle(new AddShardWriteOperation() { Data = unassignedStep, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Update, RemoveLock = true, LockId = assigned.LockId.Value }); //await _entitiesRepository.UpdateStep(unassignedStep); if (inputsUpdated) { //Update the record with real values, this is not commited to DB unassignedStep.UpdateJournal(new Domain.Entities.JournalEntries.JournalEntry() { CreatedBy = SystemUsers.QUEUE_MANAGER, CreatedOn = DateTime.UtcNow, Updates = new List <Update>() { new Update() { FieldName = "inputs", Type = UpdateType.Override, Value = realAssignedValues } } }); } } catch (Exception e) { Console.WriteLine(e.Message); //throw e; } assignedStepSuccessfully = true; } else { ignoreUnassignedSteps.Add(unassignedStep.Id); assignedStepSuccessfully = false; } } //There were no unassigned steps to assign else { assignedStepSuccessfully = true; } }while (!assignedStepSuccessfully); if (unassignedStep != null) { var template = await _entitiesRepository.GetFirstOrDefaultAsync <StepTemplate>(st => st.ReferenceId == unassignedStep.StepTemplateId); //Decrypt the step unassignedStep.Inputs = DynamicDataUtility.DecryptDynamicData(template.InputDefinitions, unassignedStep.Inputs, EncryptionProtocol.AES256, ClusterStateService.GetEncryptionKey()); unassignedStep.RemoveDelimiters(); //Encrypt the step unassignedStep.Inputs = DynamicDataUtility.EncryptDynamicData(template.InputDefinitions, unassignedStep.Inputs, EncryptionProtocol.RSA, botkey.PublicEncryptionKey, true); } stopwatch.Stop(); return(new CommandResult <Step>() { ObjectRefId = unassignedStep != null?unassignedStep.Id.ToString() : "", ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.Update, Result = unassignedStep != null ? unassignedStep : null }); } else { return(new CommandResult <Step>() { ObjectRefId = "", ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.None }); } }
public async Task <CommandResult> Handle(CreateExecutionScheduleCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); ExecutionSchedule schedule = await _entitiesRepository.GetFirstOrDefaultAsync <ExecutionSchedule>(st => st.Name == request.Name); if (schedule != null) { throw new InvalidExecutionScheduleException("Execution Schedule with name " + request.Name + " is invalid."); } ExecutionTemplate template = await _entitiesRepository.GetFirstOrDefaultAsync <ExecutionTemplate>(st => st.Name == request.ExecutionTemplateName); if (template == null) { throw new InvalidExecutionScheduleException("Execution Template with name " + request.ExecutionTemplateName + " is invalid."); } foreach (var scheduleString in request.Schedule) { var isValid = SchedulerUtility.IsValidScheduleString(scheduleString); if (!isValid) { throw new InvalidExecutionScheduleException("Schedule " + scheduleString + " is invalid."); } } var executionSchedule = new ExecutionSchedule( Guid.NewGuid(), request.Name, request.ExecutionTemplateName, request.Description, request.CreatedBy, request.Schedule, SchedulerUtility.NextOccurence(request.Schedule) ); var executionScheduleResponse = await _node.Handle(new AddShardWriteOperation() { Data = executionSchedule, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Create }); if (request.RunImmediately) { await _mediator.Send(new ExecuteExecutionTemplateCommand() { CreatedBy = request.CreatedBy, ExecutionScheduleId = executionSchedule.Id, Name = executionSchedule.ExecutionTemplateName }); } stopwatch.Stop(); return(new CommandResult <ExecutionSchedule>() { ObjectRefId = executionSchedule.Id.ToString(), ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.Create, Result = executionSchedule }); }
public async Task <CommandResult> Handle(CreateStepTemplateCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); if (request.ReferenceId != null) { request.Name = request.ReferenceId.Split(':')[0]; request.Version = request.ReferenceId.Split(':')[1]; } var newId = Guid.NewGuid(); var newStepTemplate = new StepTemplate( newId, request.ReferenceId == null ? request.Name + ":" + request.Version : request.ReferenceId, request.Description, request.AllowDynamicInputs, request.InputDefinitions.ToDictionary(entry => entry.Key.ToLower(), entry => entry.Value), request.OutputDefinitions.ToDictionary(entry => entry.Key.ToLower(), entry => entry.Value), request.CreatedBy, DateTime.UtcNow ); var existingStepTemplate = await _entitiesRepository.GetFirstOrDefaultAsync <StepTemplate>(st => st.ReferenceId == newStepTemplate.ReferenceId); if (existingStepTemplate == null) { if (request.Name.First() == '_' && request.CreatedBy != SystemUsers.SYSTEM_TEMPLATES_MANAGER) { throw new InvalidStepTemplateException("Only system workflows can start with _"); } var createdWorkflowTemplateId = await _node.Handle(new AddShardWriteOperation() { Data = newStepTemplate, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Create }); } else { Logger.LogDebug("Found existing step template"); BaseException exception; if (!existingStepTemplate.IsEqual(newStepTemplate, out exception)) { throw exception; } } stopwatch.Stop(); return(new CommandResult() { ObjectRefId = newStepTemplate.ReferenceId, ElapsedMs = stopwatch.ElapsedMilliseconds, Type = CommandResultTypes.Create }); }
public async Task <CommandResult <BotKey> > Handle(UpdateBotKeyCommand request, CancellationToken cancellationToken) { var stopwatch = new Stopwatch(); stopwatch.Start(); var botKey = await _entitiesRepository.GetFirstOrDefaultAsync <BotKey>(bk => bk.Id == request.Id); var update = false; if (request.IsDisabled != null && botKey.IsDisabled != request.IsDisabled) { botKey.IsDisabled = request.IsDisabled.Value; update = true; } if (request.BotName != null && botKey.BotName != request.BotName) { botKey.BotName = request.BotName; update = true; } if (update) { var botLockResult = await _node.Handle(new RequestDataShard() { Type = "BotKey", ObjectId = request.Id, CreateLock = true }); if (botLockResult.IsSuccessful && botLockResult.AppliedLocked) { if (update) { var result = await _node.Handle(new AddShardWriteOperation() { Data = botKey, WaitForSafeWrite = true, Operation = ConsensusCore.Domain.Enums.ShardOperationOptions.Update, RemoveLock = true }); if (result.IsSuccessful) { return(new CommandResult <BotKey>() { ElapsedMs = stopwatch.ElapsedMilliseconds, ObjectRefId = request.Id.ToString(), Type = CommandResultTypes.Update, Result = botKey }); } else { throw new FailedClusterOperationException("Failed to apply cluster operation with for botKey " + request.Id); } } } else { throw new FailedClusterOperationException("Failed to apply cluster operation with for botkey " + botKey.Id); } } return(new CommandResult <BotKey>() { ElapsedMs = stopwatch.ElapsedMilliseconds, ObjectRefId = request.Id.ToString(), Type = CommandResultTypes.Update, Result = botKey }); }