Repository navigation
[AMORO-4431][AMS] Close optimizing process instead of failing when self-optimizing is disabled - #4432
zhang-arvin wants to merge 1 commit into
Conversation
…lf-optimizing is disabled Closes apache#4431. Root cause: since 0.9 both the real close path and failed commits routed through completeProcess(false), so disabling self-optimizing (or cancelling) was recorded as a process failure. Worse, when the in-memory OptimizingProcess was already gone the table_process row was never closed and stayed RUNNING. Changes: - Distinguish CLOSED from FAILED: completeProcess now takes the terminal ProcessStatus and TableOptimizingMetrics only increments process_failed_count for genuine FAILED processes. - DefaultTableRuntime.closeProcessFromStore(processId) persist-closes a non-terminal table_process row by id and resets the table to IDLE when the in-memory process is gone. - TableRuntimeRefreshExecutor retries closing the tracked process on every refresh while self-optimizing stays disabled, so an orphan RUNNING row cannot survive. - DefaultOptimizingService.cancelProcess falls back to closing the tracked row by id, and TableController.cancelOptimizingProcess no longer returns HTTP 200 when cancel did not happen. - completeProcess is now null-safe (previously an NPE when the in-memory process was gone). Tests: TestDefaultOptimizingService covers disabling self-optimizing with a live process and with an orphan row, plus cancel-by-id with a missing in-memory process; all assert the row becomes CLOSED and process_failed_count is not incremented.
j1wonpark
left a comment
There was a problem hiding this comment.
Thanks for separating intentional closure from failure accounting.
question: Could we clarify how the reported process ends up with a RUNNING row but no in-memory OptimizingProcess? The log in #4431 shows an Iceberg commit validation failure, but does not establish that the runtime reference was missing. The new tests clear the reference via reflection, so they verify the fallback behavior rather than the failure path that creates this state.
I reproduced one possible path: if the outer transaction commit in persistAndSetCompleted fails after completeProcess has cleared the reference, the database rolls back to RUNNING while the reference remains null. This does not establish that the same failure occurred in the reported environment.
Could we add a regression test through the actual failure/recovery path, with the relevant logs or reproduction steps linking it to #4431? That would help us determine whether this needs a fix to state consistency, orphan cleanup, or both.
Root cause
Since 0.9, both the normal close path and a failed commit routed through
completeProcess(false), so disabling self-optimizing (or cancelling) was recorded as a process failure. On top of that, when the in-memoryOptimizingProcesswas already gone (AMS restart / released process), thetable_processrow was never closed and stayedRUNNINGforever:TableRuntimeRefreshExecutor.handleConfigChangedonly closed the in-memory process, and only whengetOptimizingProcess() != null. Later refreshes did not retry, so an orphan row stayedRUNNING.DefaultOptimizingService.cancelProcessreturnedfalsewhen the in-memory process was missing, butTableController.cancelOptimizingProcessstill returned HTTP 200.OptimizingQueue...persistAndSetCompleted(false)/close()calledcompleteProcess(false), which incrementedamoro_table_optimizing_process_failed_count_totaleven for a user/config close.Changes
DefaultTableRuntime.completeProcessnow takes the terminalProcessStatus;TableOptimizingMetrics.processComplete(type, success, failed, planTime)only increments the failure counters for a genuineFAILEDprocess. A CLOSED/CANCELED/KILLED process no longer counts as a failure.DefaultTableRuntime.closeProcessFromStore(processId)(andcloseTrackedProcessFromStore()) persist-close a non-terminaltable_processrow owned by the table and reset the table toIDLEwhen no in-memory process exists.TableRuntimeRefreshExecutorcalls the close on every refresh while self-optimizing stays disabled, so an orphanRUNNINGrow cannot survive.DefaultOptimizingService.cancelProcessfalls back to closing the tracked row by id;TableController.cancelOptimizingProcessfails (non-200) when cancel did not happen.completeProcessis now null-safe (previously NPE'd when the in-memory process was gone, as seen inOptimizingQueue.releaseTable).Tests
TestDefaultOptimizingService:CLOSED, tableIDLE,process_failed_countunchanged;CLOSED, counter unchanged;trueand closes the row.mvn -pl amoro-ams -am test -Dtest=TestDefaultOptimizingService(33 tests) and the relatedTestIcebergV3OptimizingPlanning,TestTableRuntimeRefreshExecutor,TestTableSummary*,TestOverviewManager,TestTableManagerQuerysuites pass;spotless:checkpasses.Fixes #4431.