sdk-java icon indicating copy to clipboard operation
sdk-java copied to clipboard

Workflow should have an access to an activity id of the activity it scheduled

Open Spikhalskiy opened this issue 4 years ago • 3 comments

Is your feature request related to a problem? Please describe. There is a scenario when a workflow needs to cancel an activity if it gets an external signal.

For example, an activity sends its own id to some external code and this code has a need to cancel the activity if something happens or finishes before the activity is done. Right now the only way for an external code to cancel an activity in progress is to send a signal to the workflow that scheduled the activity and the workflow cancels the activity using a cancelation scope after that.

To do that, the activity can't use an activityId, the user needs to create some new correlation id and pass it from the workflow into the activity because an activity code has no way to know an activityId of the activity it just scheduled.

Describe the solution you'd like

  1. We create some kind of ActivityInvocationStub for each invocation of an activity. This stub may bind an activityType and any kind of additional parameters we need to set per each invocation. This stub can also expose the activityId. User may not be required to work with such stubs all the time if they don't need them, but they should be available if the user needs them (the same way as untyped WorkflowStubs are implemented)
  2. Workflow should be able to generate and pass an activityId into such kind of stub. We should be careful with that, because activityIds in JavaSDK are used to ensure determinism and identify a state machine, so duplicates should be prohibited.

Such a stub should also potentially be able to override ActivityOptions for the specific activity call.

Describe alternatives you've considered Change nothing and make users pass their own additional ids (and maintain a mapping between these ids to the cancelation scopes or the activities) if they need the workflow to be able to address and cancel an activity later. But there are other reasons to have such stubs: #1009

Additional context What about timers for example? Should the same apply to timers and their ids?

Spikhalskiy avatar Jan 30 '22 07:01 Spikhalskiy

This is also really important for using async activity completion. On server side, activity can be completed with tasktoken or activityID. But JavaSDK only expose tasktoken.

The task token approach is problematic in some cases — By nature user needs to set a long timeout(startToClose) because they don’t know when the external system will complete the activity. The tasktoken can only be retrieved within the activity(for determinism) and send to the external system, before calling ctx.doNotCompleteOnReturn(); However, there could be errors(e.g. timeout) and retry when sending the tasktoken, and then the activity worker can get restarted. As a result, the activity will be stuck until the timeout…

longquanzheng avatar Feb 02 '22 19:02 longquanzheng

External code that uses async activity completion should always be triggered by the activity itself. When this happens, an activity should pass activityId/taskToken to that code. There should be no code that uses some predefined activityId, but is not triggered by this activity itself. Activity (and its ID) is an internal entity of a workflow and not it's public API. Workflow and its ID is a business-level entity, Activity and ActivityId is a workflow implementation detail. This implementation detail may be known by, in turn, it's own implementation detail (code that is triggered by it), but it shouldn't be known by some external code not directly triggered by the activity itself. For that purpose, there are signals. Signals have predefined names and are exposed on the business level entity - workflow.

An activity execution already has its own id now and can pass it to the code performing the completion. Thus, this task is not a prerequisite for an activity completion in a way how it's intended to be used.

Spikhalskiy avatar Feb 02 '22 21:02 Spikhalskiy

An activity execution already has its own id now and can pass it to the code performing the completion.

Passing the ID within the activity is not reliable. We should redesign this part for async activity completion.

What if activity worker restarted when the RPC of sending ID/token timeout and retry? This will cause the activity stuck forever, unless we require the activity to implement heartbeat.Implementing heartbeat will be tedious and extremely inefficient -- will cost lots of API requests to server.

longquanzheng avatar Feb 03 '22 00:02 longquanzheng