Skip to content

Commit 6bdfcb3

Browse files
LEEKYEtvalentyn
andauthored
update description and logs for timeout (#36003)
* update description and logs for timeout * minor fix * go format fix * fix * Update changes.md * Update the flag description in release note * remove whitespace * Update CHANGES.md slightly updated the description * Update CHANGES.md --------- Co-authored-by: tvalentyn <tvalentyn@users.noreply.github.com>
1 parent 4bb6e5a commit 6bdfcb3

8 files changed

Lines changed: 30 additions & 20 deletions

File tree

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@
8181
Beam now supports data enrichment capabilities using SQL databases, with built-in support for:
8282
- Managed PostgreSQL, MySQL, and Microsoft SQL Server instances on CloudSQL
8383
- Unmanaged SQL database instances not hosted on CloudSQL (e.g., self-hosted or on-premises databases)
84+
* Added a pipeline option to specify the processing timeout for a single element by any PTransform (Java/Python/Go) ([#35174](https://github.com/apache/beam/issues/35174)).
85+
- When specified, the SDK harness automatically restarts if an element takes too long to process. Beam runner may then retry processing of the same work item.
86+
- Use the `--element_processing_timeout_minutes` option to reduce the chance of having stalled pipelines due to unexpected cases of slow processing, where slowness might not happen again if processing of the same element is retried.
8487

8588
## Breaking Changes
8689

sdks/go/pkg/beam/core/metrics/sampler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ func (s *StateSampler) Sample(ctx context.Context, t time.Duration) error {
6363
}
6464

6565
if s.millisSinceLastTransition > s.nextLogTime {
66-
log.Infof(ctx, "Operation ongoing in transform %v for at least %v ms without outputting or completing in state %v", ps.pid, s.millisSinceLastTransition, getState(ps.state))
66+
log.Infof(ctx, "Operation ongoing in transform %v for at least %v without outputting or completing in state %v", ps.pid, s.millisSinceLastTransition, getState(ps.state))
6767
s.nextLogTime += s.logInterval
6868
}
6969
if s.restartLullTimeout > 0 && s.millisSinceLastTransition > s.restartLullTimeout {
70-
return errors.Errorf("Operation ongoing in transform %v for at least %v ms without outputting or completing in state %v, the SDK harness will be terminated and restarted", ps.pid, s.millisSinceLastTransition, getState(ps.state))
70+
return errors.Errorf("Processing of an element in transform %v has exceeded the specified timeout of %v without outputting or completing in state %v, SDK harness will be terminated", ps.pid, s.restartLullTimeout, getState(ps.state))
7171
}
7272
}
7373
return nil

sdks/go/pkg/beam/core/metrics/sampler_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ func TestSamplerWithRestartLullTimeout(t *testing.T) {
176176
t.Errorf("s.sample(bctx, interval) = %v, want %v", got, want)
177177
}
178178
err := s.Sample(bctx, interval)
179-
if err == nil || !strings.Contains(err.Error(), "the SDK harness will be terminated and restarted") {
180-
t.Errorf("s.sample(bctx, interval) = %v, want %v", err, "the SDK harness will be terminated and restarted")
179+
if err == nil || !strings.Contains(err.Error(), "SDK harness will be terminated") {
180+
t.Errorf("s.sample(bctx, interval) = %v, want %v", err, "SDK harness will be terminated")
181181
}
182182
}
183183

sdks/go/pkg/beam/options/jobopts/options.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ var (
102102
ResourceHints stringSlice
103103

104104
// ElementProcessingTimeout flag to set the timeout for processing an element in a PTransform operation. If set to -1, there is no timeout.
105-
ElementProcessingTimeout = flag.Duration("element_processing_timeout", -1, "The timeout for processing an element in a PTransform operation. If set to -1, there is no timeout.")
105+
ElementProcessingTimeout = flag.Duration("element_processing_timeout", -1,
106+
"The time limit (in minutes) for any PTransform to finish processing a single element. If exceeded, "+
107+
"the SDK worker process self-terminates and processing may be restarted by a runner. There is no time limit if the value is set to -1.")
106108
)
107109

108110
type missingFlagError error

sdks/java/core/src/main/java/org/apache/beam/sdk/options/SdkHarnessOptions.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,8 +433,9 @@ public Duration create(PipelineOptions options) {
433433
* signaling the runner harness to restart the SDK worker.
434434
*/
435435
@Description(
436-
"The time limit (minute) that an SDK worker allows for a PTransform operation "
437-
+ "before signaling the runner harness to restart the SDK worker. There is no time limit if the value is set to 0.")
436+
"The time limit (in minutes) for any PTransform to finish processing a single element."
437+
+ " If exceeded, the SDK worker process self-terminates and processing may be restarted by a runner."
438+
+ " There is no time limit if the value is set to 0.")
438439
@NonNegative
439440
int getElementProcessingTimeoutMinutes();
440441

sdks/java/harness/src/main/java/org/apache/beam/fn/harness/control/ExecutionStateSampler.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -400,25 +400,26 @@ private Optional<String> takeSample(long currentTimeMillis, long millisSinceLast
400400
if (thread == null) {
401401
timeoutMessage =
402402
String.format(
403-
"Operation ongoing in bundle %s for at least %s without outputting "
404-
+ "or completing (stack trace unable to be generated). The SDK worker will restart.",
403+
"Processing of an element in bundle %s has exceeded the specified timeout of %s "
404+
+ "(stack trace unable to be generated). The SDK worker will be terminated.",
405405
processBundleId.get(),
406406
DURATION_FORMATTER.print(
407407
Duration.millis(userSpecifiedLullTimeMsForRestart).toPeriod()));
408408
} else if (currentExecutionState == null) {
409409
timeoutMessage =
410410
String.format(
411-
"Operation ongoing in bundle %s for at least %s without outputting "
412-
+ "or completing:%n at %s. The SDK worker will restart.",
411+
"Processing of an element in bundle %s has exceeded the specified timeout of %s "
412+
+ "without outputting or completing:%n at %s. The SDK worker will be terminated.",
413413
processBundleId.get(),
414414
DURATION_FORMATTER.print(
415415
Duration.millis(userSpecifiedLullTimeMsForRestart).toPeriod()),
416416
Joiner.on("\n at ").join(thread.getStackTrace()));
417417
} else {
418418
timeoutMessage =
419419
String.format(
420-
"Operation ongoing in bundle %s for PTransform{id=%s, name=%s, state=%s} "
421-
+ "for at least %s without outputting or completing:%n at %s. The SDK worker will restart.",
420+
"Processing of an element in bundle %s for PTransform{id=%s, name=%s, state=%s} "
421+
+ "has exceeded the specified timeout of %s without outputting or completing:%n at %s. "
422+
+ "The SDK worker will be terminated.",
422423
processBundleId.get(),
423424
currentExecutionState.ptransformId,
424425
currentExecutionState.ptransformUniqueName,

sdks/python/apache_beam/options/pipeline_options.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,9 +1461,10 @@ def _add_argparse_args(cls, parser):
14611461
type=int,
14621462
default=None,
14631463
help=(
1464-
'The time limit (in minutes) that an SDK worker allows for a'
1465-
' PTransform operation to process one element before signaling'
1466-
' the runner harness to restart the SDK worker.'))
1464+
'The time limit (in minutes) for any PTransform to finish '
1465+
'processing a single element. If exceeded, the SDK worker '
1466+
'process self-terminates and processing may be restarted '
1467+
'by a runner.'))
14671468

14681469
def validate(self, validator):
14691470
errors = []

sdks/python/apache_beam/runners/worker/worker_status.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ def __init__(
185185
self._status_channel)
186186
self._responses = queue.Queue()
187187
self.log_lull_timeout_ns = log_lull_timeout_ns
188-
if element_processing_timeout_minutes:
188+
if (element_processing_timeout_minutes and
189+
element_processing_timeout_minutes > 0):
189190
self._element_processing_timeout_ns = (
190191
element_processing_timeout_minutes * 60 * 1e9)
191192
else:
@@ -285,12 +286,13 @@ def _log_lull_sampler_info(self, sampler_info, instruction):
285286
if timeout_exceeded:
286287
_LOGGER.error(
287288
(
288-
'Operation ongoing in bundle %s%s for at least %.2f seconds'
289-
' without outputting or completing.\n'
289+
'Processing of an element in bundle %s%s has exceeded the '
290+
'specified timeout of %.2f minutes. SDK harness will be '
291+
'terminated.\n'
290292
'Current Traceback:\n%s'),
291293
instruction,
292294
step_name_log,
293-
lull_seconds,
295+
self._element_processing_timeout_ns / 1e9 / 60,
294296
stack_trace,
295297
)
296298
from apache_beam.runners.worker.sdk_worker_main import terminate_sdk_harness

0 commit comments

Comments
 (0)