diff --git a/Client.IntegrationTests/Client.IntegrationTests.csproj b/Client.IntegrationTests/Client.IntegrationTests.csproj
index a7f54abf..e16f6401 100644
--- a/Client.IntegrationTests/Client.IntegrationTests.csproj
+++ b/Client.IntegrationTests/Client.IntegrationTests.csproj
@@ -29,6 +29,9 @@
PreserveNewest
+
+ PreserveNewest
+
diff --git a/Client.IntegrationTests/EvaluateDecisionTest.cs b/Client.IntegrationTests/EvaluateDecisionTest.cs
new file mode 100644
index 00000000..578af3b5
--- /dev/null
+++ b/Client.IntegrationTests/EvaluateDecisionTest.cs
@@ -0,0 +1,69 @@
+//
+// Copyright (c) 2021 camunda services GmbH (info@camunda.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using NUnit.Framework;
+using Zeebe.Client;
+
+namespace Client.IntegrationTests;
+
+[TestFixture]
+public class EvaluateDecisionTest
+{
+ private static readonly string DecisionPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", "dinnerDecisions.dmn");
+ private static readonly string DevisionEvaluationVariables = "{\"season\":\"Fall\", \"guestCount\":12}";
+
+ private readonly ZeebeIntegrationTestHelper testHelper = ZeebeIntegrationTestHelper.Latest();
+ private IZeebeClient zeebeClient;
+
+ [OneTimeSetUp]
+ public async Task Setup()
+ {
+ zeebeClient = await testHelper.SetupIntegrationTest();
+ }
+
+ [OneTimeTearDown]
+ public async Task Stop()
+ {
+ await testHelper.TearDownIntegrationTest();
+ }
+
+ [Test]
+ public async Task ShouldEvaluateDecision()
+ {
+ // given
+ var deployResponse = await zeebeClient.NewDeployCommand()
+ .AddResourceFile(DecisionPath)
+ .Send();
+ var decisionKey = deployResponse.Decisions[0].DecisionKey;
+
+ // when
+ var evaluateDecisionResponse = await zeebeClient
+ .NewEvaluateDecisionCommand()
+ .DecisionKey(decisionKey)
+ .Variables(DevisionEvaluationVariables)
+ .Send();
+
+ // then
+ Assert.AreEqual(evaluateDecisionResponse.DecisionVersion, 1);
+ Assert.AreEqual(decisionKey, evaluateDecisionResponse.DecisionKey);
+ Assert.AreEqual("dish", evaluateDecisionResponse.DecisionId);
+ Assert.Greater(evaluateDecisionResponse.DecisionKey, 1);
+ // right now it seems the DMN engine returns an double quated string
+ Assert.AreEqual("\"Stew\"", evaluateDecisionResponse.DecisionOutput);
+ }
+}
\ No newline at end of file
diff --git a/Client.IntegrationTests/Resources/dinnerDecisions.dmn b/Client.IntegrationTests/Resources/dinnerDecisions.dmn
new file mode 100644
index 00000000..e360d180
--- /dev/null
+++ b/Client.IntegrationTests/Resources/dinnerDecisions.dmn
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+ season
+
+
+
+
+ guestCount
+
+
+
+
+
+
+ "Fall"
+
+
+ <= 8
+
+
+ "Spareribs"
+
+
+
+
+ "Winter"
+
+
+ <= 8
+
+
+ "Roastbeef"
+
+
+
+
+ "Spring"
+
+
+ <= 4
+
+
+ "Dry Aged Gourmet Steak"
+
+
+
+ Save money
+
+ "Spring"
+
+
+ [5..8]
+
+
+ "Steak"
+
+
+
+ Less effort
+
+ "Fall","Winter","Spring"
+
+
+ > 8
+
+
+ "Stew"
+
+
+
+ Hey, why not?
+
+ "Summer"
+
+
+
+
+
+ "Light Salad and nice Steak"
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Client.UnitTests/EvaluateDecisionTest.cs b/Client.UnitTests/EvaluateDecisionTest.cs
new file mode 100644
index 00000000..2e46f17d
--- /dev/null
+++ b/Client.UnitTests/EvaluateDecisionTest.cs
@@ -0,0 +1,260 @@
+using System;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using GatewayProtocol;
+using Grpc.Core;
+using NUnit.Framework;
+
+namespace Zeebe.Client
+{
+ [TestFixture]
+ public class EvaluateDecisionTest : BaseZeebeTest
+ {
+ [Test]
+ public async Task ShouldSendRequestAsExpected()
+ {
+ // given
+ var expectedRequest = new EvaluateDecisionRequest
+ {
+ DecisionId = "decision",
+ };
+
+ // when
+ await ZeebeClient.NewEvaluateDecisionCommand()
+ .DecisionId("decision")
+ .Send();
+
+ // then
+ var request = TestService.Requests[typeof(EvaluateDecisionRequest)][0];
+ Assert.AreEqual(expectedRequest, request);
+ }
+
+ [Test]
+ public void ShouldTimeoutRequest()
+ {
+ // given
+
+ // when
+ var task = ZeebeClient.NewEvaluateDecisionCommand()
+ .DecisionId("decision")
+ .Send(TimeSpan.Zero);
+ var aggregateException = Assert.Throws(() => task.Wait());
+ var rpcException = (RpcException)aggregateException.InnerExceptions[0];
+
+ // then
+ Assert.AreEqual(Grpc.Core.StatusCode.DeadlineExceeded, rpcException.Status.StatusCode);
+ }
+
+ [Test]
+ public void ShouldCancelRequest()
+ {
+ // given
+
+ // when
+ var task = ZeebeClient.NewEvaluateDecisionCommand()
+ .DecisionId("decision")
+ .Send(new CancellationTokenSource(TimeSpan.Zero).Token);
+ var aggregateException = Assert.Throws(() => task.Wait());
+ var rpcException = (RpcException)aggregateException.InnerExceptions[0];
+
+ // then
+ Assert.AreEqual(Grpc.Core.StatusCode.Cancelled, rpcException.Status.StatusCode);
+ }
+
+ [Test]
+ public async Task ShouldSendRequestWithDecisionKeyExpected()
+ {
+ // given
+ var expectedRequest = new EvaluateDecisionRequest
+ {
+ DecisionKey = 12
+ };
+
+ // when
+ await ZeebeClient.NewEvaluateDecisionCommand()
+ .DecisionKey(12)
+ .Send();
+
+ // then
+ var request = TestService.Requests[typeof(EvaluateDecisionRequest)][0];
+ Assert.AreEqual(expectedRequest, request);
+ }
+
+ [Test]
+ public async Task ShouldSendRequestWithVariablesAsExpected()
+ {
+ // given
+ var expectedRequest = new EvaluateDecisionRequest
+ {
+ DecisionKey = 12,
+ Variables = "{\"foo\":1}"
+ };
+
+ // when
+ await ZeebeClient.NewEvaluateDecisionCommand()
+ .DecisionKey(12)
+ .Variables("{\"foo\":1}")
+ .Send();
+
+ // then
+ var request = TestService.Requests[typeof(EvaluateDecisionRequest)][0];
+ Assert.AreEqual(expectedRequest, request);
+ }
+
+ [Test]
+ public async Task ShouldSendRequestWithVariablesAndDecisionIdAsExpected()
+ {
+ // given
+ var expectedRequest = new EvaluateDecisionRequest
+ {
+ DecisionId = "decision",
+ Variables = "{\"foo\":1}"
+ };
+
+ // when
+ await ZeebeClient.NewEvaluateDecisionCommand()
+ .DecisionId("decision")
+ .Variables("{\"foo\":1}")
+ .Send();
+
+ // then
+ var request = TestService.Requests[typeof(EvaluateDecisionRequest)][0];
+ Assert.AreEqual(expectedRequest, request);
+ }
+
+ [Test]
+ public async Task ShouldReceiveResponseAsExpected()
+ {
+ // given
+ var expectedResponse = new EvaluateDecisionResponse
+ {
+ DecisionId = "decision",
+ DecisionKey = 123,
+ DecisionName = "decision-123",
+ DecisionOutput = "1",
+ DecisionVersion = 2,
+ FailureMessage = "",
+ FailedDecisionId = "",
+ DecisionRequirementsId = "12",
+ DecisionRequirementsKey = 1234,
+ EvaluatedDecisions =
+ {
+ new EvaluatedDecision
+ {
+ DecisionId = "decision",
+ DecisionKey = 123,
+ DecisionName = "decision-123",
+ DecisionOutput = "1",
+ DecisionVersion = 2,
+ DecisionType = "noop",
+ EvaluatedInputs =
+ {
+ new EvaluatedDecisionInput
+ {
+ InputId = "moep",
+ InputName = "moepmoep",
+ InputValue = "boom"
+ },
+ new EvaluatedDecisionInput
+ {
+ InputId = "moeb",
+ InputName = "moebmoeb",
+ InputValue = "boom"
+ }
+ },
+ MatchedRules =
+ {
+ new MatchedDecisionRule
+ {
+ EvaluatedOutputs =
+ {
+ new EvaluatedDecisionOutput
+ {
+ OutputId = "outputId",
+ OutputName = "output",
+ OutputValue = "val"
+ },
+ new EvaluatedDecisionOutput
+ {
+ OutputId = "outputId2",
+ OutputName = "output2",
+ OutputValue = "val2"
+ }
+ },
+ RuleId = "ruleid",
+ RuleIndex = 1
+ }
+ }
+ }
+ },
+ };
+
+ TestService.AddRequestHandler(typeof(EvaluateDecisionRequest), request => expectedResponse);
+
+ // when
+ var evaluatedDecisionResponse = await ZeebeClient.NewEvaluateDecisionCommand()
+ .DecisionId("decision")
+ .Send();
+
+ // then
+ Assert.AreEqual("decision", evaluatedDecisionResponse.DecisionId);
+ Assert.AreEqual(123, evaluatedDecisionResponse.DecisionKey);
+ Assert.AreEqual("decision-123", evaluatedDecisionResponse.DecisionName);
+ Assert.AreEqual("1", evaluatedDecisionResponse.DecisionOutput);
+ Assert.AreEqual(2, evaluatedDecisionResponse.DecisionVersion);
+ Assert.AreEqual("", evaluatedDecisionResponse.FailureMessage);
+ Assert.AreEqual("", evaluatedDecisionResponse.FailedDecisionId);
+ Assert.AreEqual("12", evaluatedDecisionResponse.DecisionRequirementsId);
+ Assert.AreEqual(1234, evaluatedDecisionResponse.DecisionRequirementsKey);
+
+ var evaluatedDecisions = evaluatedDecisionResponse.EvaluatedDecisions;
+ Assert.AreEqual(1, evaluatedDecisions.Count);
+
+ var decision = evaluatedDecisions[0];
+ Assert.AreEqual("decision", decision.DecisionId);
+ Assert.AreEqual(123, decision.DecisionKey);
+ Assert.AreEqual("decision-123", decision.DecisionName);
+ Assert.AreEqual("1", decision.DecisionOutput);
+ Assert.AreEqual(2, decision.DecisionVersion);
+ Assert.AreEqual("noop", decision.DecisionType);
+
+ var decisionEvaluatedInputs = decision.EvaluatedInputs;
+ Assert.AreEqual(2, decisionEvaluatedInputs.Count);
+
+ var decisionEvaluatedInput = decisionEvaluatedInputs[0];
+ Assert.AreEqual("moep", decisionEvaluatedInput.InputId);
+ Assert.AreEqual("moepmoep", decisionEvaluatedInput.InputName);
+ Assert.AreEqual("boom", decisionEvaluatedInput.InputValue);
+
+ decisionEvaluatedInput = decisionEvaluatedInputs[1];
+ Assert.AreEqual("moeb", decisionEvaluatedInput.InputId);
+ Assert.AreEqual("moebmoeb", decisionEvaluatedInput.InputName);
+ Assert.AreEqual("boom", decisionEvaluatedInput.InputValue);
+
+
+ var decisionMatchedRules = decision.MatchedRules;
+ Assert.AreEqual(1, decisionMatchedRules.Count);
+ var decisionMatchedRule = decisionMatchedRules[0];
+
+ Assert.AreEqual("ruleid", decisionMatchedRule.RuleId);
+ Assert.AreEqual(1, decisionMatchedRule.RuleIndex);
+
+ var evaluatedDecisionOutputs = decisionMatchedRule.EvaluatedOutputs;
+ Assert.AreEqual(2, evaluatedDecisionOutputs.Count);
+
+ var evaluatedDecisionOutput = evaluatedDecisionOutputs[0];
+ Assert.AreEqual("outputId", evaluatedDecisionOutput.OutputId);
+ Assert.AreEqual("output", evaluatedDecisionOutput.OutputName);
+ Assert.AreEqual("val", evaluatedDecisionOutput.OutputValue);
+
+ evaluatedDecisionOutput = evaluatedDecisionOutputs[1];
+ Assert.AreEqual("outputId2", evaluatedDecisionOutput.OutputId);
+ Assert.AreEqual("output2", evaluatedDecisionOutput.OutputName);
+ Assert.AreEqual("val2", evaluatedDecisionOutput.OutputValue);
+ }
+ }
+}
+
+
+
diff --git a/Client.UnitTests/GatewayTestService.cs b/Client.UnitTests/GatewayTestService.cs
index 46d36b8a..936cf6a6 100644
--- a/Client.UnitTests/GatewayTestService.cs
+++ b/Client.UnitTests/GatewayTestService.cs
@@ -61,6 +61,7 @@ public GatewayTestService()
typedRequestHandler.Add(typeof(SetVariablesRequest), request => new SetVariablesResponse());
typedRequestHandler.Add(typeof(ResolveIncidentRequest), request => new ResolveIncidentResponse());
typedRequestHandler.Add(typeof(CreateProcessInstanceWithResultRequest), request => new CreateProcessInstanceWithResultResponse());
+ typedRequestHandler.Add(typeof(EvaluateDecisionRequest), request => new EvaluateDecisionResponse());
foreach (var pair in typedRequestHandler)
{
@@ -144,6 +145,11 @@ public override Task DeployResource(DeployResourceReques
return Task.FromResult((DeployResourceResponse)HandleRequest(request, context));
}
+ public override Task EvaluateDecision(EvaluateDecisionRequest request, ServerCallContext context)
+ {
+ return Task.FromResult((EvaluateDecisionResponse)HandleRequest(request, context));
+ }
+
public delegate void ConsumeMetadata(Metadata metadata);
public void ConsumeRequestHeaders(ConsumeMetadata consumer)
diff --git a/Client.UnitTests/TestDataProvider.cs b/Client.UnitTests/TestDataProvider.cs
index fa59b14a..808587cd 100644
--- a/Client.UnitTests/TestDataProvider.cs
+++ b/Client.UnitTests/TestDataProvider.cs
@@ -6,14 +6,6 @@
using NUnit.Framework;
using Zeebe.Client.Api.Commands;
using Zeebe.Client.Api.Responses;
-using Zeebe.Client.Impl.Responses;
-using CancelProcessInstanceResponse = GatewayProtocol.CancelProcessInstanceResponse;
-using CompleteJobResponse = GatewayProtocol.CompleteJobResponse;
-using FailJobResponse = GatewayProtocol.FailJobResponse;
-using PublishMessageResponse = GatewayProtocol.PublishMessageResponse;
-using ResolveIncidentResponse = GatewayProtocol.ResolveIncidentResponse;
-using SetVariablesResponse = GatewayProtocol.SetVariablesResponse;
-using ThrowErrorResponse = GatewayProtocol.ThrowErrorResponse;
namespace Zeebe.Client
{
@@ -140,9 +132,17 @@ public static IEnumerable Provider()
}
}
},
- new GatewayProtocol.DeployResourceResponse(),
+ new DeployResourceResponse(),
(RequestCreator)
(zeebeClient => zeebeClient.NewDeployCommand().AddResourceFile(DemoProcessPath)));
+ yield return new TestCaseData(
+ new EvaluateDecisionRequest
+ {
+ DecisionId = "decision"
+ },
+ new EvaluateDecisionResponse(),
+ (RequestCreator)
+ (zeebeClient => zeebeClient.NewEvaluateDecisionCommand().DecisionId("decision")));
}
}
}
\ No newline at end of file
diff --git a/Client/Api/Commands/IEvaluateDecisionCommandStep1.cs b/Client/Api/Commands/IEvaluateDecisionCommandStep1.cs
new file mode 100644
index 00000000..a7e24433
--- /dev/null
+++ b/Client/Api/Commands/IEvaluateDecisionCommandStep1.cs
@@ -0,0 +1,54 @@
+//
+// Copyright (c) 2021 camunda services GmbH (info@camunda.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using GatewayProtocol;
+using Zeebe.Client.Api.Responses;
+
+namespace Zeebe.Client.Api.Commands;
+
+public interface IEvaluateDecisionCommandStep1
+{
+ ///
+ /// Set the id of the decision to evaluate. This is the static id of the decision in the DMN XML
+ /// (i.e. "<decision id='my-decision'>").
+ ///
+ ///
+ /// The DMN id of the decision.
+ /// the builder for this command. Call to complete the command and send
+ /// it to the broker.
+ IEvaluateDecisionCommandStep2 DecisionId(string decisionId);
+
+ ///
+ /// Set the key of the decision to evaluate. The key is assigned by the broker while deploying the
+ /// decision. It can be picked from the deployment.
+ ///
+ ///
+ /// The key of the decision.
+ /// the builder for this command. Call to complete the command and send
+ /// it to the broker.
+ IEvaluateDecisionCommandStep2 DecisionKey(long decisionKey);
+
+ public interface IEvaluateDecisionCommandStep2 : IFinalCommandWithRetryStep
+ {
+ ///
+ /// Set the variables for the decision evaluation.
+ ///
+ ///
+ /// The variables JSON document as String.
+ /// the builder for this command. Call to complete the command and send
+ /// it to the broker.
+ IEvaluateDecisionCommandStep2 Variables(string variables);
+ }
+}
\ No newline at end of file
diff --git a/Client/Api/Responses/IEvaluateDecisionResponse.cs b/Client/Api/Responses/IEvaluateDecisionResponse.cs
new file mode 100644
index 00000000..7f58c499
--- /dev/null
+++ b/Client/Api/Responses/IEvaluateDecisionResponse.cs
@@ -0,0 +1,62 @@
+using System.Collections.Generic;
+
+namespace Zeebe.Client.Api.Responses
+{
+ ///
+ /// Response for evaluating a decision on the broker.
+ ///
+ public interface IEvaluateDecisionResponse
+ {
+ ///
+ /// the decision ID, as parsed during deployment; together with the versions forms a unique
+ /// identifier for a specific decision
+ ///
+ string DecisionId { get; }
+
+ ///
+ /// the assigned decision version
+ ///
+ int DecisionVersion { get; }
+
+ ///
+ /// the assigned decision key, which acts as a unique identifier for this decision
+ ///
+ long DecisionKey { get; }
+
+ ///
+ /// the name of the decision, as parsed during deployment
+ ///
+ string DecisionName { get; }
+
+ ///
+ /// the ID of the decision requirements graph that this decision is part of, as parsed
+ /// during deployment
+ ///
+ string DecisionRequirementsId { get; }
+
+ ///
+ /// the assigned key of the decision requirements graph that this decision is part of
+ ///
+ long DecisionRequirementsKey { get; }
+
+ ///
+ /// the output of the evaluated decision
+ ///
+ string DecisionOutput { get; }
+
+ ///
+ /// a list of decisions that were evaluated within the requested decision evaluation
+ ///
+ IList EvaluatedDecisions { get; }
+
+ ///
+ /// a string indicating the ID of the decision which failed during evaluation
+ ///
+ string FailedDecisionId { get; }
+
+ ///
+ /// a message describing why the decision which was evaluated failed
+ ///
+ string FailureMessage { get; }
+ }
+}
\ No newline at end of file
diff --git a/Client/Api/Responses/IEvaluatedDecision.cs b/Client/Api/Responses/IEvaluatedDecision.cs
new file mode 100644
index 00000000..98b7fea9
--- /dev/null
+++ b/Client/Api/Responses/IEvaluatedDecision.cs
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2021 camunda services GmbH (info@camunda.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Collections.Generic;
+using GatewayProtocol;
+
+namespace Zeebe.Client.Api.Responses;
+
+public interface IEvaluatedDecision
+{
+ ///
+ /// the decision ID, as parsed during deployment; together with the versions forms a unique
+ /// identifier for a specific decision
+ ///
+ string DecisionId { get; }
+
+ ///
+ /// the assigned decision version
+ ///
+ int DecisionVersion { get; }
+
+ ///
+ /// the assigned decision key, which acts as a unique identifier for this decision
+ ///
+ long DecisionKey { get; }
+
+ ///
+ /// the name of the decision, as parsed during deployment
+ ///
+ string DecisionName { get; }
+
+ ///
+ /// the type of the evaluated decision
+ ///
+ string DecisionType { get; }
+
+ ///
+ /// the output of the evaluated decision
+ ///
+ string DecisionOutput { get; }
+
+ ///
+ /// the decision inputs that were evaluated within this decision evaluation
+ ///
+ IList EvaluatedInputs { get; }
+
+ ///
+ /// the decision rules that matched within this decision evaluation
+ ///
+ IList MatchedRules { get; }
+}
\ No newline at end of file
diff --git a/Client/Api/Responses/IEvaluatedDecisionInput.cs b/Client/Api/Responses/IEvaluatedDecisionInput.cs
new file mode 100644
index 00000000..4a85509b
--- /dev/null
+++ b/Client/Api/Responses/IEvaluatedDecisionInput.cs
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2021 camunda services GmbH (info@camunda.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Zeebe.Client.Api.Responses;
+
+public interface IEvaluatedDecisionInput
+{
+ ///
+ /// the id of the evaluated decision input
+ ///
+ string InputId { get; }
+
+ ///
+ /// the name of the evaluated decision input
+ ///
+ string InputName { get; }
+
+ ///
+ /// the value of the evaluated decision input
+ ///
+ string InputValue { get; }
+}
\ No newline at end of file
diff --git a/Client/Api/Responses/IEvaluatedDecisionOutput.cs b/Client/Api/Responses/IEvaluatedDecisionOutput.cs
new file mode 100644
index 00000000..874d00e8
--- /dev/null
+++ b/Client/Api/Responses/IEvaluatedDecisionOutput.cs
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2021 camunda services GmbH (info@camunda.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Zeebe.Client.Api.Responses;
+
+public interface IEvaluatedDecisionOutput
+{
+ ///
+ /// the id of the evaluated decision output
+ ///
+ string OutputId { get; }
+
+ ///
+ /// the name of the evaluated decision output
+ ///
+ string OutputName { get; }
+
+ ///
+ /// the value of the evaluated decision output
+ ///
+ string OutputValue { get; }
+}
\ No newline at end of file
diff --git a/Client/Api/Responses/IMatchedDecisionRule.cs b/Client/Api/Responses/IMatchedDecisionRule.cs
new file mode 100644
index 00000000..d8cc7617
--- /dev/null
+++ b/Client/Api/Responses/IMatchedDecisionRule.cs
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2021 camunda services GmbH (info@camunda.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Collections.Generic;
+using GatewayProtocol;
+
+namespace Zeebe.Client.Api.Responses;
+
+public interface IMatchedDecisionRule
+{
+ ///
+ /// the id of the matched rule
+ ///
+ string RuleId { get; }
+
+ ///
+ /// the index of the matched rule
+ ///
+ int RuleIndex { get; }
+
+ ///
+ /// the evaluated decision outputs
+ ///
+ IList EvaluatedOutputs { get; }
+}
\ No newline at end of file
diff --git a/Client/Client.csproj b/Client/Client.csproj
index 78f2b406..c6191d7b 100644
--- a/Client/Client.csproj
+++ b/Client/Client.csproj
@@ -150,7 +150,7 @@ This release is based on the Zeebe 8.1.X release (https://github.com/zeebe-io/ze
True
-
+
diff --git a/Client/IZeebeClient.cs b/Client/IZeebeClient.cs
index 51e7c877..9ef5d022 100644
--- a/Client/IZeebeClient.cs
+++ b/Client/IZeebeClient.cs
@@ -136,6 +136,24 @@ public interface IZeebeClient : IJobClient, IDisposable
/// a builder for the deploy command
///
IDeployResourceCommandStep1 NewDeployCommand();
+
+ ///
+ /// Command to evaluate a decision.
+ ///
+ ///
+ ///
+ ///
+ /// zeebeClient
+ /// .NewEvaluateDecisionCommand()
+ /// .DecisionKey("my-decision")
+ /// .Variables(json)
+ /// .Send();
+ ///
+ ///
+ ///
+ /// a builder for the deploy command
+ ///
+ IEvaluateDecisionCommandStep1 NewEvaluateDecisionCommand();
///
/// Command to create/start a new instance of a process.
diff --git a/Client/Impl/Commands/EvaluateDecisionCommand.cs b/Client/Impl/Commands/EvaluateDecisionCommand.cs
new file mode 100644
index 00000000..332964db
--- /dev/null
+++ b/Client/Impl/Commands/EvaluateDecisionCommand.cs
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2021 camunda services GmbH (info@camunda.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using GatewayProtocol;
+using Zeebe.Client.Api.Commands;
+using Zeebe.Client.Api.Misc;
+using Zeebe.Client.Api.Responses;
+using Zeebe.Client.Impl.Responses;
+
+namespace Zeebe.Client.Impl.Commands;
+
+public class EvaluateDecisionCommand : IEvaluateDecisionCommandStep1, IEvaluateDecisionCommandStep1.IEvaluateDecisionCommandStep2
+{
+ private readonly EvaluateDecisionRequest request;
+ private readonly Gateway.GatewayClient gatewayClient;
+ private readonly IAsyncRetryStrategy asyncRetryStrategy;
+
+ public EvaluateDecisionCommand(Gateway.GatewayClient client, IAsyncRetryStrategy asyncRetryStrategy)
+ {
+ gatewayClient = client;
+ request = new EvaluateDecisionRequest();
+ this.asyncRetryStrategy = asyncRetryStrategy;
+ }
+
+ public IEvaluateDecisionCommandStep1.IEvaluateDecisionCommandStep2 DecisionId(string decisionId)
+ {
+ request.DecisionId = decisionId;
+ return this;
+ }
+
+ public IEvaluateDecisionCommandStep1.IEvaluateDecisionCommandStep2 DecisionKey(long decisionKey)
+ {
+ request.DecisionKey = decisionKey;
+ return this;
+ }
+
+ public async Task Send(TimeSpan? timeout = null, CancellationToken token = default)
+ {
+ var asyncReply = gatewayClient.EvaluateDecisionAsync(request, deadline: timeout?.FromUtcNow(), cancellationToken: token);
+ var response = await asyncReply.ResponseAsync;
+ return new EvaluatedDecisionResponse(response);
+ }
+
+ public async Task Send(CancellationToken cancellationToken)
+ {
+ return await Send(token: cancellationToken);
+ }
+
+ public async Task SendWithRetry(TimeSpan? timespan = null, CancellationToken token = default)
+ {
+ return await asyncRetryStrategy.DoWithRetry(() => Send(timespan, token));
+ }
+
+ public IEvaluateDecisionCommandStep1.IEvaluateDecisionCommandStep2 Variables(string variables)
+ {
+ request.Variables = variables;
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/Client/Impl/Responses/EvaluatedDecision.cs b/Client/Impl/Responses/EvaluatedDecision.cs
new file mode 100644
index 00000000..6c42e7aa
--- /dev/null
+++ b/Client/Impl/Responses/EvaluatedDecision.cs
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2021 camunda services GmbH (info@camunda.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Collections.Generic;
+using Zeebe.Client.Api.Responses;
+
+namespace Zeebe.Client.Impl.Responses;
+
+public class EvaluatedDecision : IEvaluatedDecision
+{
+ public string DecisionId { get; }
+ public int DecisionVersion { get; }
+ public long DecisionKey { get; }
+ public string DecisionName { get; }
+ public string DecisionType { get; }
+ public string DecisionOutput { get; }
+ public IList EvaluatedInputs { get; }
+ public IList MatchedRules { get; }
+
+ public EvaluatedDecision(GatewayProtocol.EvaluatedDecision evaluatedDecision)
+ {
+ DecisionId = evaluatedDecision.DecisionId;
+ DecisionVersion = evaluatedDecision.DecisionVersion;
+ DecisionKey = evaluatedDecision.DecisionKey;
+ DecisionName = evaluatedDecision.DecisionName;
+ DecisionType = evaluatedDecision.DecisionType;
+ DecisionOutput = evaluatedDecision.DecisionOutput;
+
+ EvaluatedInputs = new List();
+ foreach (var input in evaluatedDecision.EvaluatedInputs)
+ {
+ EvaluatedInputs.Add(new EvaluatedDecisionInput(input));
+ }
+
+ MatchedRules = new List();
+ foreach (var matchedRule in evaluatedDecision.MatchedRules)
+ {
+ MatchedRules.Add(new MatchedDecisionRule(matchedRule));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Client/Impl/Responses/EvaluatedDecisionInput.cs b/Client/Impl/Responses/EvaluatedDecisionInput.cs
new file mode 100644
index 00000000..a68cc0ff
--- /dev/null
+++ b/Client/Impl/Responses/EvaluatedDecisionInput.cs
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2021 camunda services GmbH (info@camunda.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using Zeebe.Client.Api.Responses;
+
+namespace Zeebe.Client.Impl.Responses;
+
+public class EvaluatedDecisionInput : IEvaluatedDecisionInput
+{
+ public string InputId { get; }
+ public string InputName { get; }
+ public string InputValue { get; }
+
+ public EvaluatedDecisionInput(GatewayProtocol.EvaluatedDecisionInput evaluatedDecisionInput)
+ {
+ InputId = evaluatedDecisionInput.InputId;
+ InputName = evaluatedDecisionInput.InputName;
+ InputValue = evaluatedDecisionInput.InputValue;
+ }
+}
\ No newline at end of file
diff --git a/Client/Impl/Responses/EvaluatedDecisionOutput.cs b/Client/Impl/Responses/EvaluatedDecisionOutput.cs
new file mode 100644
index 00000000..bc6a533a
--- /dev/null
+++ b/Client/Impl/Responses/EvaluatedDecisionOutput.cs
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2021 camunda services GmbH (info@camunda.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using Zeebe.Client.Api.Responses;
+
+namespace Zeebe.Client.Impl.Responses;
+
+public class EvaluatedDecisionOutput : IEvaluatedDecisionOutput
+{
+ public string OutputId { get; }
+ public string OutputName { get; }
+ public string OutputValue { get; }
+
+ public EvaluatedDecisionOutput(GatewayProtocol.EvaluatedDecisionOutput evaluatedDecisionOutput)
+ {
+ OutputId = evaluatedDecisionOutput.OutputId;
+ OutputName = evaluatedDecisionOutput.OutputName;
+ OutputValue = evaluatedDecisionOutput.OutputValue;
+ }
+}
\ No newline at end of file
diff --git a/Client/Impl/Responses/EvaluatedDecisionResponse.cs b/Client/Impl/Responses/EvaluatedDecisionResponse.cs
new file mode 100644
index 00000000..c0c6c4f9
--- /dev/null
+++ b/Client/Impl/Responses/EvaluatedDecisionResponse.cs
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2021 camunda services GmbH (info@camunda.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Collections.Generic;
+using Zeebe.Client.Api.Responses;
+
+namespace Zeebe.Client.Impl.Responses;
+
+public class EvaluatedDecisionResponse : IEvaluateDecisionResponse
+{
+ public string DecisionId { get; }
+ public int DecisionVersion { get; }
+ public long DecisionKey { get; }
+ public string DecisionName { get; }
+ public string DecisionRequirementsId { get; }
+ public long DecisionRequirementsKey { get; }
+ public string DecisionOutput { get; }
+ public IList EvaluatedDecisions { get; }
+ public string FailedDecisionId { get; }
+ public string FailureMessage { get; }
+
+ public EvaluatedDecisionResponse(GatewayProtocol.EvaluateDecisionResponse response)
+ {
+ DecisionId = response.DecisionId;
+ DecisionVersion = response.DecisionVersion;
+ DecisionKey = response.DecisionKey;
+ DecisionName = response.DecisionName;
+ DecisionRequirementsId = response.DecisionRequirementsId;
+ DecisionRequirementsKey = response.DecisionRequirementsKey;
+ DecisionOutput = response.DecisionOutput;
+ this.EvaluatedDecisions = new List();
+ foreach (var decision in response.EvaluatedDecisions)
+ {
+ this.EvaluatedDecisions.Add(new EvaluatedDecision(decision));
+ }
+
+ FailedDecisionId = response.FailedDecisionId;
+ FailureMessage = response.FailureMessage;
+ }
+}
\ No newline at end of file
diff --git a/Client/Impl/Responses/MatchedDecisionRule.cs b/Client/Impl/Responses/MatchedDecisionRule.cs
new file mode 100644
index 00000000..534220d4
--- /dev/null
+++ b/Client/Impl/Responses/MatchedDecisionRule.cs
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2021 camunda services GmbH (info@camunda.com)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Collections.Generic;
+using Zeebe.Client.Api.Responses;
+
+namespace Zeebe.Client.Impl.Responses;
+
+public class MatchedDecisionRule : IMatchedDecisionRule
+{
+ public string RuleId { get; }
+ public int RuleIndex { get; }
+ public IList EvaluatedOutputs { get; }
+
+ public MatchedDecisionRule(GatewayProtocol.MatchedDecisionRule matchedDecisionRule)
+ {
+ RuleId = matchedDecisionRule.RuleId;
+ RuleIndex = matchedDecisionRule.RuleIndex;
+
+ EvaluatedOutputs = new List();
+ foreach (var evaluatedOutput in matchedDecisionRule.EvaluatedOutputs)
+ {
+ EvaluatedOutputs.Add(new EvaluatedDecisionOutput(evaluatedOutput));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Client/ZeebeClient.cs b/Client/ZeebeClient.cs
index a1568f69..c41398a1 100644
--- a/Client/ZeebeClient.cs
+++ b/Client/ZeebeClient.cs
@@ -142,6 +142,11 @@ public IDeployResourceCommandStep1 NewDeployCommand()
return new DeployResourceCommand(gatewayClient, asyncRetryStrategy);
}
+ public IEvaluateDecisionCommandStep1 NewEvaluateDecisionCommand()
+ {
+ return new EvaluateDecisionCommand(gatewayClient, asyncRetryStrategy);
+ }
+
public ICreateProcessInstanceCommandStep1 NewCreateProcessInstanceCommand()
{
return new CreateProcessInstanceCommand(gatewayClient, asyncRetryStrategy);