From 4a534db2f5ea027dda17e46f9d33e6f36630e374 Mon Sep 17 00:00:00 2001 From: Jacob Snarr Date: Wed, 4 Dec 2024 21:35:16 -0500 Subject: [PATCH] fix(server): Pass UserTask UserId and UserGroup details to WorkerContext (#1178) --- docs/docs/08-api.md | 2 +- schemas/littlehorse/user_tasks.proto | 4 +- sdk-go/lhproto/user_tasks.pb.go | 4 +- .../proto/UserTaskTriggerReference.java | 36 ++++---- .../UserTaskTriggerReferenceOrBuilder.java | 12 +-- sdk-js/src/proto/user_tasks.ts | 4 +- sdk-python/littlehorse/model/__init__.py | 2 +- .../UserTaskTriggerReferenceModel.java | 22 +++-- server/src/test/java/e2e/UserTaskTest.java | 87 +++++++++++++++++++ 9 files changed, 136 insertions(+), 37 deletions(-) diff --git a/docs/docs/08-api.md b/docs/docs/08-api.md index 8170029e3..506dcc229 100644 --- a/docs/docs/08-api.md +++ b/docs/docs/08-api.md @@ -3228,7 +3228,7 @@ SDK, which allows the Task Method to determine where the TaskRun comes from. | `node_run_id` | | [NodeRunId](#noderunid) | Is the NodeRun that the UserTaskRun belongs to. | | `user_task_event_number` | | int32 | Is the index in the `events` field of the UserTaskRun that the TaskRun corresponds to. | | `user_id` | optional| string | Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not asigned to a specific user_id. | -| `user_group` | optional| string | Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not asigned to a specific user_id. | +| `user_group` | optional| string | Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not asigned to a specific user_group. | diff --git a/schemas/littlehorse/user_tasks.proto b/schemas/littlehorse/user_tasks.proto index f414a538c..caf22d190 100644 --- a/schemas/littlehorse/user_tasks.proto +++ b/schemas/littlehorse/user_tasks.proto @@ -214,8 +214,8 @@ message UserTaskTriggerReference { // asigned to a specific user_id. optional string user_id = 3; - // Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not - // asigned to a specific user_id. + // Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not + // asigned to a specific user_group. optional string user_group = 4; } diff --git a/sdk-go/lhproto/user_tasks.pb.go b/sdk-go/lhproto/user_tasks.pb.go index 52e588a08..6fbe3af93 100644 --- a/sdk-go/lhproto/user_tasks.pb.go +++ b/sdk-go/lhproto/user_tasks.pb.go @@ -770,8 +770,8 @@ type UserTaskTriggerReference struct { // Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not // asigned to a specific user_id. UserId *string `protobuf:"bytes,3,opt,name=user_id,json=userId,proto3,oneof" json:"user_id,omitempty"` - // Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not - // asigned to a specific user_id. + // Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not + // asigned to a specific user_group. UserGroup *string `protobuf:"bytes,4,opt,name=user_group,json=userGroup,proto3,oneof" json:"user_group,omitempty"` } diff --git a/sdk-java/src/main/java/io/littlehorse/sdk/common/proto/UserTaskTriggerReference.java b/sdk-java/src/main/java/io/littlehorse/sdk/common/proto/UserTaskTriggerReference.java index d178ad079..78456a5fe 100644 --- a/sdk-java/src/main/java/io/littlehorse/sdk/common/proto/UserTaskTriggerReference.java +++ b/sdk-java/src/main/java/io/littlehorse/sdk/common/proto/UserTaskTriggerReference.java @@ -174,8 +174,8 @@ public java.lang.String getUserId() { private volatile java.lang.Object userGroup_ = ""; /** *
-   * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not
-   * asigned to a specific user_id.
+   * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not
+   * asigned to a specific user_group.
    * 
* * optional string user_group = 4; @@ -187,8 +187,8 @@ public boolean hasUserGroup() { } /** *
-   * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not
-   * asigned to a specific user_id.
+   * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not
+   * asigned to a specific user_group.
    * 
* * optional string user_group = 4; @@ -209,8 +209,8 @@ public java.lang.String getUserGroup() { } /** *
-   * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not
-   * asigned to a specific user_id.
+   * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not
+   * asigned to a specific user_group.
    * 
* * optional string user_group = 4; @@ -980,8 +980,8 @@ public Builder setUserIdBytes( private java.lang.Object userGroup_ = ""; /** *
-     * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not
-     * asigned to a specific user_id.
+     * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not
+     * asigned to a specific user_group.
      * 
* * optional string user_group = 4; @@ -992,8 +992,8 @@ public boolean hasUserGroup() { } /** *
-     * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not
-     * asigned to a specific user_id.
+     * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not
+     * asigned to a specific user_group.
      * 
* * optional string user_group = 4; @@ -1013,8 +1013,8 @@ public java.lang.String getUserGroup() { } /** *
-     * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not
-     * asigned to a specific user_id.
+     * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not
+     * asigned to a specific user_group.
      * 
* * optional string user_group = 4; @@ -1035,8 +1035,8 @@ public java.lang.String getUserGroup() { } /** *
-     * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not
-     * asigned to a specific user_id.
+     * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not
+     * asigned to a specific user_group.
      * 
* * optional string user_group = 4; @@ -1053,8 +1053,8 @@ public Builder setUserGroup( } /** *
-     * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not
-     * asigned to a specific user_id.
+     * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not
+     * asigned to a specific user_group.
      * 
* * optional string user_group = 4; @@ -1068,8 +1068,8 @@ public Builder clearUserGroup() { } /** *
-     * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not
-     * asigned to a specific user_id.
+     * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not
+     * asigned to a specific user_group.
      * 
* * optional string user_group = 4; diff --git a/sdk-java/src/main/java/io/littlehorse/sdk/common/proto/UserTaskTriggerReferenceOrBuilder.java b/sdk-java/src/main/java/io/littlehorse/sdk/common/proto/UserTaskTriggerReferenceOrBuilder.java index 3052f74d3..01504da4d 100644 --- a/sdk-java/src/main/java/io/littlehorse/sdk/common/proto/UserTaskTriggerReferenceOrBuilder.java +++ b/sdk-java/src/main/java/io/littlehorse/sdk/common/proto/UserTaskTriggerReferenceOrBuilder.java @@ -79,8 +79,8 @@ public interface UserTaskTriggerReferenceOrBuilder extends /** *
-   * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not
-   * asigned to a specific user_id.
+   * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not
+   * asigned to a specific user_group.
    * 
* * optional string user_group = 4; @@ -89,8 +89,8 @@ public interface UserTaskTriggerReferenceOrBuilder extends boolean hasUserGroup(); /** *
-   * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not
-   * asigned to a specific user_id.
+   * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not
+   * asigned to a specific user_group.
    * 
* * optional string user_group = 4; @@ -99,8 +99,8 @@ public interface UserTaskTriggerReferenceOrBuilder extends java.lang.String getUserGroup(); /** *
-   * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not
-   * asigned to a specific user_id.
+   * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not
+   * asigned to a specific user_group.
    * 
* * optional string user_group = 4; diff --git a/sdk-js/src/proto/user_tasks.ts b/sdk-js/src/proto/user_tasks.ts index 74dc7bd9a..45ffd4eaf 100644 --- a/sdk-js/src/proto/user_tasks.ts +++ b/sdk-js/src/proto/user_tasks.ts @@ -347,8 +347,8 @@ export interface UserTaskTriggerReference { | string | undefined; /** - * Is the user_id that the UserTaskRun is assigned to. Unset if UserTaskRun is not - * asigned to a specific user_id. + * Is the user_group that the UserTaskRun is assigned to. Unset if UserTaskRun is not + * asigned to a specific user_group. */ userGroup?: string | undefined; } diff --git a/sdk-python/littlehorse/model/__init__.py b/sdk-python/littlehorse/model/__init__.py index c956189c7..85f573b7e 100644 --- a/sdk-python/littlehorse/model/__init__.py +++ b/sdk-python/littlehorse/model/__init__.py @@ -5,8 +5,8 @@ from .node_run_pb2 import * from .object_id_pb2 import * from .scheduled_wf_run_pb2 import * -from .service_pb2_grpc import * from .service_pb2 import * +from .service_pb2_grpc import * from .task_def_pb2 import * from .task_run_pb2 import * from .user_tasks_pb2 import * diff --git a/server/src/main/java/io/littlehorse/common/model/getable/core/taskrun/UserTaskTriggerReferenceModel.java b/server/src/main/java/io/littlehorse/common/model/getable/core/taskrun/UserTaskTriggerReferenceModel.java index ec5d3fd4f..bfbc19448 100644 --- a/server/src/main/java/io/littlehorse/common/model/getable/core/taskrun/UserTaskTriggerReferenceModel.java +++ b/server/src/main/java/io/littlehorse/common/model/getable/core/taskrun/UserTaskTriggerReferenceModel.java @@ -42,9 +42,15 @@ public Class getProtoBaseClass() { public UserTaskTriggerReference.Builder toProto() { UserTaskTriggerReference.Builder out = UserTaskTriggerReference.newBuilder() .setNodeRunId(nodeRunId.toProto()) - .setUserTaskEventNumber(userTaskEventNumber) - .setUserId(this.userId) - .setUserGroup(this.userGroup); + .setUserTaskEventNumber(userTaskEventNumber); + + if (userId != null) { + out.setUserId(this.userId); + } + + if (userGroup != null) { + out.setUserGroup(this.userGroup); + } return out; } @@ -54,8 +60,14 @@ public void initFrom(Message proto, ExecutionContext context) { UserTaskTriggerReference p = (UserTaskTriggerReference) proto; nodeRunId = LHSerializable.fromProto(p.getNodeRunId(), NodeRunIdModel.class, context); userTaskEventNumber = p.getUserTaskEventNumber(); - userId = p.getUserId(); - userGroup = p.getUserGroup(); + + if (p.hasUserId()) { + userId = p.getUserId(); + } + + if (p.hasUserGroup()) { + userGroup = p.getUserGroup(); + } } @Override diff --git a/server/src/test/java/e2e/UserTaskTest.java b/server/src/test/java/e2e/UserTaskTest.java index 773f6bbc8..4550ca55f 100644 --- a/server/src/test/java/e2e/UserTaskTest.java +++ b/server/src/test/java/e2e/UserTaskTest.java @@ -13,6 +13,9 @@ import io.littlehorse.sdk.common.proto.SaveUserTaskRunProgressRequest; import io.littlehorse.sdk.common.proto.SaveUserTaskRunProgressRequest.SaveUserTaskRunAssignmentPolicy; import io.littlehorse.sdk.common.proto.SearchWfRunRequest; +import io.littlehorse.sdk.common.proto.TaskRun; +import io.littlehorse.sdk.common.proto.TaskRunId; +import io.littlehorse.sdk.common.proto.TaskStatus; import io.littlehorse.sdk.common.proto.UserTaskEvent; import io.littlehorse.sdk.common.proto.UserTaskEvent.EventCase; import io.littlehorse.sdk.common.proto.UserTaskRun; @@ -62,6 +65,12 @@ public class UserTaskTest { @LHWorkflow("cancel-user-task-on-deadline") private Workflow userTaskCancelOnDeadline; + @LHWorkflow("schedule-reminder-task-without-user-fields-workflow") + private Workflow scheduleReminderTaskWithoutUserFields; + + @LHWorkflow("worker-context-receives-user-details") + private Workflow workerContextReceivesUserDetails; + @LHUserTaskForm(USER_TASK_DEF_NAME) private MyForm myForm = new MyForm(); @@ -296,6 +305,42 @@ void shouldExecuteBusinessExceptionHandlerWhenUserTaskGetsCancelOnDeadline() { .start(); } + @Test + void shouldScheduleAndExecuteReminderTask() { + workflowVerifier + .prepareRun(scheduleReminderTaskWithoutUserFields) + .waitForStatus(ERROR, Duration.ofSeconds(6)) + .thenVerifyNodeRun(0, 1, nodeRun -> { + UserTaskRunId userTaskId = nodeRun.getUserTask().getUserTaskRunId(); + UserTaskRun userTaskRun = client.getUserTaskRun(userTaskId); + UserTaskEvent userTaskEvent = userTaskRun.getEvents(1); + TaskRunId taskRunId = userTaskEvent.getTaskExecuted().getTaskRun(); + TaskRun taskRun = client.getTaskRun(taskRunId); + TaskStatus taskRunStatus = taskRun.getStatus(); + + Assertions.assertThat(taskRunStatus).isEqualTo(TaskStatus.TASK_SUCCESS); + }) + .start(); + } + + @Test + void verifyWorkerContextHasUserIdOrUserGroup() { + workflowVerifier + .prepareRun(workerContextReceivesUserDetails) + .waitForStatus(ERROR, Duration.ofSeconds(6)) + .thenVerifyNodeRun(0, 1, nodeRun -> { + UserTaskRunId userTaskId = nodeRun.getUserTask().getUserTaskRunId(); + UserTaskRun userTaskRun = client.getUserTaskRun(userTaskId); + UserTaskEvent userTaskEvent = userTaskRun.getEvents(1); + TaskRunId taskRunId = userTaskEvent.getTaskExecuted().getTaskRun(); + TaskRun taskRun = client.getTaskRun(taskRunId); + TaskStatus taskRunStatus = taskRun.getStatus(); + + Assertions.assertThat(taskRunStatus).isEqualTo(TaskStatus.TASK_SUCCESS); + }) + .start(); + } + @LHWorkflow("deadline-reassignment-workflow") public Workflow buildDeadlineReassignmentWorkflow() { return new WorkflowImpl("deadline-reassignment-workflow", entrypointThread -> { @@ -315,6 +360,30 @@ public Workflow buildDeadlineReassignmentWorkflow() { }); } + @LHWorkflow("schedule-reminder-task-without-user-fields-workflow") + public Workflow buildReminderTaskWorkflowWithUserGroupField() { + return new WorkflowImpl("reminder-task-without-user-fields-workflow", entrypointThread -> { + UserTaskOutput formOutput = entrypointThread.assignUserTask(USER_TASK_DEF_NAME, "jacob", null); + + // Schedule a reminder immediately + entrypointThread.scheduleReminderTask(formOutput, 0, "reminder-task"); + + entrypointThread.cancelUserTaskRunAfter(formOutput, 5); + }); + } + + @LHWorkflow("worker-context-receives-user-details") + public Workflow workerContextReceivesUserDetails() { + return new WorkflowImpl("worker-context-receives-user-details", entrypointThread -> { + UserTaskOutput formOutput = entrypointThread.assignUserTask(USER_TASK_DEF_NAME, "jacob", null); + + // Schedule a reminder immediately + entrypointThread.scheduleReminderTask(formOutput, 0, "verify-worker-context", "jacob", null); + + entrypointThread.cancelUserTaskRunAfter(formOutput, 5); + }); + } + @LHWorkflow("deadline-reassignment-workflow-user-without-group") public Workflow buildDeadlineReassignmentWorkflowUserWithoutGroup() { return new WorkflowImpl("deadline-reassignment-workflow-user-without-group", entrypointThread -> { @@ -369,6 +438,24 @@ public String userTaskCanceled() { public void doReminder(WorkerContext ctx) { cache.put(ctx.getWfRunId().getId(), "hello there!"); } + + @LHTaskMethod("verify-worker-context") + public void verifyWorkerContext(String userId, String userGroup, WorkerContext ctx) { + if (userId == null && userGroup == null) { + throw new IllegalStateException("At least one of userId or userGroup must be specified"); + } + + if (userId != null) { + if (!userId.equals(ctx.getUserId())) { + throw new IllegalStateException("WorkerContext UserId does not match expected value."); + } + } + if (userGroup != null) { + if (!userGroup.equals(ctx.getUserGroup())) { + throw new IllegalStateException("WorkerContext UserGroup does not match expected value."); + } + } + } } class MyForm {