Skip to content

fix(hubble): close loaders on task exit - #814

Open
imbajin wants to merge 13 commits into
apache:masterfrom
hugegraph:fix/hubble-loader-cleanup
Open

imbajin wants to merge 13 commits into
apache:masterfrom
hugegraph:fix/hubble-loader-cleanup

Conversation

@imbajin

@imbajin imbajin commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Purpose of the PR

Hubble could leave a Loader open after task exit or failed save/dispatch. Resume and retry had the same leak, and rethrowing the original load failure during shutdown could overwrite PAUSED or STOPPED.

Source PR: hugegraph#66.

Main Changes

Close each Loader through the existing drain and transaction callbacks, including resume/retry failures and rollback. Preserve the primary exception and the requested task state when shutdown only rethrows that exception; independent cleanup failures remain FAILED with recovery information. When a load failure is already recorded, a separate mode-reset failure is preserved during shutdown; the first directly thrown Error keeps its identity: a resource-close Error takes precedence over an ordinary reset failure, while an earlier reset Error remains primary. Successful shutdown unregisters its own JVM hook, and unused Loaders preserve checkpoints.

Concurrent ordinary imports need the paired Loader owner integration and Server ownership API. The current paired artifacts passed an actual same-Server Hubble multi-file run and authenticated Chrome CSV import, followed by independent data and mode readback. Both corresponding shared-mode review threads are resolved. The paired PRs remain unmerged.

A completes, B still running -> LOADING
B completes                 -> NONE

Verifying these changes

  • Need tests and can be verified as follows:
    • The existing Hubble integration evidence is unchanged. This SDK follow-up passes the complete Client/Loader unit suites, related reactor clean compile, formatting and strict checks of both changed files. A root offline all-module compile could not resolve an uncached, unrelated Spark plugin and remains unverified.
    • Native Loader regressions cover save/dispatch failures, rollback, shutdown exceptions and hook cleanup. Additional actual Loader/client controls cover a rejected HTTP mode reset, recorded-failure identity and resource release; controlled fatal client-close boundaries check Error precedence and acyclic diagnostics.
    • An isolated resource/owner fixture covers task-state and cleanup-failure boundaries with HTTP stubs.
    • Real Spring/H2/MyBatis/async Loader execution against standalone RocksDB verifies two-file ownership, exact data and normal-completion cleanup. A real Chrome file chooser, mapping and Run Once flow verifies data/UI, graph switching and query display; independent Server readback confirms NONE and an unchanged second graph. Direct resource inspection confirms context closure, terminated worker pools and removed hooks. The same three independent reviewers passed this bounded integration.
    • PD/HStore deployment, the broader pause/stop and role matrix, and full TC05/TC13 remain open. Application-level idle async threads are tracked separately from Loader cleanup.

Does this PR potentially affect the following parts?

  • Dependencies
  • Modify configurations
  • The public API
  • Other affects: import resource cleanup
  • Nope

Documentation Status

  • Doc - TODO
  • Doc - Done: Hubble and Loader READMEs.
  • Doc - No Need

Conceptual overview

Hubble closes each Loader before task outcome publication, including unscheduled failures and rollback. Existing load failures preserve requested pause/stop states; independent cleanup failures remain visible. Concurrent imports require #815 and Server #3331.

Conceptual illustration; not test or release-acceptance evidence.

Hubble task exit and unscheduled-failure paths converge on Loader cleanup, with task-state handling and paired ownership dependencies

- require confirmed loading mode before cleanup
- keep cleanup state local and reset it on clone
- cover failed startup and cleanup error paths
- document network uncertainty and shared mode limits
- log the graph when a mode write loses its response
- preserve the original checked transport exception
- retain cleanup ownership and avoid blind mode resets
- verify the diagnostic and explain manual recovery
- include the latest mode acquisition guard
- preserve current ASF launcher and fixture fixes
- keep Hubble changes available for review
- retain loader ownership through cleanup and recovery
- preserve typed file progress during cancellation
- serialize job admission with metadata deletion
- verify transaction rollback and stale callbacks
- align the Hubble cleanup branch with current master
- preserve the validated Loader and Hubble source bytes
- retain lifecycle and checkpoint regression coverage
@github-actions github-actions Bot added hubble hugegraph-hubble loader hugegraph-loader labels Oct 13, 2026

