fix(ext-workflow): honor DAPR_GRPC_MAX_INBOUND_MESSAGE_SIZE_BYTES on workflow channels#1085
fix(ext-workflow): honor DAPR_GRPC_MAX_INBOUND_MESSAGE_SIZE_BYTES on workflow channels#1085tezizzm wants to merge 3 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1085 +/- ##
==========================================
- Coverage 86.63% 82.15% -4.48%
==========================================
Files 84 116 +32
Lines 4473 9578 +5105
==========================================
+ Hits 3875 7869 +3994
- Misses 598 1709 +1111 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR fixes workflow gRPC message-size handling in dapr-ext-workflow so long-running workflows with large activity payloads (or large accumulated orchestration history) can honor DAPR_GRPC_MAX_INBOUND_MESSAGE_SIZE_BYTES (and an explicit max_grpc_message_length kwarg) instead of failing at gRPC’s default 4 MiB limit.
Changes:
- Added
get_grpc_channel_options()utility to resolve workflow gRPC channel options (kwarg → env var → gRPC default), applying limits symmetrically for send/receive. - Threaded
max_grpc_message_length: Optional[int] = Nonethrough workflow runtime and both sync/async workflow clients, passing resolvedchannel_optionsinto durabletask constructors. - Added unit tests covering precedence and symmetric option application for runtime and clients.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| ext/dapr-ext-workflow/dapr/ext/workflow/util.py | Adds get_grpc_channel_options() to compute workflow-channel gRPC max message size options. |
| ext/dapr-ext-workflow/dapr/ext/workflow/workflow_runtime.py | Threads max_grpc_message_length into WorkflowRuntime and passes computed channel_options to TaskHubGrpcWorker. |
| ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_client.py | Threads max_grpc_message_length into sync DaprWorkflowClient and passes computed channel_options to TaskHubGrpcClient. |
| ext/dapr-ext-workflow/dapr/ext/workflow/aio/dapr_workflow_client.py | Threads max_grpc_message_length into async DaprWorkflowClient and passes computed channel_options to AsyncTaskHubGrpcClient. |
| ext/dapr-ext-workflow/tests/test_workflow_util.py | Adds tests for get_grpc_channel_options() precedence and symmetric send/receive options. |
| ext/dapr-ext-workflow/tests/test_workflow_runtime.py | Adds tests asserting WorkflowRuntime passes symmetric channel_options derived from kwarg/env var. |
| ext/dapr-ext-workflow/tests/test_workflow_client.py | Adds tests asserting sync DaprWorkflowClient passes symmetric channel_options derived from kwarg/env var. |
| ext/dapr-ext-workflow/tests/test_workflow_client_aio.py | Adds tests asserting async DaprWorkflowClient passes symmetric channel_options derived from kwarg/env var. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…workflow channels Workflow activity payloads over gRPC's 4 MiB default raised RESOURCE_EXHAUSTED because the durabletask channel ignored the message size limit. dapr#1024 plumbed DAPR_GRPC_MAX_INBOUND_MESSAGE_SIZE_BYTES through the Dapr API channel only; the workflow worker and clients still fell back to the gRPC default. Add a get_grpc_channel_options helper that resolves the limit from an explicit max_grpc_message_length kwarg, then the env var, then None, and thread it through WorkflowRuntime, DaprWorkflowClient, and the async DaprWorkflowClient. Unlike dapr#1024, set both send and receive limits symmetrically since workflow payloads cross the channel in both directions. Reuses the existing setting; no new env var. Signed-off-by: Martez Killens <5050479+tezizzm@users.noreply.github.com>
Co-authored-by: Casper Nielsen <whopsec@protonmail.com> Signed-off-by: Martez Killens <tezizzm@users.noreply.github.com>
Make explicit that a `0` value in either the kwarg or the DAPR_GRPC_MAX_INBOUND_MESSAGE_SIZE_BYTES env var is treated as "no opinion" and falls through to the next source, consistent with the documented `global_settings.DAPR_GRPC_MAX_INBOUND_MESSAGE_SIZE_BYTES = 0` sentinel. Behavior is unchanged; this addresses PR review feedback asking for the precedence rule to be stated precisely. Signed-off-by: Martez Killens <tezizzm@users.noreply.github.com>
2ebb2bd to
272f7cd
Compare
| ): | ||
| """Initializes the async workflow client. | ||
|
|
||
| Args: |
There was a problem hiding this comment.
I think it'd be good to document all arguments instead of just the new one, otherwise the documentation is incomplete.
| ): | ||
| """Initializes the sync workflow client. | ||
|
|
||
| Args: |
| ): | ||
| """Initializes the workflow runtime. | ||
|
|
||
| Args: |
Description
Long-running workflows whose activity results exceed gRPC's 4 MiB default fail with
RESOURCE_EXHAUSTED: Sent message larger than max (X vs. 4194304). #1024 addedDAPR_GRPC_MAX_INBOUND_MESSAGE_SIZE_BYTESand threaded it through the Dapr APIchannel only — it did not cover the workflow (durabletask) channel, so even with
the env var exported, workflows still hit the 4 MiB ceiling once the orchestration
history (input + accumulated activity results) crossed the limit.
This PR mirrors the #1024 pattern in
dapr-ext-workflow:get_grpc_channel_options()helper indapr/ext/workflow/util.py. Resolutionorder: explicit
max_grpc_message_lengthkwarg →settings.DAPR_GRPC_MAX_INBOUND_MESSAGE_SIZE_BYTES→
None(gRPC default).max_grpc_message_length: Optional[int] = Nonekwarg throughthe three workflow gRPC constructors and passes the resolved
channel_options:WorkflowRuntime.__init__→TaskHubGrpcWorkerDaprWorkflowClient.__init__(sync) →TaskHubGrpcClientaio.DaprWorkflowClient.__init__(async) →AsyncTaskHubGrpcClientprecedence.
Unlike #1024, the limit is applied symmetrically to both send and receive, because
workflow activity payloads cross the channel in both directions (worker → daprd carries
activity output too); #1024 only set the receive limit in its env-var branch.
No new environment variable is introduced (reuses #1024's), and no vendored
_durabletask/internals ordapr/proto/files are touched.Issue reference
We strive to have all PR being opened based on an issue, where the problem or feature have been discussed prior to implementation.
Please reference the issue this PR will close: #1084
Checklist
Please make sure you've completed the relevant tasks for this PR, out of the following list: