Skip to content

Isolate health-report probes so a slow builder can't starve others - #1018

Merged
ekharkunov merged 2 commits into
devfrom
fix/health-report-probe-starvation
Aug 12, 2026
Merged

Isolate health-report probes so a slow builder can't starve others#1018
ekharkunov merged 2 commits into
devfrom
fix/health-report-probe-starvation

Conversation

@ekharkunov

@ekharkunov ekharkunov commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

collectHealthReport() fired every builder probe via CompletableFuture.supplyAsync without an executor, so they shared the common ForkJoinPool while making a blocking HTTP call. completeOnTimeout() completes the future but does not cancel the running task, so a slow builder held its pool thread for the whole socket lifetime. On a few-core host a slow node could starve a healthy node's probe, which was then mis-reported as Unreachable.

Run each probe on a dedicated pool sized to the number of builders, and bound the blocking execute() with a per-request RequestConfig timeout so a stuck builder releases its worker near the timeout. Add a regression test pairing a fast node with a slow one and asserting the fast node stays Operational.

collectHealthReport fired every builder probe via CompletableFuture.supplyAsync
without an executor, so they shared the common ForkJoinPool while making a
blocking HTTP call. completeOnTimeout completes the future but does not cancel
the running task, so a slow builder held its pool thread for the whole socket
lifetime. On a few-core host a slow node could starve a healthy node's probe,
which was then mis-reported as Unreachable -- the flaky
testRemoteNodesNotFullyOperational failure on CI.

Run each probe on a dedicated pool sized to the number of builders, and bound
the blocking execute() with a per-request RequestConfig timeout so a stuck
builder releases its worker near the timeout. Add a regression test pairing a
fast node with a slow one and asserting the fast node stays Operational.
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

Summary - Extender code coverage report

Summary
Generated on: 08/12/2026 - 12:48:58
Coverage date: 08/12/2026 - 12:48:28
Parser: JaCoCo
Assemblies: 13
Classes: 83
Files: 83
Line coverage: 39.5% (2357 of 5963)
Covered lines: 2357
Uncovered lines: 3606
Coverable lines: 5963
Total lines: 12219
Branch coverage: 41.9% (989 of 2356)
Covered branches: 989
Total branches: 2356
Method coverage: Feature is only available for sponsors
Tag: 232_31598099577

Coverage

