u70b3 opened a new pull request, #67978:
URL: https://github.com/apache/doris/pull/67978

   # Add Lance index job dispatcher with thrift dispatch boundary
   
   > **Stacked on #67630** (admission + job inspection SQL). This branch 
currently carries that PR's commits as well; only the last 8 commits are new 
here, and the diff collapses to the dispatcher changes once #67630 merges. 
Reviewing the last 8 commits directly is the easiest reading order.
   
   ## Problem
   
   The durable Lance index job records created by the admission path (#67630) 
currently stay `PENDING` forever: nothing drives them toward a terminal state 
and no execution channel exists. This change adds the master-side driver and 
the dispatch-boundary contracts so an admitted job can be dispatched at most 
once, classified into its terminal state, and released — still entirely behind 
the disabled-by-default `enable_lance_index_mutation` gate.
   
   ## What lands
   
   - **Thrift dispatch boundary (contract only)**: `TLanceIndexJobDispatch` / 
`TLanceIndexJobReport` plus `submit_lance_index_job` and 
`reportLanceIndexJobResult`, four new enums with explicit field ids. No backend 
consumption lands here (the isolated worker is a later release); the backend 
handler stub answers a clean not-implemented error, so a cluster without 
workers resolves a dispatched job as `NOT_COMMITTED` instead of `UNKNOWN`.
   - **`LanceIndexJobDispatcher`** (master-only `MasterDaemon`, one round in 
fixed order):
     - *deadline sweep*: an expired `RUNNING` job converges to `UNKNOWN` 
through `completeWithResult(NO_TRUSTED_RESULT)`; the possible-live slot, fence, 
and quota all stay held (a deadline bounds the wait, never proves termination);
     - *possible-live sweep*: a slot is released only when the recorded backend 
process epoch no longer exists; a missing backend entry or heartbeat loss 
proves nothing and keeps the slot held;
     - *refresh driver*: terminal jobs with refresh `REQUIRED`/`FAILED` resume 
through the existing idempotent external-table refresh path; `FAILED` retries 
are throttled to one attempt per retry interval while a first `REQUIRED` 
refresh is never delayed; `DONE` releases the fence and quota through the 
existing apply-to-memory accounting;
     - *PENDING dispatch*: durable `RUNNING` (invocation id, backend process 
epoch, deadline) is journaled **before** any network I/O, then 
leadership/revision/invocation-id are rechecked immediately before the single 
send; per-round and per-backend in-flight caps bound the dispatch rate; 
local-file datasets additionally require the separate operator assertion and a 
single-FE, single-alive-backend topology.
   - **Callback handler**: a typed result envelope is applied through 
`completeWithResult` (the identity check and the result classification live in 
the job manager from #67235); stale or malformed envelopes are logged and 
dropped.
   - **Config**: dispatch interval, execute deadline, per-round dispatch cap, 
per-backend in-flight cap, refresh retry interval, and the local-file mutation 
assertion — all mutable, master-only, positive-validated through the existing 
validator.
   - **Job manager**: three read-only sweep queries plus a force-release filter 
on the refresh query. No new edit-log operation (the job upsert is reused), no 
new write path, no lifecycle change.
   
   ## Design interpretations (please confirm)
   
   1. **Dedicated thrift methods** instead of extending `TTaskType`/the 
agent-task queue: this avoids wire-enum drift across branches and the 
tablet-oriented semantics (and resend culture) of that track; FE-side 
single-send plus the manager compare-and-set already provide at-most-once.
   2. **PENDING retry is unbounded**: there is no dispatch-exhaustion terminal 
state; a pre-send failure (no backend selectable, caps reached, local-file 
assertion off) keeps the job `PENDING` and retries on the next round.
   3. **Send failure classification**: a transport exception after the send may 
have occurred converges the job to `UNKNOWN` immediately; only a clean error 
status — provably not enqueued — resolves `NOT_COMMITTED` as a resource 
rejection.
   4. **The dispatcher does not read the mutation gate**: the gate guards 
admission; a job that is already durable must be driven to its terminal state 
regardless of the gate's current value.
   5. **Local `file://` handling** enforces the topology rejection at dispatch 
only; the pre/post-invocation version and identity checks belong to the worker 
slice.
   
   ## Concurrency
   
   The dispatcher holds no catalog or manager lock across any call; every 
durable transition goes through the job manager under its own lock, and the 
catalog → job-manager lock order is unchanged. The report handler runs on the 
RPC thread and performs no I/O beyond the manager's edit-log write. The daemon 
early-exits on lost mastership and on the checkpoint thread, and an idle round 
writes no journal record.
   
   ## Validation
   
   - Focused FE run: **481 tests across 16 classes, 0 failures / 0 errors / 0 
skipped** (89 new: dispatcher 26, refresh driver 8, report handler 16, frontend 
shim 3, thrift contract 7, manager queries +5, wiring +2, config validator 
+4... alongside the existing suites), with checkstyle.
   - Full FE UT (clean build, fe-common + fe-core): **9490 tests**; all 21 
failing methods across 14 classes are the known environmental set 
(timezone/network/native library), identical class-by-class to the merge base — 
including `DiskReblanceWhenSchedulerIdle`, re-verified to fail with the same 
assertion on the merge base itself. Zero new failures.
   - Regression suite `test_lance_index_dispatch.groovy`: negative/static only 
(config smoke, dispatcher-inert assertions); it needs the external docker 
fixture and runs in the pipeline, not locally. 
`test_lance_index_admission.groovy` was made deterministic by pinning the 
dispatch interval for its window, because admitted jobs are now actually 
dispatched once the gate is open.
   - Backend compiles with the not-implemented stub; no backend behavior change.
   
   ## Deferred
   
   - Backend consumption of the boundary: supervisor, hard-isolated worker 
process, and the lance-c invocation (a later release).
   - The mutation gate stays closed; opening it requires the verified worker 
memory/PID/runtime boundary.
   - End-to-end dispatch evidence and real `UNKNOWN` production (fake-worker 
fault tests in UT cover the lifecycle contracts; G2/G4 e2e evidence belongs to 
the worker slice).
   - Master-side IDL sync PR, if needed, lands with the worker slice.
   
   ## Release note
   
   None — fully gated behind the disabled-by-default 
`enable_lance_index_mutation`; no user-visible behavior change.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to