Skip to content

Conversation

javier-aliaga
Copy link

@javier-aliaga javier-aliaga commented May 26, 2025

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Comment on lines 56 to 60
- WorkflowInstanceId: This field will provide a unique identifier for the workflow instance. It is already available in the orchestration context but will now be propagated to the activity context.

- TaskInstanceId: This field will provide a unique identifier for the same activity among retries. This new field will be part of the [Activity Request](https://github.com/dapr/durabletask-protobuf/blob/main/protos/orchestrator_service.proto) and needs to be populated in the runtime.

- RetryAttempt: This field will contain the current retry count for the activity execution.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the expected proto changes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


### Related proposals

N/A
Copy link
Contributor

@nelson-parente nelson-parente May 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't there some overlap between this proposal and Workflow: Rerun from Activity #80?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think so, as a rerun is a completely new run of the activity


The proposed fields introduced in this document are:

- WorkflowInstanceId: This field will provide a unique identifier for the workflow instance. It is already available in the orchestration context but will now be propagated to the activity context.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how is this unique identifier built? same question for TaskInstanceId

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


- TaskInstanceId: This field will provide a unique identifier for the same activity among retries. This new field will be part of the [Activity Request](https://github.com/dapr/durabletask-protobuf/blob/main/protos/orchestrator_service.proto) and needs to be populated in the runtime.

- RetryAttempt: This field will contain the current retry count for the activity execution.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a retry the same as a rerun?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think so. I would say that rerun are part of the orchestration events and retries are part of the task execution failure.

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: Javier Aliaga <javier@diagrid.io>
@WhitWaldo
Copy link

Sort of continuing my thoughts on last weeks (5/20) release call, I don't follow how activity identifiers provide stronger guarantees against re-execution or otherwise help track activity execution state.

Event Source Log Already Handles Replays

The event source log persists activity inputs and outputs when an activity successfully completes. During a workflow replay (I'm not talking about the proposed re-run operation), the system reuses persisted outputs and only re-executes activities with no matching log. This already ensures idempotency between replays without needing activity identifiers:

  • If the data exists in the log, the activity isn't re-executed
  • If the data doesn't exist in the log, the activity is re-executed

An activity identifier doesn't change this logic - it adds a redundant check without improving reliability.

Idempotency Isn't Required for Activities

Dapr recommends, but doesn't require, idempotent activities. Developers can ensure one-time external calls per-workflow by isolating them in activities because once that result is logged, the activity isn't going to run again.

If some sort of uniqueness is needed, developers can generate a deterministic GUID within the workflow context and pass it into the activity as an input, so that activity-level identifier doesn't add value here either.

Ultimately, I don't see how this functionality meaningfully improves workflows. The concerns raised are already addressed by the current implementation and adding identifiers to activity contexts doesn't significantly simplify the current approach. While clearer documentation could help to resolve some of the confusion around best practices, I disagree that this is a necessary change.

@javier-aliaga
Copy link
Author

Thanks @WhitWaldo for your feedback. This proposal is mostly for idempotency and other patterns not covered by the replay.

As you say you can achieve the idempotency by passing the unique identifier as part of the input, but in my experience it feels more natural to be part of the context as you do not have to modify your input to support it. I will look a bit more how other workflow engines supports this, we already check with Temporal and they provide a unique activity Id.

I also have been looking a bit more into other patterns, for example, in a case a user of workflows want to monitor all invocations for a given workflow, should they also modify their input to include it? It would be handy to have the instanceId as part of the activity to send it to all third party systems.

Again, as you say this proposal can be achieve by other ways, but having more information in the activity context I think it makes it easy to the users to implement this patterns.

@WhitWaldo
Copy link

Thanks @WhitWaldo for your feedback. This proposal is mostly for idempotency and other patterns not covered by the replay.

As you say you can achieve the idempotency by passing the unique identifier as part of the input, but in my experience it feels more natural to be part of the context as you do not have to modify your input to support it. I will look a bit more how other workflow engines supports this, we already check with Temporal and they provide a unique activity Id.

I also have been looking a bit more into other patterns, for example, in a case a user of workflows want to monitor all invocations for a given workflow, should they also modify their input to include it? It would be handy to have the instanceId as part of the activity to send it to all third party systems.

Again, as you say this proposal can be achieve by other ways, but having more information in the activity context I think it makes it easy to the users to implement this patterns.

Temporal certainly diverges in several ways from Dapr Workflows - given the limited bandwidth everyone has for each release, for my two cents, I'd rather see the energy flow more towards fixing bugs and enabling new functionality that's not otherwise achievable over something like this, seeing as it is more of an alternative way of doing something already easily achievable and which already has helper method support.

Case in point, the workflow must be deterministic and those non-deterministic operations (like getting the current timestamp or creating a GUID) must be placed in activities so the output is persisted for replays. But to enable and simplify precisely this sort of scenario, the WorkflowContext provides a context.CurrentUtcDateTime property and a context.NewGuid() method that provide replayable versions of each of these right there on the workflow context, so they might trivially be passed into the activity as deterministic inputs.

With respect to monitoring, identifiers don't really facilitate that scenario quite as much as Cassie's event streaming proposal might, especially coupled with more verbose tracing already produced by the runtime (which presumably already reflects the workflow ID) and reflecting input values. Especially as the activity identifiers themselves aren't addressable, seeing them in the logs would be less useful to me than knowing which piece of the larger work was being tackled by that activity.

@javier-aliaga
Copy link
Author

javier-aliaga commented May 27, 2025

@WhitWaldo I was thinking on logs. I can see a pattern to create a workflow run with instanceId as the correlationId so then you can propagate that id to all different systems and get a unified log

@WhitWaldo
Copy link

WhitWaldo commented May 27, 2025

@WhitWaldo I was thinking on logs. I can see a pattern to create a workflow run with instanceId as the correlationId so then you can propagate that id to all different systems and get a unified log

Thinking in terms of Temporal, they actually break out the notion of Workflows as an entity and as a run so the latter has a separate identifier with each execution. While Dapr Workflows isn't well set up to do the same today, I think having some sort of unique Workflow Execution identifier correlating all the activities across all executions that's paired with another identifier that's unique per Workflow Replay would be useful as a pair of correlation identifiers. But that would need to happen pretty much entirely at the runtime and wouldn't itself be reflected at all in the SDKs.

@javier-aliaga
Copy link
Author

@WhitWaldo I simplified the proposal to make only reference to idempotency

@WhitWaldo
Copy link

@WhitWaldo I simplified the proposal to make only reference to idempotency

I'm sure we'll talk about this in the release call today, but I'm still going to double down and say that an actor-level identifier is not necessary for idempotency purposes. That's already handled by how the event source log works today.

@yaron2
Copy link
Member

yaron2 commented May 28, 2025

@WhitWaldo I simplified the proposal to make only reference to idempotency

I'm sure we'll talk about this in the release call today, but I'm still going to double down and say that an actor-level identifier is not necessary for idempotency purposes. That's already handled by how the event source log works today.

That's not accurate, activities can be retried at the daprd level for any number of reasons, including gRPC transport level errors. Users today are reporting multiple activations of activities.

@javier-aliaga javier-aliaga marked this pull request as ready for review May 28, 2025 17:54
@WhitWaldo
Copy link

@WhitWaldo I simplified the proposal to make only reference to idempotency

I'm sure we'll talk about this in the release call today, but I'm still going to double down and say that an actor-level identifier is not necessary for idempotency purposes. That's already handled by how the event source log works today.

That's not accurate, activities can be retried at the daprd level for any number of reasons, including gRPC transport level errors. Users today are reporting multiple activations of activities.

I guess I remain confused about what this proposal is advocating for then.

I read it as asking for activities to have an identifier populated in the activity context that users could read and pass to third-party services as an idempotency token - if that's what's being asked for, I would still suggest this isn't necessary because that identifier can be generated in a replay-safe way on the workflow context and passed in via the input.

While I probably could have worded my last response more clearly, I wasn't suggesting that activities don't ever get re-run - as I articulated in an earlier comment, they don't get re-run when they complete successfully. My point being that having the identifier saved alongside the event source log seems duplicative because if there's a completed log for the activity, it ran and it won't again - we don't need an identifier to validate this.

If multiple activations are being observed, that sounds like a runtime bug and not something that can or should be addressed by changes to the SDKs, but I didn't see anything about that in this proposal.

@javier-aliaga javier-aliaga changed the title [WIP] Enrich workflow activity context Enrich workflow activity context May 29, 2025
@javier-aliaga
Copy link
Author

javier-aliaga commented May 30, 2025

@WhitWaldo the main reason for this is:

I read it as asking for activities to have an identifier populated in the activity context that users could read and pass to third-party services as an idempotency token - if that's what's being asked for, I would still suggest this isn't necessary because that identifier can be generated in a replay-safe way on the workflow context and passed in via the input.

I took a look to the event logs and I think having this identifier will also help there. Just an example, I created the following workflow:
imagen

And this is the event log:

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000000
eventId:-1  timestamp:{seconds:1748593106  nanos:667706961}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000001
eventId:-1  timestamp:{seconds:1748593106  nanos:660805086}  executionStarted:{name:"HelloWorldWorkflow"  input:{value:"{\"data\":{}}"}  orchestrationInstance:{instanceId:"d9026db3-d660-4c80-b610-c48fc8961e1d"  executionId:{value:"053c5a78-bc45-4e99-83b7-78ff96baca1d"}}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000002
timestamp:{seconds:1748593106  nanos:668935336}  taskScheduled:{name:"SayHelloWorldActivity"  input:{value:"{\"name\":\"John\"}"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000003
eventId:1  timestamp:{seconds:1748593106  nanos:668936336}  taskScheduled:{name:"SayHelloWorldActivity"  input:{value:"{\"name\":\"Helen\"}"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000004
eventId:2  timestamp:{seconds:1748593106  nanos:668936627}  taskScheduled:{name:"SayHelloWorldActivity"  input:{value:"{\"name\":\"Gloria\"}"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000005
eventId:-1  timestamp:{seconds:1748593106  nanos:681033794}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000006
eventId:-1  timestamp:{seconds:1748593106  nanos:673115252}  taskFailed:{failureDetails:{errorType:"*fmt.wrapError"  errorMessage:"activity SayHelloWorldActivity failed: retrying: 3"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000007
eventId:-1  timestamp:{seconds:1748593106  nanos:673192169}  taskFailed:{taskScheduledId:1  failureDetails:{errorType:"*fmt.wrapError"  errorMessage:"activity SayHelloWorldActivity failed: retrying: 2"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000008
eventId:-1  timestamp:{seconds:1748593106  nanos:673281377}  taskFailed:{taskScheduledId:2  failureDetails:{errorType:"*fmt.wrapError"  errorMessage:"activity SayHelloWorldActivity failed: retrying: 1"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000009
eventId:3  timestamp:{seconds:1748593106  nanos:681508794}  timerCreated:{fireAt:{seconds:1748593106  nanos:781033794}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000010
eventId:-1  timestamp:{seconds:1748593106  nanos:684286544}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000011
eventId:-1  timestamp:{seconds:1748593106  nanos:681509377}  timerFired:{fireAt:{seconds:1748593106  nanos:781033794}  timerId:3}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000012
eventId:4  timestamp:{seconds:1748593106  nanos:684734752}  taskScheduled:{name:"SayHelloWorldActivity"  input:{value:"{\"name\":\"John\"}"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000013
eventId:-1  timestamp:{seconds:1748593106  nanos:690238669}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000014
eventId:-1  timestamp:{seconds:1748593106  nanos:688579502}  taskFailed:{taskScheduledId:4  failureDetails:{errorType:"*fmt.wrapError"  errorMessage:"activity SayHelloWorldActivity failed: retrying: 2"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000015
eventId:5  timestamp:{seconds:1748593106  nanos:690642127}  timerCreated:{fireAt:{seconds:1748593106  nanos:840238669}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000016
eventId:-1  timestamp:{seconds:1748593106  nanos:692082086}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000017
eventId:-1  timestamp:{seconds:1748593106  nanos:690642586}  timerFired:{fireAt:{seconds:1748593106  nanos:840238669}  timerId:5}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000018
eventId:6  timestamp:{seconds:1748593106  nanos:692330127}  taskScheduled:{name:"SayHelloWorldActivity"  input:{value:"{\"name\":\"John\"}"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000019
eventId:-1  timestamp:{seconds:1748593106  nanos:697517544}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000020
eventId:-1  timestamp:{seconds:1748593106  nanos:695838919}  taskFailed:{taskScheduledId:6  failureDetails:{errorType:"*fmt.wrapError"  errorMessage:"activity SayHelloWorldActivity failed: retrying: 1"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000021
eventId:7  timestamp:{seconds:1748593106  nanos:697780502}  timerCreated:{fireAt:{seconds:1748593106  nanos:922517544}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000022
eventId:-1  timestamp:{seconds:1748593106  nanos:699085544}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000023
eventId:-1  timestamp:{seconds:1748593106  nanos:697780877}  timerFired:{fireAt:{seconds:1748593106  nanos:922517544}  timerId:7}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000024
eventId:8  timestamp:{seconds:1748593106  nanos:699309544}  taskScheduled:{name:"SayHelloWorldActivity"  input:{value:"{\"name\":\"John\"}"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000025
eventId:-1  timestamp:{seconds:1748593107  nanos:705661586}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000026
eventId:-1  timestamp:{seconds:1748593107  nanos:701588669}  taskCompleted:{taskScheduledId:8  result:{value:"{\"startTime\":\"2025-05-30T08:18:26.701098002Z\",\"endTime\":\"2025-05-30T08:18:27.701260753Z\",\"success\":true,\"message\":\"Hello John!\"}"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000027
eventId:9  timestamp:{seconds:1748593107  nanos:706152211}  timerCreated:{fireAt:{seconds:1748593107  nanos:805661586}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000028
eventId:-1  timestamp:{seconds:1748593107  nanos:707640544}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000029
eventId:-1  timestamp:{seconds:1748593107  nanos:706152878}  timerFired:{fireAt:{seconds:1748593107  nanos:805661586}  timerId:9}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000030
eventId:10  timestamp:{seconds:1748593107  nanos:708119128}  taskScheduled:{name:"SayHelloWorldActivity"  input:{value:"{\"name\":\"Helen\"}"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000031
eventId:-1  timestamp:{seconds:1748593107  nanos:716527211}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000032
eventId:-1  timestamp:{seconds:1748593107  nanos:710915711}  taskFailed:{taskScheduledId:10  failureDetails:{errorType:"*fmt.wrapError"  errorMessage:"activity SayHelloWorldActivity failed: retrying: 1"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000033
eventId:11  timestamp:{seconds:1748593107  nanos:717072169}  timerCreated:{fireAt:{seconds:1748593107  nanos:866527211}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000034
eventId:-1  timestamp:{seconds:1748593107  nanos:719996711}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000035
eventId:-1  timestamp:{seconds:1748593107  nanos:717072669}  timerFired:{fireAt:{seconds:1748593107  nanos:866527211}  timerId:11}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000036
eventId:12  timestamp:{seconds:1748593107  nanos:720561503}  taskScheduled:{name:"SayHelloWorldActivity"  input:{value:"{\"name\":\"Helen\"}"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000037
eventId:-1  timestamp:{seconds:1748593108  nanos:737914420}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000038
eventId:-1  timestamp:{seconds:1748593108  nanos:726112378}  taskCompleted:{taskScheduledId:12  result:{value:"{\"startTime\":\"2025-05-30T08:18:27.722927503Z\",\"endTime\":\"2025-05-30T08:18:28.724541003Z\",\"success\":true,\"message\":\"Hello Helen!\"}"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000039
eventId:13  timestamp:{seconds:1748593108  nanos:739599128}  timerCreated:{fireAt:{seconds:1748593108  nanos:837914420}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000040
eventId:-1  timestamp:{seconds:1748593108  nanos:745545545}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000041
eventId:-1  timestamp:{seconds:1748593108  nanos:739601670}  timerFired:{fireAt:{seconds:1748593108  nanos:837914420}  timerId:13}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000042
eventId:14  timestamp:{seconds:1748593108  nanos:747115753}  taskScheduled:{name:"SayHelloWorldActivity"  input:{value:"{\"name\":\"Gloria\"}"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000043
eventId:-1  timestamp:{seconds:1748593109  nanos:755771295}  orchestratorStarted:{}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000044
eventId:-1  timestamp:{seconds:1748593109  nanos:752833920}  taskCompleted:{taskScheduledId:14  result:{value:"{\"startTime\":\"2025-05-30T08:18:28.751417503Z\",\"endTime\":\"2025-05-30T08:18:29.752485837Z\",\"success\":true,\"message\":\"Hello Gloria!\"}"}}

k:helloworldworkflow-app||dapr.internal.dapr-tests.helloworldworkflow-app.workflow||d9026db3-d660-4c80-b610-c48fc8961e1d||history-000045
eventId:15  timestamp:{seconds:1748593109  nanos:756551045}  executionCompleted:{orchestrationStatus:ORCHESTRATION_STATUS_COMPLETED  result:{value:"{\"success\":true,\"activityHistory\":[{\"activityName\":\"SayHelloWorldActivity1\",\"activityType\":\"activity\",\"startTime\":\"2025-05-30T08:18:26.701098002Z\",\"endTime\":\"2025-05-30T08:18:27.701260753Z\"},{\"activityName\":\"SayHelloWorldActivity2\",\"activityType\":\"activity\",\"startTime\":\"2025-05-30T08:18:27.722927503Z\",\"endTime\":\"2025-05-30T08:18:28.724541003Z\"},{\"activityName\":\"SayHelloWorldActivity3\",\"activityType\":\"activity\",\"startTime\":\"2025-05-30T08:18:28.751417503Z\",\"endTime\":\"2025-05-30T08:18:29.752485837Z\"}]}"}}

As you can see it is not easy to track the log for one of the activities, even if you have the idempotency/execution key as part of the input it is not present in all the entry logs for the activity execution, like the history-000006 entry, which activity failed?

@WhitWaldo
Copy link

WhitWaldo commented Jun 3, 2025

I don't dispute the potential value of having an activity run-specific identifier in the activity context for potential idempotency support, but this would need some consideration with Josh's re-run feature to identify whether that identifier should change between re-runs (meaning it's not useful for idempotency support) or not.

Rather, it seems like you'd need an approach as I'd suggested to keep this value consistent between re-run invocations (with a deterministic value passed in from the workflow).

On the release call today, this was clarified as having a separate activity ID for each re-run (think of it as a hash specific to the inputs) but the same activity ID for each retry.

@WhitWaldo
Copy link

While talking through the re-run functionality on today's release call, it occurred to me - idempotency, traceability, etc. aside, isn't this just an identifier for the activities themselves so they can be identified as the re-run/clone starting point? If that's the case, since we're moving forward with re-run/clone support, this seems like a must-have or there'd be no easy way to identify the starting activity in the cloned workflow.

Signed-off-by: Javier Aliaga <javier@diagrid.io>
@olitomlinson
Copy link

I agree with @WhitWaldo remarks here.

If some sort of uniqueness is needed, developers can generate a deterministic GUID within the workflow context and pass it into the activity as an input, so that activity-level identifier doesn't add value here either.

It really is trivial to pass in an additional property on an input model to an Activity, which contains the Idempotency Key to be utilised in the Activity.

Also bare in mind that if you truly want to support complete idempotency chains via this proposal, you need to allow an option for a user to specify the Idempotency Key on the Activity Call signature (rather than have Dapr originate one for you implicitly) -- All we've done at this point is shifted the user-defined Idempotency Key from the input model to the method signature, which IMO is not worth it.

This can all be solved with better documentation and code examples.

@cicoyle cicoyle moved this from In progress to Done in v1.16 Release Tracking Board Jul 22, 2025
@JoshVanL
Copy link
Contributor

+1 binding

1 similar comment
@cicoyle
Copy link
Contributor

cicoyle commented Sep 24, 2025

+1 binding

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

7 participants