com/defold/extender - 29.5%
Name Line Branch
com/defold/extender 29.5% 34.4%
com/defold/extender/AppManifestConfiguration 100%
com/defold/extender/AppManifestPlatformConfig 100%
com/defold/extender/AsyncBuilder 0% 0%
com/defold/extender/BuilderConstants 80%
com/defold/extender/Configuration 100%
com/defold/extender/Extender 12.5% 11.2%
com/defold/extender/ExtenderApplication 0%
com/defold/extender/ExtenderBuildState 62.5% 57.1%
com/defold/extender/ExtenderConst 0%
com/defold/extender/ExtenderController 17.6% 21.9%
com/defold/extender/ExtenderException 85.7%
com/defold/extender/ExtenderUtil 67% 58%
com/defold/extender/ExtenderYamlSafeConstructor 100%
com/defold/extender/ExtensionManifestValidator 94.6% 86.3%
com/defold/extender/ManifestConfiguration 100%
com/defold/extender/ManifestPlatformConfig 100%
com/defold/extender/PlatformConfig 100%
com/defold/extender/PlatformNotSupportedException 0%
com/defold/extender/SandboxedPath 70.9% 69%
com/defold/extender/TemplateExecutor 33.3% 50%
com/defold/extender/Timer 100%
com/defold/extender/TreePrinter 0% 0%
com/defold/extender/Version 0%
com/defold/extender/VersionNotSupportedException 0%
com/defold/extender/WebSecurityConfig 0% 0%
com/defold/extender/WhitelistConfig 100%
com/defold/extender/ZipUtils 80.3% 69.2%
com/defold/extender/builders - 0%
Name Line Branch
com/defold/extender/builders 0% 0%
com/defold/extender/builders/CSharpBuilder 0% 0%
com/defold/extender/cache - 33.3%
Name Line Branch
com/defold/extender/cache 33.3% 16.6%
com/defold/extender/cache/CacheEntry 64.7% 75%
com/defold/extender/cache/CacheKeyGenerator 81.8% 100%
com/defold/extender/cache/DataCache
com/defold/extender/cache/DataCacheFactory 5% 0%
com/defold/extender/cache/DummyDataCache 80%
com/defold/extender/cache/GCPDataCache 0% 0%
com/defold/extender/cache/LocalDiskDataCache 64.7% 16.6%
com/defold/extender/cache/info - 100%
Name Line Branch
com/defold/extender/cache/info 100% ****
com/defold/extender/cache/info/CacheInfoFileParser 100%
com/defold/extender/cache/info/CacheInfoFileWriter 100%
com/defold/extender/cache/info/CacheInfoWrapper 100%
com/defold/extender/log - 14.2%
Name Line Branch
com/defold/extender/log 14.2% 0%
com/defold/extender/log/ExtenderLogEnhancer 0% 0%
com/defold/extender/log/ExtenderLogEnhancerConfiguration 0% 0%
com/defold/extender/log/Markers 80%
com/defold/extender/metrics - 38.8%
Name Line Branch
com/defold/extender/metrics 38.8% ****
com/defold/extender/metrics/MetricsWriter 38.8%
com/defold/extender/process - 52.7%
Name Line Branch
com/defold/extender/process 52.7% 58.3%
com/defold/extender/process/CommandLineTokenizer 95.5% 83.8%
com/defold/extender/process/ProcessExecutor 22.6% 17.6%
com/defold/extender/process/ProcessUtils 0% 0%
com/defold/extender/remote - 96%
Name Line Branch
com/defold/extender/remote 96% 77.7%
com/defold/extender/remote/RemoteBuildException 100%
com/defold/extender/remote/RemoteEngineBuilder 95.7% 77.7%
com/defold/extender/remote/RemoteHostConfiguration 100%
com/defold/extender/remote/RemoteInstanceConfig 100%
com/defold/extender/services - 44.9%
Name Line Branch
com/defold/extender/services 44.9% 40.2%
com/defold/extender/services/DataCacheService 79.8% 61.9%
com/defold/extender/services/DefoldSdkService 75.5% 61%
com/defold/extender/services/DefoldSdkServiceConfiguration
com/defold/extender/services/GCPInstanceService 1.1% 0%
com/defold/extender/services/GradleService 0%
com/defold/extender/services/GradleServiceInterface
com/defold/extender/services/HealthReporterService 82.4% 55.2%
com/defold/extender/services/MockGradleService 0%
com/defold/extender/services/RealGradleService 0% 0%
com/defold/extender/services/UserUpdateService 0% 0%
com/defold/extender/services/cocoapods - 51.9%
Name Line Branch
com/defold/extender/services/cocoapods 51.9% 56.6%
com/defold/extender/services/cocoapods/CocoaPodsService 9.4% 20.6%
com/defold/extender/services/cocoapods/CocoaPodsServiceBuildState 16.6% 0%
com/defold/extender/services/cocoapods/CreateBuildSpecArgs 60.7%
com/defold/extender/services/cocoapods/IConfigParser
com/defold/extender/services/cocoapods/LanguageSet 66.6% 50%
com/defold/extender/services/cocoapods/MainPodfile 20%
com/defold/extender/services/cocoapods/PlatformAndLanguageSet 0% 0%
com/defold/extender/services/cocoapods/PlatformSet 0% 0%
com/defold/extender/services/cocoapods/PlistBuddyWrapper 0% 0%
com/defold/extender/services/cocoapods/PodBuildSpec 81.4% 65.4%
com/defold/extender/services/cocoapods/PodfileParser 94.9% 82.2%
com/defold/extender/services/cocoapods/PodfileParsingException 100%
com/defold/extender/services/cocoapods/PodSpec 60.4% 40%
com/defold/extender/services/cocoapods/PodSpecParser 89.5% 79.1%
com/defold/extender/services/cocoapods/PodUtils 63% 51.4%
com/defold/extender/services/cocoapods/ResolvedPods 52.7% 45.6%
com/defold/extender/services/cocoapods/XCConfigParser 94.5% 85.2%
com/defold/extender/services/data - 80.7%
Name Line Branch
com/defold/extender/services/data 80.7% 75%
com/defold/extender/services/data/DefoldSdk 87.5% 75%
com/defold/extender/services/data/GCPInstanceState 0%
com/defold/extender/tracing - 21.8%
Name Line Branch
com/defold/extender/tracing 21.8% 25%
com/defold/extender/tracing/ExtenderExecutor 0% 0%
com/defold/extender/tracing/ExtenderTracerInterceptor 100% 100%
com/defold/extender/tracing/TraceIdInResponseServletFilter 0% 0%
com/defold/extender/utils - 0%
Name Line Branch
com/defold/extender/utils 0% 0%
com/defold/extender/utils/FrameworkUtil 0% 0%
com/defold/extender/utils/PodBuildUtil 0% 0%

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 45402b0379

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread server/src/main/java/com/defold/extender/services/HealthReporterService.java Outdated
Capping the pool at 32 reintroduced the starvation it was meant to fix: with
more than 32 builders, probes past the cap wait in the executor queue while
their completeOnTimeout timer -- started at submission, not at execution -- is
already running, so a healthy builder could time out to false before its
request ran. Size the pool to the exact builder count so no probe queues.
@ekharkunov
ekharkunov merged commit 44ce5da into dev Aug 12, 2026
5 checks passed
@ekharkunov
ekharkunov deleted the fix/health-report-probe-starvation branch August 12, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant