diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 9ce8a6ee..bb0eed77 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -1,6 +1,13 @@ name: CI Build -on: [push, pull_request,workflow_dispatch] +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_dispatch: jobs: lint: diff --git a/Conductor/Api/EnvironmentResourceApi.cs b/Conductor/Api/EnvironmentResourceApi.cs index 60b029ac..732a4ea3 100644 --- a/Conductor/Api/EnvironmentResourceApi.cs +++ b/Conductor/Api/EnvironmentResourceApi.cs @@ -597,9 +597,13 @@ public ApiResponse> GetAllWithHttpInfo() if (exception != null) throw exception; } + var list = (List>)this.Configuration.ApiClient.Deserialize(localVarResponse, typeof(List>)); + var dictionary = list + .Where(item => item.ContainsKey("name") && item.ContainsKey("value")) + .ToDictionary(item => item["name"], item => item["value"]); return new ApiResponse>(localVarStatusCode, - localVarResponse.Headers.ToDictionary(x => x.Name, x => string.Join(",", x.Value)), - (Dictionary)this.Configuration.ApiClient.Deserialize(localVarResponse, typeof(Dictionary))); + localVarResponse.Headers.ToDictionary(x => x.Name, x => string.Join(",", x.Value)), + dictionary); } /// diff --git a/Conductor/Client/Authentication/TokenHandler.cs b/Conductor/Client/Authentication/TokenHandler.cs index f0579e11..e743e29a 100644 --- a/Conductor/Client/Authentication/TokenHandler.cs +++ b/Conductor/Client/Authentication/TokenHandler.cs @@ -62,7 +62,15 @@ private string GetTokenFromServer(OrkesAuthenticationSettings authenticationSett { try { - return tokenClient.GenerateToken(tokenRequest)._token; + var token = tokenClient.GenerateToken(tokenRequest); + return token._token; + } + catch (ApiException e) + { + if (e.ErrorCode == 405 || e.ErrorCode == 404) + { + throw new Exception($"Error while getting authentication token. Is the config BasePath correct? {tokenClient.Configuration.BasePath}"); + } } catch (Exception e) { diff --git a/Conductor/Client/Extensions/ApiExtensions.cs b/Conductor/Client/Extensions/ApiExtensions.cs index 7a2846f8..c0878a54 100644 --- a/Conductor/Client/Extensions/ApiExtensions.cs +++ b/Conductor/Client/Extensions/ApiExtensions.cs @@ -14,7 +14,6 @@ using Conductor.Executor; using Conductor.Client.Authentication; using System; -using System.Diagnostics; namespace Conductor.Client.Extensions { @@ -25,20 +24,25 @@ public class ApiExtensions private const string ENV_SECRET = "SECRET"; private const int REST_CLIENT_REQUEST_TIME_OUT = 30 * 1000; - public static Configuration Configuration { get; set; } - - static ApiExtensions() - { - Configuration = new Configuration(REST_CLIENT_REQUEST_TIME_OUT) + private static readonly Lazy _lazyConfiguration = + new Lazy(() => new Configuration(REST_CLIENT_REQUEST_TIME_OUT) { BasePath = GetEnvironmentVariable(ENV_ROOT_URI), AuthenticationSettings = new OrkesAuthenticationSettings( - GetEnvironmentVariable(ENV_KEY_ID), - GetEnvironmentVariable(ENV_SECRET) - ) - }; + GetEnvironmentVariable(ENV_KEY_ID), + GetEnvironmentVariable(ENV_SECRET) + ) + }); + + private static Configuration _customConfiguration; + + public static Configuration Configuration + { + get => _customConfiguration ?? _lazyConfiguration.Value; + set => _customConfiguration = value; } + public static WorkflowExecutor GetWorkflowExecutor() { return new WorkflowExecutor( @@ -66,9 +70,7 @@ public static string GetWorkflowExecutionURL(string workflowId) private static string GetEnvironmentVariable(string variable) { - string value = Environment.GetEnvironmentVariable(variable); - Debug.Assert(value != null); - return value; + return Environment.GetEnvironmentVariable(variable) ?? throw new InvalidOperationException($"Environment variable '{variable}' is not set."); } } } diff --git a/Conductor/Client/Models/WorkflowTask.cs b/Conductor/Client/Models/WorkflowTask.cs index d73bca7e..d90d3c1c 100644 --- a/Conductor/Client/Models/WorkflowTask.cs +++ b/Conductor/Client/Models/WorkflowTask.cs @@ -15,7 +15,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.IO; using System.Linq; using System.Runtime.Serialization; using System.Text; @@ -225,24 +224,8 @@ public enum WorkflowTaskTypeEnum /// workflowTaskType. public WorkflowTask(bool? asyncComplete = default(bool?), string caseExpression = default(string), string caseValueParam = default(string), Dictionary> decisionCases = default(Dictionary>), List defaultCase = default(List), List defaultExclusiveJoinTask = default(List), string description = default(string), string dynamicForkJoinTasksParam = default(string), string dynamicForkTasksInputParamName = default(string), string dynamicForkTasksParam = default(string), string dynamicTaskNameParam = default(string), string evaluatorType = default(string), string expression = default(string), List> forkTasks = default(List>), Dictionary inputParameters = default(Dictionary), List joinOn = default(List), string loopCondition = default(string), List loopOver = default(List), string name = default(string), bool? optional = default(bool?), bool? rateLimited = default(bool?), int? retryCount = default(int?), string scriptExpression = default(string), string sink = default(string), int? startDelay = default(int?), SubWorkflowParams subWorkflowParam = default(SubWorkflowParams), TaskDef taskDefinition = default(TaskDef), string taskReferenceName = default(string), string type = default(string), WorkflowTaskTypeEnum? workflowTaskType = default(WorkflowTaskTypeEnum?), Dictionary onStateChange = default(Dictionary)) { - // to ensure "name" is required (not null) - if (name == null) - { - throw new InvalidDataException("name is a required property for WorkflowTask and cannot be null"); - } - else - { - this.Name = name; - } - // to ensure "taskReferenceName" is required (not null) - if (taskReferenceName == null) - { - throw new InvalidDataException("taskReferenceName is a required property for WorkflowTask and cannot be null"); - } - else - { - this.TaskReferenceName = taskReferenceName; - } + this.TaskReferenceName = taskReferenceName; + this.Name = name; this.AsyncComplete = asyncComplete; this.CaseExpression = caseExpression; this.CaseValueParam = caseValueParam; diff --git a/Conductor/conductor-csharp.csproj b/Conductor/conductor-csharp.csproj index 1ad67ccb..38fa951b 100644 --- a/Conductor/conductor-csharp.csproj +++ b/Conductor/conductor-csharp.csproj @@ -16,7 +16,7 @@ - + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 36a20bc1..042cb420 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,9 +17,10 @@ ARG CONDUCTOR_SERVER_URL ENV KEY=${KEY} ENV SECRET=${SECRET} ENV CONDUCTOR_SERVER_URL=${CONDUCTOR_SERVER_URL} +COPY /csharp-examples /package/csharp-examples COPY /Tests /package/Tests WORKDIR /package/Tests -RUN dotnet test -l "console;verbosity=normal" +RUN dotnet test -p:DefineConstants=EXCLUDE_EXAMPLE_WORKERS -l "console;verbosity=normal" FROM build as pack_release ARG SDK_VERSION diff --git a/Tests/Worker/WorkerTests.cs b/Tests/Worker/WorkerTests.cs index 64f41594..3ad706b3 100644 --- a/Tests/Worker/WorkerTests.cs +++ b/Tests/Worker/WorkerTests.cs @@ -47,7 +47,7 @@ public async System.Threading.Tasks.Task TestWorkflowAsyncExecution() var workflow = GetConductorWorkflow(); ApiExtensions.GetWorkflowExecutor().RegisterWorkflow(workflow, true); var workflowIdList = await StartWorkflows(workflow, quantity: 15); - await ExecuteWorkflowTasks(workflowCompletionTimeout: TimeSpan.FromSeconds(20)); + await ExecuteWorkflowTasks(workflowCompletionTimeout: TimeSpan.FromSeconds(30)); await ValidateWorkflowCompletion(workflowIdList.ToArray()); } diff --git a/Tests/Worker/Workers.cs b/Tests/Worker/Workers.cs index 349d1ee2..8461737d 100644 --- a/Tests/Worker/Workers.cs +++ b/Tests/Worker/Workers.cs @@ -30,18 +30,18 @@ static FunctionalWorkers() _random = new Random(); } - // Polls for 5 task every 200ms - [WorkerTask("test-sdk-csharp-task", 5, "taskDomain", 200, "workerId")] + // Polls for 5 task every 100ms + [WorkerTask("test-sdk-csharp-task", 5, "taskDomain", 100, "simpleWorker")] public static TaskResult SimpleWorker(Conductor.Client.Models.Task task) { return task.Completed(); } - // Polls for 12 tasks every 420ms - [WorkerTask("test-sdk-csharp-task", 12, "taskDomain", 420, "workerId")] + // Polls for 5 tasks every 420ms + [WorkerTask("test-sdk-csharp-task", 5, "taskDomain", 420, "lazyWorker")] public TaskResult LazyWorker(Conductor.Client.Models.Task task) { - var timeSpan = System.TimeSpan.FromMilliseconds(_random.Next(128, 2048)); + var timeSpan = System.TimeSpan.FromMilliseconds(_random.Next(100, 900)); System.Threading.Tasks.Task.Delay(timeSpan).GetAwaiter().GetResult(); return task.Completed(); } diff --git a/Tests/conductor-csharp.test.csproj b/Tests/conductor-csharp.test.csproj index e9a37278..aabf6373 100644 --- a/Tests/conductor-csharp.test.csproj +++ b/Tests/conductor-csharp.test.csproj @@ -1,6 +1,6 @@ - netcoreapp6.0 + net6.0 @@ -8,7 +8,7 @@ - + diff --git a/Conductor/Examples/Copilot/Customer.cs b/csharp-examples/Examples/Copilot/Customer.cs similarity index 100% rename from Conductor/Examples/Copilot/Customer.cs rename to csharp-examples/Examples/Copilot/Customer.cs diff --git a/Conductor/Examples/Copilot/OpenAICopilot.cs b/csharp-examples/Examples/Copilot/OpenAICopilot.cs similarity index 100% rename from Conductor/Examples/Copilot/OpenAICopilot.cs rename to csharp-examples/Examples/Copilot/OpenAICopilot.cs diff --git a/Conductor/Examples/DynamicWorkflow.cs b/csharp-examples/Examples/DynamicWorkflow.cs similarity index 100% rename from Conductor/Examples/DynamicWorkflow.cs rename to csharp-examples/Examples/DynamicWorkflow.cs diff --git a/Conductor/Examples/ExampleConstant.cs b/csharp-examples/Examples/ExampleConstant.cs similarity index 100% rename from Conductor/Examples/ExampleConstant.cs rename to csharp-examples/Examples/ExampleConstant.cs diff --git a/Conductor/Examples/GreetingsMain.cs b/csharp-examples/Examples/GreetingsMain.cs similarity index 100% rename from Conductor/Examples/GreetingsMain.cs rename to csharp-examples/Examples/GreetingsMain.cs diff --git a/Conductor/Examples/Orkes/OpenAIChatGpt.cs b/csharp-examples/Examples/Orkes/OpenAIChatGpt.cs similarity index 100% rename from Conductor/Examples/Orkes/OpenAIChatGpt.cs rename to csharp-examples/Examples/Orkes/OpenAIChatGpt.cs diff --git a/Conductor/Examples/Orkes/OpenAIChatUserInput.cs b/csharp-examples/Examples/Orkes/OpenAIChatUserInput.cs similarity index 100% rename from Conductor/Examples/Orkes/OpenAIChatUserInput.cs rename to csharp-examples/Examples/Orkes/OpenAIChatUserInput.cs diff --git a/Conductor/Examples/Orkes/OpenAIFunctionExample.cs b/csharp-examples/Examples/Orkes/OpenAIFunctionExample.cs similarity index 100% rename from Conductor/Examples/Orkes/OpenAIFunctionExample.cs rename to csharp-examples/Examples/Orkes/OpenAIFunctionExample.cs diff --git a/Conductor/Examples/Orkes/OpenAIHelloworld.cs b/csharp-examples/Examples/Orkes/OpenAIHelloworld.cs similarity index 100% rename from Conductor/Examples/Orkes/OpenAIHelloworld.cs rename to csharp-examples/Examples/Orkes/OpenAIHelloworld.cs diff --git a/Conductor/Examples/Orkes/SyncUpdates.cs b/csharp-examples/Examples/Orkes/SyncUpdates.cs similarity index 100% rename from Conductor/Examples/Orkes/SyncUpdates.cs rename to csharp-examples/Examples/Orkes/SyncUpdates.cs diff --git a/Conductor/Examples/Orkes/TaskStatusChangeAudit.cs b/csharp-examples/Examples/Orkes/TaskStatusChangeAudit.cs similarity index 97% rename from Conductor/Examples/Orkes/TaskStatusChangeAudit.cs rename to csharp-examples/Examples/Orkes/TaskStatusChangeAudit.cs index 1f7156cd..5f0071c1 100644 --- a/Conductor/Examples/Orkes/TaskStatusChangeAudit.cs +++ b/csharp-examples/Examples/Orkes/TaskStatusChangeAudit.cs @@ -60,13 +60,13 @@ public void AuditLog(object workflowInput, string status, string name) } [WorkerTask(taskType: "simple_task_1", batchSize: 5, pollIntervalMs: 200, workerId: "workerId")] - public static string SimpleTask1(Task task) + public static string SimpleTask1(Conductor.Client.Models.Task task) { return "OK"; } [WorkerTask(taskType: "simple_task_2", batchSize: 5, pollIntervalMs: 200, workerId: "workerId")] - public static TaskResult SimpleTask2(Task task) + public static TaskResult SimpleTask2(Conductor.Client.Models.Task task) { return new TaskResult { Status = TaskResult.StatusEnum.FAILEDWITHTERMINALERROR }; } diff --git a/Conductor/Examples/Orkes/VectorDbHelloWorld.cs b/csharp-examples/Examples/Orkes/VectorDbHelloWorld.cs similarity index 100% rename from Conductor/Examples/Orkes/VectorDbHelloWorld.cs rename to csharp-examples/Examples/Orkes/VectorDbHelloWorld.cs diff --git a/Conductor/Examples/Orkes/WaitForWebhook.cs b/csharp-examples/Examples/Orkes/WaitForWebhook.cs similarity index 100% rename from Conductor/Examples/Orkes/WaitForWebhook.cs rename to csharp-examples/Examples/Orkes/WaitForWebhook.cs diff --git a/Conductor/Examples/Orkes/Workers/ChatWorkers.cs b/csharp-examples/Examples/Orkes/Workers/ChatWorkers.cs similarity index 100% rename from Conductor/Examples/Orkes/Workers/ChatWorkers.cs rename to csharp-examples/Examples/Orkes/Workers/ChatWorkers.cs diff --git a/Conductor/Examples/Orkes/Workers/ConversationCollector.cs b/csharp-examples/Examples/Orkes/Workers/ConversationCollector.cs similarity index 100% rename from Conductor/Examples/Orkes/Workers/ConversationCollector.cs rename to csharp-examples/Examples/Orkes/Workers/ConversationCollector.cs diff --git a/Conductor/Examples/Orkes/Workers/UserDetails.cs b/csharp-examples/Examples/Orkes/Workers/UserDetails.cs similarity index 100% rename from Conductor/Examples/Orkes/Workers/UserDetails.cs rename to csharp-examples/Examples/Orkes/Workers/UserDetails.cs diff --git a/Conductor/Examples/Orkes/WorkflowRerun.cs b/csharp-examples/Examples/Orkes/WorkflowRerun.cs similarity index 100% rename from Conductor/Examples/Orkes/WorkflowRerun.cs rename to csharp-examples/Examples/Orkes/WorkflowRerun.cs diff --git a/Conductor/Examples/ShellWorker.cs b/csharp-examples/Examples/ShellWorker.cs similarity index 100% rename from Conductor/Examples/ShellWorker.cs rename to csharp-examples/Examples/ShellWorker.cs diff --git a/Conductor/Examples/TaskConfigure.cs b/csharp-examples/Examples/TaskConfigure.cs similarity index 100% rename from Conductor/Examples/TaskConfigure.cs rename to csharp-examples/Examples/TaskConfigure.cs diff --git a/Conductor/Examples/TaskWorkers.cs b/csharp-examples/Examples/TaskWorkers.cs similarity index 100% rename from Conductor/Examples/TaskWorkers.cs rename to csharp-examples/Examples/TaskWorkers.cs diff --git a/Conductor/Examples/Workers/DynamicWorker.cs b/csharp-examples/Examples/Workers/DynamicWorker.cs similarity index 100% rename from Conductor/Examples/Workers/DynamicWorker.cs rename to csharp-examples/Examples/Workers/DynamicWorker.cs diff --git a/Conductor/Examples/Workers/GreetingsWorkflow.cs b/csharp-examples/Examples/Workers/GreetingsWorkflow.cs similarity index 100% rename from Conductor/Examples/Workers/GreetingsWorkflow.cs rename to csharp-examples/Examples/Workers/GreetingsWorkflow.cs diff --git a/csharp-examples/TestWorker.cs b/csharp-examples/TestWorker.cs index 2fc6b4b1..a1ce28e0 100644 --- a/csharp-examples/TestWorker.cs +++ b/csharp-examples/TestWorker.cs @@ -18,11 +18,19 @@ namespace csharp.examples; -public class TestWorker(string taskType) : IWorkflowTask +public class TestWorker : IWorkflowTask { + private readonly Random rnd = new(); - public string TaskType { get; } = taskType; + private readonly string taskType; + + public TestWorker(string taskType) + { + this.taskType = taskType; + } + + public string TaskType => taskType; public WorkflowTaskExecutorConfiguration WorkerSettings { get; } = new WorkflowTaskExecutorConfiguration() { BatchSize = 20 diff --git a/Conductor/Examples/Utils/ReRunWorkflow.json b/csharp-examples/Utils/ReRunWorkflow.json similarity index 100% rename from Conductor/Examples/Utils/ReRunWorkflow.json rename to csharp-examples/Utils/ReRunWorkflow.json diff --git a/Conductor/Examples/Utils/WorkerUtil.cs b/csharp-examples/Utils/WorkerUtil.cs similarity index 93% rename from Conductor/Examples/Utils/WorkerUtil.cs rename to csharp-examples/Utils/WorkerUtil.cs index 00bfe50e..1348f512 100644 --- a/Conductor/Examples/Utils/WorkerUtil.cs +++ b/csharp-examples/Utils/WorkerUtil.cs @@ -12,9 +12,6 @@ */ using Conductor.Client.Extensions; using Conductor.Client.Interfaces; -using System; -using System.Threading; -using System.Threading.Tasks; namespace Conductor.Examples.Utils { @@ -32,7 +29,7 @@ public static async Task StartBackGroundTask(ManualResetEvent waitHandle, { var host = WorkflowTaskHost.CreateWorkerHost(Microsoft.Extensions.Logging.LogLevel.Information); await host.StartAsync(); - Thread.Sleep(20000); + Thread.Sleep(40000); waitHandle.Set(); await host.StopAsync(); return true; diff --git a/csharp-examples/csharp-examples.csproj b/csharp-examples/csharp-examples.csproj index 71d71348..0b28ab8a 100644 --- a/csharp-examples/csharp-examples.csproj +++ b/csharp-examples/csharp-examples.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net6.0 csharp_examples enable enable @@ -10,11 +10,16 @@ - + - + + + + +