@imbajin imbajin left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Same-source cross-review: 7.5/10 at fc0c3fc. Commit and tree match the reviewed org PR. Two open points remain: dispatch rejection followed by failure-state transaction rollback can discard the recovery owner (hugegraph#66 (comment)); normal same-job multi-file completion can restore NONE while another importer remains active (hugegraph#66 (comment)). The first is a baseline-existing recovery gap; the second is the existing shared GraphMode ownership family newly exposed by completion cleanup. Server #3331 alone does not integrate this client. No new runtime reproduction or ASF CI pass is claimed.

- route Ingest and graph cleanup through scoped job deletion
- preserve permission and remote-drop failure boundaries
- retry rejected dispatch after SQL and commit failures
- isolate polling writes and retire owners after commit
- document and verify deletion and recovery contracts
@codecov

codecov Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.77778% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 45.39%. Comparing base (8e6ed84) to head (2b2d66c).

Files with missing lines Patch % Lines
...ava/org/apache/hugegraph/entity/load/LoadTask.java 73.91% 5 Missing and 7 partials ⚠️
...apache/hugegraph/service/load/LoadTaskService.java 79.16% 8 Missing and 2 partials ⚠️
...a/org/apache/hugegraph/loader/HugeGraphLoader.java 81.81% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master     #814      +/-   ##
============================================
- Coverage     47.04%   45.39%   -1.65%     
+ Complexity     4517     3381    -1136     
============================================
  Files           602      377     -225     
  Lines         29448    22583    -6865     
  Branches       3454     3033     -421     
============================================
- Hits          13853    10251    -3602     
+ Misses        14312    11251    -3061     
+ Partials       1283     1081     -202     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

- propagate Spring transaction and savepoint failures
- retain earlier owners when the polling transaction aborts
- verify real deadlocks and ordinary SQL failure isolation
- document the polling rollback boundary
- inherit merged source release helper migration
- retain upstream JSON list support
- preserve reviewed Hubble deletion and recovery changes
 - use deletion-specific stopping while keeping stop requests strict
 - preserve completed states and wait for existing owner cleanup
 - cover H2 completion races, closure refusal and completion waits
 - document deletion of tasks that finish after enumeration
- close task and example loaders after loading
- close unused loaders on save, dispatch or transaction failure
- remove owned shutdown hooks and preserve unused checkpoints
- defer metadata and concurrency recovery to separate work
- limit unused-loader cleanup to initial task creation
- retain task-exit and built-in example guidance
- leave resume and retry failures in the deferred scope
@imbajin imbajin changed the title fix(hubble): close owned loaders before deletion fix(hubble): close loaders on task exit Oct 13, 2026
@imbajin
imbajin marked this pull request as ready for review October 13, 2026 16:34

@bitflicker64 bitflicker64 left a comment

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.

Blocking: yes. Summary: Closing the Loader on task exit, on a failed initial save or dispatch and on rollback works as described, and the hook removal and checkpoint handling in the Loader are sound, but the new shutdown resets the graph mode to NONE when the first task of a multi-file job finishes while the others are still importing. Two smaller notes cover the resume and retry paths and the status after a failed load. Evidence: full diff 8e6ed84..8757dc8 read with LoadTask, LoadTaskService, LoadTaskController, LoadTaskExecutor, AsyncConfig, HugeGraphLoader, LoadContext and TaskManager at this head, and GraphTransaction.prepareAdditions in apache/hugegraph; no tests were run for this review. candidate-image (loader) failed on this head in its Install locked same-source SDK step and the Hubble image, CodeQL and module validation jobs were still queued at review time, so CI did not yet confirm the new tests.

Pengzna
Pengzna previously approved these changes Oct 13, 2026
Close loaders when resume or retry dispatch fails.
Preserve stopped states when shutdown rethrows the load failure.
Report independent cleanup errors without replacing the primary cause.
Cover native loader exception and dispatch boundaries.

@bitflicker64 bitflicker64 left a comment

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.

Blocking: yes. Summary: The earlier Important comment still applies at 2b2d66c: merged on its own, this PR resets the graph mode to NONE when the first of several concurrent tasks on a graph exits, because the protection for a shared loading mode is in #815 and apache/hugegraph#3331, which are both still open. The two earlier Minor notes are settled (resume and retry now close their Loader on a failed update or a rejected dispatch, and a shutdown that only rethrows the load failure keeps PAUSED or STOPPED), and one new non-blocking Important note covers a mode reset failure that is lost when the load has also failed. Evidence: full diff 8e6ed84..2b2d66c (9 files, +624/-26) read with LoadTask, LoadTaskService, LoadTaskController, JobManagerService, LoadTaskExecutor, HugeGraphLoader, LoadContext and TaskManager at this head. On JDK 17, mvn -pl hugegraph-loader,hugegraph-hubble/hubble-be -am test limited to LoadContextTest, LoadTaskServiceTest and IngestTransactionIntegrationTest passes (28, 20 and 12 tests, Checkstyle and RAT skipped), and two throwaway probe tests against an HTTP stub in the same run reproduce the new note. CI: the loader-ci and hubble-ci jobs were still pending on this head at review time, and no completed check had failed.

- retain independent mode reset errors during shutdown
- preserve direct fatal cleanup errors and identity
- prevent cyclic cleanup exception diagnostics
- cover actual loader resource cleanup and reset failures

@imbajin imbajin left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Integration follow-up — the current standalone merge assessment is limited by the paired ownership lifecycle, not the now-fixed reset-error masking.

Reviewed #814 commit: 5e0389b.

The new exception-preservation tests and implementation address the earlier masking finding. The remaining integration dependency runs in both directions: this PR closes each Loader, but its LoadContext.unsetLoadingMode() still uses the shared enum reset, so concurrent imports require #815 and Server apache/hugegraph#3331. Conversely, #815 at 73ad996 still needs this PR's Hubble task-exit cleanup to release owner handles, as noted in #815 (comment).

Please validate the combined changes while preserving both this PR's reset/close exception precedence and #815's owner release. A useful paired regression starts two Hubble imports, keeps LOADING after the first task exits, and verifies NONE plus closed Loader resources after the final task exits, including failure/pause paths. Independent green checks on the two separate branches do not establish that combined lifecycle.

This consolidates existing integration requirements and does not reopen the fixed masking finding. Evidence is current-head source and existing review discussion; no new full Hubble/PD/HStore runtime acceptance is claimed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hubble hugegraph-hubble loader hugegraph-loader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants