Conversation
There was a problem hiding this comment.
Pull request overview
Adds work-item filtering support to the Java SDK worker so the backend can dispatch only matching orchestration/activity work items to a given DurableTaskGrpcWorker, with builder APIs for explicit or auto-generated filters.
Changes:
- Introduces
WorkItemFiltermodel + builder for orchestration/activity name (+ optional version) filters. - Extends
DurableTaskGrpcWorkerBuilderto accept explicit filters or auto-generate filters from registered task types (with versioning-aware behavior for STRICT matching). - Updates
DurableTaskGrpcWorkerto sendWorkItemFiltersinGetWorkItemsRequestand adds unit tests + changelog entry.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| client/src/main/java/com/microsoft/durabletask/WorkItemFilter.java | New public API type representing orchestration/activity work-item filters. |
| client/src/main/java/com/microsoft/durabletask/DurableTaskGrpcWorkerBuilder.java | Adds useWorkItemFilters(...) APIs and auto-generation of filters during build(). |
| client/src/main/java/com/microsoft/durabletask/DurableTaskGrpcWorker.java | Sends filters to the sidecar via GetWorkItemsRequest.workItemFilters. |
| client/src/test/java/com/microsoft/durabletask/WorkItemFilterTest.java | Unit tests for WorkItemFilter behavior + proto conversion. |
| client/src/test/java/com/microsoft/durabletask/WorkItemFilterBuilderTest.java | Unit tests for builder/worker integration of explicit and auto-generated filters. |
| CHANGELOG.md | Notes new work item filtering support in Unreleased. |
| private GetWorkItemsRequest buildGetWorkItemsRequest() { | ||
| GetWorkItemsRequest.Builder builder = GetWorkItemsRequest.newBuilder(); | ||
| if (this.workItemFilter != null) { | ||
| builder.setWorkItemFilters(toProtoWorkItemFilters(this.workItemFilter)); |
There was a problem hiding this comment.
buildGetWorkItemsRequest() rebuilds and re-serializes the WorkItemFilters proto every time the listen loop restarts (and could do so repeatedly on transient disconnects). Since workItemFilter is immutable for the lifetime of the worker, consider precomputing and storing the proto WorkItemFilters once (e.g., in the constructor) to reduce allocations and CPU in retry loops.
| private GetWorkItemsRequest buildGetWorkItemsRequest() { | |
| GetWorkItemsRequest.Builder builder = GetWorkItemsRequest.newBuilder(); | |
| if (this.workItemFilter != null) { | |
| builder.setWorkItemFilters(toProtoWorkItemFilters(this.workItemFilter)); | |
| /** | |
| * Cached proto representation of {@link #workItemFilter} to avoid rebuilding it on every retry. | |
| * This is lazily initialized since {@code workItemFilter} is immutable for the lifetime of the worker. | |
| */ | |
| private volatile WorkItemFilters cachedWorkItemFilters; | |
| private GetWorkItemsRequest buildGetWorkItemsRequest() { | |
| GetWorkItemsRequest.Builder builder = GetWorkItemsRequest.newBuilder(); | |
| if (this.workItemFilter != null) { | |
| // Lazily compute and cache the proto WorkItemFilters since workItemFilter is immutable | |
| WorkItemFilters filters = this.cachedWorkItemFilters; | |
| if (filters == null) { | |
| synchronized (this) { | |
| filters = this.cachedWorkItemFilters; | |
| if (filters == null) { | |
| filters = toProtoWorkItemFilters(this.workItemFilter); | |
| this.cachedWorkItemFilters = filters; | |
| } | |
| } | |
| } | |
| builder.setWorkItemFilters(filters); |
| List<String> versionsCopy = versions != null | ||
| ? Collections.unmodifiableList(new ArrayList<String>(versions)) | ||
| : Collections.<String>emptyList(); |
There was a problem hiding this comment.
addOrchestration(name, versions) copies the provided versions list but doesn't validate its contents. If versions contains any null elements, toProtoWorkItemFilters will later fail when calling addAllVersions(...) on the protobuf builder (protobuf repeated string fields don't accept null entries). Consider rejecting null version entries (and optionally empty strings) up-front with an IllegalArgumentException.
| List<String> versionsCopy = versions != null | |
| ? Collections.unmodifiableList(new ArrayList<String>(versions)) | |
| : Collections.<String>emptyList(); | |
| List<String> versionsCopy; | |
| if (versions == null) { | |
| versionsCopy = Collections.<String>emptyList(); | |
| } else { | |
| List<String> cleanedVersions = new ArrayList<String>(versions.size()); | |
| for (String version : versions) { | |
| if (version == null || version.isEmpty()) { | |
| throw new IllegalArgumentException("Orchestration filter versions must not contain null or empty entries."); | |
| } | |
| cleanedVersions.add(version); | |
| } | |
| versionsCopy = Collections.unmodifiableList(cleanedVersions); | |
| } |
| public Builder addActivity(String name, List<String> versions) { | ||
| if (name == null || name.isEmpty()) { | ||
| throw new IllegalArgumentException("Activity filter name must not be null or empty."); | ||
| } | ||
| List<String> versionsCopy = versions != null | ||
| ? Collections.unmodifiableList(new ArrayList<String>(versions)) | ||
| : Collections.<String>emptyList(); | ||
| this.activities.add(new ActivityFilter(name, versionsCopy)); | ||
| return this; |
There was a problem hiding this comment.
addActivity(name, versions) doesn't validate the contents of the versions list. If callers pass a list containing null elements, proto conversion via addAllVersions(...) will throw at runtime. Add input validation to reject null entries (and optionally empty strings) before storing the filter.
| WorkItemFilter.Builder builder = WorkItemFilter.newBuilder(); | ||
| for (String name : this.orchestrationFactories.keySet()) { | ||
| builder.addOrchestration(name, versions); | ||
| } | ||
| for (String name : this.activityFactories.keySet()) { | ||
| builder.addActivity(name, versions); | ||
| } |
There was a problem hiding this comment.
buildAutoWorkItemFilter() iterates over HashMap.keySet(), which has undefined iteration order. This makes the generated filter list ordering nondeterministic, which can complicate debugging/tests and can cause unnecessary request churn if the backend treats ordering as significant. Consider iterating over a sorted list of keys (e.g., copy + Collections.sort) to produce a stable order.
Issue describing the changes in this PR
Adding work items filter support for the Java SDK.
resolves #issue_for_this_pr
Pull request checklist
CHANGELOG.md