Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c831c33
Support logging the key during a KeyCommitTooLarge if EnableHotKeyLog…
rwiggles Jul 14, 2026
986fae8
Merge branch 'apache:master' into master
rwiggles Jul 14, 2026
25d7bbc
Update runners/google-cloud-dataflow-java/worker/src/main/java/org/ap…
rwiggles Jul 14, 2026
2513ffe
Update runners/google-cloud-dataflow-java/worker/src/main/java/org/ap…
rwiggles Jul 14, 2026
647a815
Update runners/google-cloud-dataflow-java/worker/src/test/java/org/ap…
rwiggles Jul 14, 2026
369aff8
gemini review responses
rwiggles Jul 14, 2026
8f55913
Merge branch 'apache:master' into master
rwiggles Jul 14, 2026
15751e2
Fix imports
rwiggles Jul 14, 2026
d3a4d1c
one more
rwiggles Jul 14, 2026
d5babb0
one more attempt
rwiggles Jul 15, 2026
9f611b5
one more attempt
rwiggles Jul 15, 2026
a5bd7d0
formatting fix
rwiggles Jul 15, 2026
2655ca5
Bump actions/checkout from 6 to 7 (#39335)
dependabot[bot] Jul 15, 2026
c3dfad9
Bump cloud.google.com/go/datastore from 1.24.0 to 1.25.0 in /sdks (#3…
dependabot[bot] Jul 15, 2026
6622497
Bump github.com/aws/aws-sdk-go-v2/feature/s3/manager in /sdks (#39334)
dependabot[bot] Jul 15, 2026
4e1732b
Fix DataflowV1 test failure by fixing getSimpleName access (#39330)
Abacn Jul 15, 2026
2bea70b
add jdkAddOpenModules for Dataflow V2 (#39306)
aIbrahiim Jul 15, 2026
1e6b61b
Add Spark JVM --add-opens for (Nexmark, TPC-DS, PortableJar) (#39337)
aIbrahiim Jul 15, 2026
163cd12
add Spark job-server --add-opens (#39339)
aIbrahiim Jul 15, 2026
dca9622
fix: add retries and query parameter encoding for GitHub API requests…
raman118 Jul 1, 2026
7b88d16
fix: add Apache license header to test_sending.py
raman118 Jul 1, 2026
5939496
Move validation to StreamingModeExecutionContext
rwiggles Jul 17, 2026
a3b7163
remove unused import
rwiggles Jul 17, 2026
c31b3e9
Merge branch 'master' into master
rwiggles Jul 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@
import org.apache.beam.runners.dataflow.worker.counters.NameContext;
import org.apache.beam.runners.dataflow.worker.profiler.ScopedProfiler.ProfileScope;
import org.apache.beam.runners.dataflow.worker.streaming.BoundedQueueExecutorWorkHandle;
import org.apache.beam.runners.dataflow.worker.streaming.KeyCommitTooLargeException;
import org.apache.beam.runners.dataflow.worker.streaming.Watermarks;
import org.apache.beam.runners.dataflow.worker.streaming.Work;
import org.apache.beam.runners.dataflow.worker.streaming.config.StreamingGlobalConfig;
import org.apache.beam.runners.dataflow.worker.streaming.config.StreamingGlobalConfigHandle;
import org.apache.beam.runners.dataflow.worker.streaming.harness.StreamingCounters;
import org.apache.beam.runners.dataflow.worker.streaming.sideinput.SideInput;
import org.apache.beam.runners.dataflow.worker.streaming.sideinput.SideInputState;
import org.apache.beam.runners.dataflow.worker.streaming.sideinput.SideInputStateFetcher;
Expand All @@ -77,6 +79,7 @@
import org.apache.beam.runners.dataflow.worker.windmill.state.WindmillTagEncodingV1;
import org.apache.beam.runners.dataflow.worker.windmill.state.WindmillTagEncodingV2;
import org.apache.beam.runners.dataflow.worker.windmill.state.WindmillTimerData;
import org.apache.beam.runners.dataflow.worker.windmill.work.processing.failures.FailureTracker;
import org.apache.beam.sdk.annotations.Internal;
import org.apache.beam.sdk.coders.Coder;
import org.apache.beam.sdk.coders.CoderException;
Expand Down Expand Up @@ -177,6 +180,9 @@ public class StreamingModeExecutionContext
private final HotKeyLogger hotKeyLogger;
private final boolean hotKeyLoggingEnabled;
private final String stepName;
private final String systemName;
private final StreamingCounters streamingCounters;
private final FailureTracker failureTracker;
private @Nullable Coder<?> keyCoder;

// Key switch listener to delegate MDC logging context and thread name updates
Expand Down Expand Up @@ -212,6 +218,9 @@ public StreamingModeExecutionContext(
HotKeyLogger hotKeyLogger,
boolean hotKeyLoggingEnabled,
String stepName,
String systemName,
StreamingCounters streamingCounters,
FailureTracker failureTracker,
String sourceBytesProcessCounterName,
SideInputStateFetcherFactory sideInputStateFetcherFactory) {
super(
Expand All @@ -231,6 +240,9 @@ public StreamingModeExecutionContext(
this.hotKeyLogger = checkNotNull(hotKeyLogger);
this.hotKeyLoggingEnabled = hotKeyLoggingEnabled;
this.stepName = checkNotNull(stepName);
this.systemName = checkNotNull(systemName);
this.streamingCounters = checkNotNull(streamingCounters);
this.failureTracker = checkNotNull(failureTracker);
this.sourceBytesProcessCounterName = checkNotNull(sourceBytesProcessCounterName);
this.sideInputStateFetcherFactory = sideInputStateFetcherFactory;
StreamingGlobalConfig config = globalConfigHandle.getConfig();
Expand Down Expand Up @@ -669,6 +681,52 @@ private void flushStateInternal() {

getOutputBuilder()
.setSourceBytesProcessed(computeSourceBytesProcessed(sourceBytesProcessCounterName));

validateCommitRequestSize();
}

private void validateCommitRequestSize() {
Windmill.WorkItemCommitRequest.Builder currentBuilder = getOutputBuilder();
Work currentWork = getWork();
long byteLimit = operationalLimits.getMaxWorkItemCommitBytes();
Windmill.WorkItemCommitRequest commitRequest = currentBuilder.build();
int commitSize = commitRequest.getSerializedSize();
int estimatedCommitSize = commitSize < 0 ? Integer.MAX_VALUE : commitSize;

// Detect overflow of integer serialized size or if the byte limit was exceeded.
// Commit is too large if overflow has occurred or the commitSize has exceeded the allowed
// commit byte limit.
streamingCounters.windmillMaxObservedWorkItemCommitBytes().addValue(estimatedCommitSize);
if (commitSize >= 0 && commitSize < byteLimit) {
return;
}

KeyCommitTooLargeException e =
KeyCommitTooLargeException.causedBy(
systemName, byteLimit, commitRequest, key, hotKeyLoggingEnabled);
failureTracker.trackFailure(systemName, currentWork.getWorkItem(), e);
LOG.error("{}", e.toString());

// Drop the current request in favor of a new, minimal one requesting truncation.
// Messages, timers, counters, and other commit content will not be used by the service
// so, we're purposefully dropping them here
Windmill.WorkItemCommitRequest.Builder truncationBuilder =
buildWorkItemTruncationRequestBuilder(currentWork, estimatedCommitSize);
for (int i = 0; i < outputBuilders.size(); i++) {

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.

You can do

this.outputBuilder.clear();
this.outputBuilder.mergeFrom(truncationBuilder);

if (outputBuilders.get(i) == currentBuilder) {
outputBuilders.set(i, truncationBuilder);
break;
}
}
this.outputBuilder = truncationBuilder;
}

private Windmill.WorkItemCommitRequest.Builder buildWorkItemTruncationRequestBuilder(
Work work, int estimatedCommitSize) {
Windmill.WorkItemCommitRequest.Builder outputBuilder = createOutputBuilder(work);
outputBuilder.setExceedsMaxWorkItemCommitBytes(true);
outputBuilder.setEstimatedWorkItemCommitBytes(estimatedCommitSize);
return outputBuilder;
}

private final long computeSourceBytesProcessed(String sourceBytesCounterName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,38 @@
package org.apache.beam.runners.dataflow.worker.streaming;

import org.apache.beam.runners.dataflow.worker.windmill.Windmill;
import org.checkerframework.checker.nullness.qual.Nullable;

public final class KeyCommitTooLargeException extends Exception {

public static KeyCommitTooLargeException causedBy(
String computationId, long byteLimit, Windmill.WorkItemCommitRequest request) {
String stageName, long byteLimit, Windmill.WorkItemCommitRequest request) {
return causedBy(stageName, byteLimit, request, null, false);
}

public static KeyCommitTooLargeException causedBy(
String stageName,
long byteLimit,
Windmill.WorkItemCommitRequest request,
boolean hotKeyLoggingEnabled) {
return causedBy(stageName, byteLimit, request, null, hotKeyLoggingEnabled);
}
Comment on lines 25 to +36

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.

these look unused, remove?


public static KeyCommitTooLargeException causedBy(
String stageName,
long byteLimit,
Windmill.WorkItemCommitRequest request,
@Nullable Object decodedKey,
boolean hotKeyLoggingEnabled) {
StringBuilder message = new StringBuilder();
message.append("Commit request for stage ");
message.append(computationId);
message.append(stageName);
message.append(" and sharding key ");
message.append(request.getShardingKey());
message.append(Long.toUnsignedString(request.getShardingKey()));
if (decodedKey != null && hotKeyLoggingEnabled) {
message.append(" and key ");
message.append(decodedKey);
}
if (request.getSerializedSize() > 0) {
message.append(
" has size "
Expand All @@ -38,9 +60,8 @@ public static KeyCommitTooLargeException causedBy(
message.append(" is larger than 2GB and cannot be processed");
}
message.append(
". This may be caused by grouping a very "
+ "large amount of data in a single window without using Combine,"
+ " or by producing a large amount of data from a single input element."
". This may be caused by grouping a very large amount of data in a single window without"
+ " using Combine, or by producing a large amount of data from a single input element."
+ " See https://cloud.google.com/dataflow/docs/guides/common-errors#key-commit-too-large-exception.");
return new KeyCommitTooLargeException(message.toString());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@
import org.apache.beam.runners.dataflow.worker.streaming.ComputationWorkExecutor;
import org.apache.beam.runners.dataflow.worker.streaming.StageInfo;
import org.apache.beam.runners.dataflow.worker.streaming.config.StreamingGlobalConfigHandle;
import org.apache.beam.runners.dataflow.worker.streaming.harness.StreamingCounters;
import org.apache.beam.runners.dataflow.worker.streaming.sideinput.SideInputStateFetcherFactory;
import org.apache.beam.runners.dataflow.worker.util.common.worker.MapTaskExecutor;
import org.apache.beam.runners.dataflow.worker.util.common.worker.OutputObjectAndByteCounter;
import org.apache.beam.runners.dataflow.worker.util.common.worker.ReadOperation;
import org.apache.beam.runners.dataflow.worker.windmill.state.WindmillStateCache;
import org.apache.beam.runners.dataflow.worker.windmill.work.processing.failures.FailureTracker;
import org.apache.beam.sdk.coders.Coder;
import org.apache.beam.sdk.coders.KvCoder;
import org.apache.beam.sdk.fn.IdGenerator;
Expand Down Expand Up @@ -84,6 +86,8 @@ final class ComputationWorkExecutorFactory {
private final SinkRegistry sinkRegistry;
private final DataflowExecutionStateSampler sampler;
private final CounterSet pendingDeltaCounters;
private final StreamingCounters streamingCounters;
private final FailureTracker failureTracker;

/**
* Function which converts map tasks to their network representation for execution.
Expand All @@ -108,7 +112,8 @@ final class ComputationWorkExecutorFactory {
ReaderCache readerCache,
Function<String, WindmillStateCache.ForComputation> stateCacheFactory,
DataflowExecutionStateSampler sampler,
CounterSet pendingDeltaCounters,
StreamingCounters streamingCounters,
FailureTracker failureTracker,
IdGenerator idGenerator,
StreamingGlobalConfigHandle globalConfigHandle,
HotKeyLogger hotKeyLogger,
Expand All @@ -122,7 +127,9 @@ final class ComputationWorkExecutorFactory {
this.readerRegistry = ReaderRegistry.defaultRegistry();
this.sinkRegistry = SinkRegistry.defaultRegistry();
this.sampler = sampler;
this.pendingDeltaCounters = pendingDeltaCounters;
this.streamingCounters = streamingCounters;
this.failureTracker = failureTracker;
this.pendingDeltaCounters = streamingCounters.pendingDeltaCounters();
this.mapTaskToNetwork = new MapTaskToNetworkFunction(idGenerator);
this.maxSinkBytes =
hasExperiment(options, DISABLE_SINK_BYTE_LIMIT_EXPERIMENT)
Expand Down Expand Up @@ -286,6 +293,9 @@ private StreamingModeExecutionContext createExecutionContext(
hotKeyLogger,
hotKeyLoggingEnabled,
stepName,
stageInfo.systemName(),
streamingCounters,
failureTracker,
computationState.sourceBytesProcessCounterName(),
sideInputStateFetcherFactory);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
import org.apache.beam.runners.dataflow.worker.streaming.ComputationState;
import org.apache.beam.runners.dataflow.worker.streaming.ComputationWorkExecutor;
import org.apache.beam.runners.dataflow.worker.streaming.ExecutableWork;
import org.apache.beam.runners.dataflow.worker.streaming.KeyCommitTooLargeException;
import org.apache.beam.runners.dataflow.worker.streaming.StageInfo;
import org.apache.beam.runners.dataflow.worker.streaming.Watermarks;
import org.apache.beam.runners.dataflow.worker.streaming.Work;
Expand Down Expand Up @@ -81,36 +80,30 @@ public class StreamingWorkScheduler {

private final Supplier<Instant> clock;
private final ComputationWorkExecutorFactory computationWorkExecutorFactory;
private final FailureTracker failureTracker;
private final WorkFailureProcessor workFailureProcessor;
private final StreamingCommitFinalizer commitFinalizer;
private final StreamingCounters streamingCounters;
private final ConcurrentMap<String, StageInfo> stageInfoMap;
private final DataflowExecutionStateSampler sampler;
private final StreamingGlobalConfigHandle globalConfigHandle;
private final BoundedQueueExecutor workExecutor;

public StreamingWorkScheduler(
Supplier<Instant> clock,
BoundedQueueExecutor workExecutor,
ComputationWorkExecutorFactory computationWorkExecutorFactory,
FailureTracker failureTracker,
WorkFailureProcessor workFailureProcessor,
StreamingCommitFinalizer commitFinalizer,
StreamingCounters streamingCounters,
ConcurrentMap<String, StageInfo> stageInfoMap,
DataflowExecutionStateSampler sampler,
StreamingGlobalConfigHandle globalConfigHandle) {
DataflowExecutionStateSampler sampler) {
this.clock = clock;
this.workExecutor = workExecutor;
this.computationWorkExecutorFactory = computationWorkExecutorFactory;
this.failureTracker = failureTracker;
this.workFailureProcessor = workFailureProcessor;
this.commitFinalizer = commitFinalizer;
this.streamingCounters = streamingCounters;
this.stageInfoMap = stageInfoMap;
this.sampler = sampler;
this.globalConfigHandle = globalConfigHandle;
}

public static StreamingWorkScheduler create(
Expand Down Expand Up @@ -139,7 +132,8 @@ public static StreamingWorkScheduler create(
readerCache,
stateCacheFactory,
sampler,
streamingCounters.pendingDeltaCounters(),
streamingCounters,
failureTracker,
idGenerator,
globalConfigHandle,
hotKeyLogger,
Expand All @@ -149,13 +143,11 @@ public static StreamingWorkScheduler create(
clock,
workExecutor,
computationWorkExecutorFactory,
failureTracker,
workFailureProcessor,
StreamingCommitFinalizer.create(workExecutor, commitFinalizerCleanupExecutor),
streamingCounters,
stageInfoMap,
sampler,
globalConfigHandle);
sampler);
}

private static long computeShuffleBytesRead(Windmill.WorkItem workItem) {
Expand All @@ -175,14 +167,6 @@ private static Windmill.WorkItemCommitRequest.Builder initializeOutputBuilder(
.setCacheToken(workItem.getCacheToken());
}

private static Windmill.WorkItemCommitRequest buildWorkItemTruncationRequest(
ByteString key, Windmill.WorkItem workItem, int estimatedCommitSize) {
Windmill.WorkItemCommitRequest.Builder outputBuilder = initializeOutputBuilder(key, workItem);
outputBuilder.setExceedsMaxWorkItemCommitBytes(true);
outputBuilder.setEstimatedWorkItemCommitBytes(estimatedCommitSize);
return outputBuilder.build();
}

/** Sets the stage name and workId of the Thread executing the {@link Work} for logging. */
private static void setUpWorkLoggingContext(String workLatencyTrackingId, String computationId) {
setLoggingContextWorkId(workLatencyTrackingId);
Expand Down Expand Up @@ -305,33 +289,6 @@ private void processWork(
}
}

private Windmill.WorkItemCommitRequest validateCommitRequestSize(
Windmill.WorkItemCommitRequest commitRequest,
String computationId,
Windmill.WorkItem workItem) {
long byteLimit = globalConfigHandle.getConfig().operationalLimits().getMaxWorkItemCommitBytes();
int commitSize = commitRequest.getSerializedSize();
int estimatedCommitSize = commitSize < 0 ? Integer.MAX_VALUE : commitSize;

// Detect overflow of integer serialized size or if the byte limit was exceeded.
// Commit is too large if overflow has occurred or the commitSize has exceeded the allowed
// commit byte limit.
streamingCounters.windmillMaxObservedWorkItemCommitBytes().addValue(estimatedCommitSize);
if (commitSize >= 0 && commitSize < byteLimit) {
return commitRequest;
}

KeyCommitTooLargeException e =
KeyCommitTooLargeException.causedBy(computationId, byteLimit, commitRequest);
failureTracker.trackFailure(computationId, workItem, e);
LOG.error("{}", e.toString());

// Drop the current request in favor of a new, minimal one requesting truncation.
// Messages, timers, counters, and other commit content will not be used by the service
// so, we're purposefully dropping them here
return buildWorkItemTruncationRequest(workItem.getKey(), workItem, estimatedCommitSize);
}

private void recordProcessingStats(
List<Work> workBatch,
List<Windmill.WorkItemCommitRequest> workItemCommits,
Expand Down Expand Up @@ -448,17 +405,13 @@ private void commitWorkBatch(

private void commitSingleKeyWork(
ComputationState computationState, Work work, Windmill.WorkItemCommitRequest commitRequest) {
// Validate the commit request, possibly requesting truncation if the commitSize is too large.
Windmill.WorkItemCommitRequest validatedCommitRequest =
validateCommitRequestSize(
commitRequest, computationState.getComputationId(), work.getWorkItem());
work.setState(Work.State.COMMIT_QUEUED);
validatedCommitRequest =
validatedCommitRequest
Windmill.WorkItemCommitRequest commitRequestWithAttributions =
commitRequest
.toBuilder()
.addAllPerWorkItemLatencyAttributions(work.getLatencyAttributions(sampler))
.build();
work.queueCommit(validatedCommitRequest, computationState);
work.queueCommit(commitRequestWithAttributions, computationState);
}

private void recordProcessingTime(
Expand Down
Loading
Loading