Skip to content

External Storage Integration: WorkflowWorker, replay, history - #3017

Open
cconstable wants to merge 18 commits into
mainfrom
extstore/workflow-worker
Open

External Storage Integration: WorkflowWorker, replay, history#3017
cconstable wants to merge 18 commits into
mainfrom
extstore/workflow-worker

Conversation

@cconstable

@cconstable cconstable commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

What was changed

  • Integrated external storage into the replay handler and history iterator.
  • WorkflowWorker handle + send response now use external storage.

Why

  • Workflow workers should utilize external storage and fetch payloads on replay.

Checklist

  • Added tests.

@cconstable
cconstable force-pushed the extstore/workflow-worker branch from dff9b7f to 3a20dcf Compare August 18, 2026 21:04
@cconstable
cconstable changed the base branch from main to extstore/foundation August 19, 2026 15:58
@cconstable
cconstable force-pushed the extstore/foundation branch from 831c284 to 460bfbf Compare August 19, 2026 17:40
@cconstable
cconstable changed the base branch from extstore/foundation to main August 19, 2026 17:53
@cconstable
cconstable changed the base branch from main to extstore/foundation August 19, 2026 17:53
@cconstable
cconstable force-pushed the extstore/workflow-worker branch from 3a20dcf to 0e37f9d Compare August 19, 2026 18:12
@cconstable cconstable changed the title extstore/workflow worker External Storage Integration: WorkflowWorker, replay, history Aug 19, 2026
@cconstable
cconstable force-pushed the extstore/workflow-worker branch from 0e37f9d to c67e0f0 Compare August 19, 2026 18:30
@cconstable
cconstable marked this pull request as ready for review August 19, 2026 18:57
@cconstable
cconstable requested a review from a team as a code owner August 19, 2026 18:57
@cconstable
cconstable force-pushed the extstore/foundation branch from 460bfbf to b3804da Compare August 21, 2026 20:35
@cconstable
cconstable force-pushed the extstore/workflow-worker branch from c67e0f0 to e292757 Compare August 21, 2026 21:57
@cconstable
cconstable force-pushed the extstore/foundation branch from b3804da to ca09b50 Compare August 24, 2026 01:23
@cconstable
cconstable force-pushed the extstore/workflow-worker branch from e292757 to cb05443 Compare August 24, 2026 01:25
Comment thread temporal-sdk/src/main/java/io/temporal/internal/worker/WorkflowWorker.java Outdated
@cconstable
cconstable force-pushed the extstore/workflow-worker branch 5 times, most recently from 6d90f7e to 1538817 Compare August 27, 2026 21:28
@cconstable
cconstable force-pushed the extstore/foundation branch from 2d2d90e to 504467c Compare August 28, 2026 16:10
Base automatically changed from extstore/foundation to main August 28, 2026 17:27
@cconstable
cconstable force-pushed the extstore/workflow-worker branch from 1538817 to d7b9a62 Compare August 28, 2026 21:36
@cconstable
cconstable force-pushed the extstore/workflow-worker branch from d7b9a62 to 8062db7 Compare August 31, 2026 15:49
Comment thread temporal-sdk/src/main/java/io/temporal/internal/worker/WorkflowWorker.java Outdated
Comment thread temporal-sdk/src/main/java/io/temporal/internal/worker/WorkflowWorker.java Outdated
Comment thread temporal-sdk/src/main/java/io/temporal/internal/worker/WorkflowWorker.java Outdated
Comment thread temporal-sdk/src/main/java/io/temporal/internal/worker/WorkflowWorker.java Outdated
Comment on lines +406 to +409
} catch (CancellationException e) {
// if the worker is shutting down, extstore will throw a CancellationException and we need to
// rethrow it here so the handle() method can decide what to do.
throw e;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Rather than absorbing a cancellation exception it's just rethrown. I think this covers all the cases we want and it allows the caller (handle()) to determine whether or not to actually send a task failure to the server... if we are in the middle of a forced shutdown it will see this cancellation error and just absorb it instead of throwing (which would result in a task failure being emitted).

Comment on lines +180 to +181
|| ex instanceof CancellationException
|| ex.getCause() instanceof CancellationException

@cconstable cconstable Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

During shutdown we shouldn't emit task failures due to things being cancelled because of the shutdown. At the moment, I don't think this actually catches any external storage stuff (since this check happens at a higher level than where the external storage exceptions are caught) but I think it's the "correct" behavior to add regardless and would prevent future issues. Would like some feedback on this @Quinn-With-Two-Ns or @maciejdudko

Comment on lines +722 to +727
} catch (CancellationException e) {
if (!options.getStorageCancellation().isCancellationRequested()) {
throw e;
}
log.trace("Abandoned a workflow task while the worker was shutting down", e);
return;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

When extstore throws a cancellation, if we are not forcefully shutting down then rethrow the error and report a failure. Otherwise, we should accept that the cancellation is just a normal part of the shutdown. The same logic was added below. It's possible that this cancellation exception might not originate from external storage in the future but I still think this is the correct course of action.

.setCompletedType(QueryResultType.QUERY_RESULT_TYPE_FAILED)
.setErrorMessage(failure.getMessage())
.setFailure(failure);
sendDirectQueryCompletedResponse(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we should send this without offloading to external storage. Recovering from an external storage error to attempt to send a failure message that external storage failed previous and use external storage on that message is likely going to fail again. This would also make it consistent with Go and Python. It should also clear taskFailedCause so that metrics are not emitted for a failure that was not actually reported.

.setCause(
WorkflowTaskFailedCause
.WORKFLOW_TASK_FAILED_CAUSE_WORKFLOW_WORKER_UNHANDLED_FAILURE);
sendTaskFailed(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we should send this without offloading to external storage. Recovering from an external storage error to attempt to send a failure message that external storage failed previous and use external storage on that message is likely going to fail again. This would also make it consistent with Go and Python. It should also clear taskFailedCause so that metrics are not emitted for a failure that was not actually reported.

@@ -473,7 +611,10 @@
.setErrorMessage(failure.getMessage())
.setFailure(failure);
sendDirectQueryCompletedResponse(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should be wrapped in try-catch ExternalStorageTaskFailure and recover by just logging and abandoning sending to the server. See https://github.com/temporalio/sdk-go/blob/57cc5a7d619493f2e67166e2200e8e3758a72ae0/internal/internal_task_pollers.go#L764-L803 as an example. It should also clear taskFailedCause so that metrics are not emitted for a failure that was not actually reported.

.setCause(
WorkflowTaskFailedCause
.WORKFLOW_TASK_FAILED_CAUSE_GRPC_MESSAGE_TOO_LARGE);
sendTaskFailed(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should be wrapped in try-catch ExternalStorageTaskFailure and recover by just logging and abandoning sending to the server. See https://github.com/temporalio/sdk-go/blob/57cc5a7d619493f2e67166e2200e8e3758a72ae0/internal/internal_task_pollers.go#L764-L803 as an example. It should also clear taskFailedCause so that metrics are not emitted for a failure that was not actually reported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants