Repository navigation
[Dataflow Java] Extend work item lease while DoFn.setup runs in batch worker - #40850
Draft
mxtymoshyk wants to merge 3 commits into
Draft
mxtymoshyk wants to merge 3 commits into
mxtymoshyk wants to merge 3 commits into
Conversation
… worker Batch work items failed when DoFn.setup took longer than the 3 minute lease, because progress reporting started only after the executor was created. Start reporting first, send lease-only updates until the executor exists, and apply a service abort received during setup once the executor is set. Fixes apache#34206
The lease is now extended during setup, so a stuck setup no longer fails the work item on its own. Log a warning after 3 minutes and every 5 minutes after that while the executor is still being created, so it shows in the worker log. Skip worker.abort() when the progress thread is interrupted before the executor exists, which would throw a NullPointerException. Reword the slow setup warning, which no longer leads to lease expiry. Addresses apache#34206
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #40850 +/- ##
=============================================
+ Coverage 0 76.00% +76.00%
- Complexity 0 2283 +2283
=============================================
Files 0 259 +259
Lines 0 14421 +14421
Branches 0 1485 +1485
=============================================
+ Hits 0 10960 +10960
- Misses 0 2767 +2767
- Partials 0 694 +694
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #34206.
Opened as a draft to get feedback on the approach.
Problem
In the legacy batch worker,
BatchDataflowWorker.doWorkbuilds the executor withmapTaskExecutorFactory.create(), which runs everyDoFn.setup. Progress reporting starts only after that, so nothing extends the lease while setup runs. If setup takes longer than the 3 minute lease, the service fails the work item, and after 4 failures the job fails.Change
BatchDataflowWorker: start the progress updater beforecreate(), then hand it the executor. Ifcreate()throws, stop the updater before reporting the error.WorkItemStatusClient: an update sent beforesetWorkercarries only the requested lease, with no progress, counters or metrics. ThecheckStatethat rejected it is removed.DataflowWorkProgressUpdater:setWorker.MapTaskExecutorkeeps the abort flag, so the read loop stops before the first record and the work item is reported as failed.Work item ... is still creating its executor after N seconds. The existing setup warning inDoFnInstanceManagersonly fires once setup returns, so without this a stuck setup would log nothing.WorkProgressUpdater: if the reporting thread is interrupted before the executor exists, skipworker.abort()instead of throwing aNullPointerException.DoFnInstanceManagers: the slow setup warning no longer says the lease will expire and fail the job. It now says setup runs again on each new worker and for each thread that needs its own instance.Tests
BatchDataflowWorkerTest.testProgressReportedWhileExecutorIsBeingCreated: blockscreate()until a status update arrives. It times out without the fix and passes with it.DataflowWorkProgressUpdaterTest.workProgressAbortBeforeWorkerIsSetAbortsItOnceSetDataflowWorkProgressUpdaterTest.workProgressWarnsWhileExecutorCreationIsSlowWorkItemStatusClientTest.reportUpdateBeforeSetWorkerOnlyExtendsLeasereplaces the test that expected the oldIllegalStateException.:runners:google-cloud-dataflow-java:worker:checkpasses. The first 3 new tests passed 20 runs in a row.Checked on Dataflow
All runs used the legacy worker (
disable_runner_v2,--dataflowWorkerJar) withCreate.of(1, 2, 3)into a ParDo whose@Setupsleeps.Service asked worker to abort with status: {"code":1}, and the work item was retried. The job still finished, because the retry ran on the same worker and reused the DoFn that had already been set up. A job fails when the retries also have to run setup, which is what the issue reports.Finished processing stage F20 with 0 errors in 303.569 seconds). The service accepted the lease-only updates sent during setup.--numberOfWorkerHarnessThreads=4: three setups ran at the same time on one worker. Each logged the new warning once at about 182 seconds and finished in about 300 seconds, with no abort.Cancelled44 seconds later.Design choices
execute()has no cap either, and a hungprocessElementrenews its lease forever today. A cap would also not stop the stuck thread; the service would retry the item while the original setup keeps running. A hung setup used to fail the job after about 12 minutes and now runs until someone cancels it, so the repeating warning is there to make it visible.create()returns, not sooner. Interrupting user code in setup can leave a half-built client in the pooled DoFn that later work items reuse.MapTaskExecutor.abort()does not interrupt the execution thread either.