fightBoxing opened a new pull request, #4195:
URL: https://github.com/apache/amoro/pull/4195

   Fixes #4172.
   
   ## Problem
   
   When a table's optimizing process reaches the post-execution phase — all 
tasks
   are `SUCCESS` and the code is about to transition the table to `COMMITTING` —
   a transient failure of `TableRuntime#beginCommitting()` (e.g. DB lock wait
   timeout in the underlying `UPDATE table_runtime`) causes `invokeConsistency`
   to roll back the in-memory status. The process stays `RUNNING` but the table
   status remains `*_OPTIMIZING`, **forever, until AMS is restarted**. The issue
   reporter confirmed exactly this symptom.
   
   Root cause: there is no code path that retries or re-drives
   \`beginCommitting()\` when it transiently fails. \`OptimizingCommitExecutor\`
   only schedules when the status is already \`COMMITTING\`, so the stuck state
   is invisible to it.
   
   ## Approach (A1: narrow, targeted self-heal)
   
   Leverage the existing \`TableRuntimeRefreshExecutor\`, which already scans 
every
   table periodically. At the end of \`execute()\`, detect the stuck pattern and
   re-drive the transition:
   
   \`\`\`
   process != null
     && process.getStatus() == RUNNING
     && tableRuntime.getOptimizingStatus() != COMMITTING
     && tableRuntime.getOptimizingStatus().isProcessing()
     && process.allTasksPrepared()
   \`\`\`
   
   When all conditions hold we call \`tableRuntime.beginCommitting()\`. On
   success the normal \`handleTableChanged\` → \`OptimizingCommitExecutor\` path
   resumes. On failure we log and retry on the next refresh cycle (≤ 1 minute
   by default).
   
   ## Why this location
   
   - \`TableRuntimeRefreshExecutor\` already does \`enabled() == true\` for 
every
     table — no new thread pool, no new scheduling mechanism.
   - \`OptimizingCommitExecutor\` is intentionally kept as-is; it is only 
notified
     via the existing \`handleTableChanged\` event once the self-heal succeeds.
   - \`OptimizingQueue.acceptResult()\` hot path (concurrent task completion) is
     **not** changed — we only expose an existing read method.
   
   ## Changes
   
   | File | Change |
   |---|---|
   | \`OptimizingProcess.java\` | Add \`boolean allTasksPrepared()\` to the 
interface. |
   | \`OptimizingQueue.java\` | \`TableOptimizingProcess.allTasksPrepared()\` 
becomes \`@Override public\` and lock-protected for cross-thread visibility. |
   | \`TableRuntimeRefreshExecutor.java\` | New private 
\`tryHealStuckCommitting()\` invoked at the end of \`execute()\`. |
   | \`TestDefaultOptimizingService.java\` | New regression test 
\`testRefreshExecutorHealsStuckRunningProcess\` that uses reflection to 
simulate the stuck state, then verifies \`execute()\` transitions back to 
\`COMMITTING\`. |
   
   ## Verification
   
   Target test passes locally:
   
   \`\`\`
   mvn -pl amoro-ams -am test \
     
-Dtest='TestDefaultOptimizingService#testRefreshExecutorHealsStuckRunningProcess'
 \
     -Dsurefire.failIfNoSpecifiedTests=false -DskipITs
   
   Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
   BUILD SUCCESS
   \`\`\`
   
   Self-heal path logs are observable during the test:
   
   \`\`\`
   WARN TableRuntimeRefresher: ...detected stuck RUNNING optimizing process
   (processId=..., status=MINOR_OPTIMIZING): all tasks have succeeded but the
   table never transitioned to COMMITTING. Self-healing by re-driving
   beginCommitting() (issue #4172).
   \`\`\`
   
   ## Risk
   
   - No change to concurrent hot paths; only one additional idempotent read
     (\`allTasksPrepared\`) per refresh cycle, short-circuited early for
     tables that are not processing.
   - Worst case if the underlying DB stays unhealthy: self-heal keeps logging
     at \`WARN\` and retrying every refresh cycle — exactly the same cost as
     before plus one cheap read. Strictly better than today's
     "stuck until restart".
   - Opened as **draft** first to let CI confirm, then I'll flip to ready
     for review if green.


-- 
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]

Reply via email to