nizhikov commented on PR #12584:
URL: https://github.com/apache/ignite/pull/12584#issuecomment-6261659829

   Round 2 review (head `2a32c93`). Thanks for the quick turnaround — most of 
round one is addressed: the status now lands in the metrics message, 
`tasksStatuses()` is gone from the public interface, padding is out of the 
enum, unregistered tasks are reflected, `CALLED`-on-listing is gone, and the 
real defragmentation / index rebuild / corrupted-PDS flows have tests.
   
   I ran checkstyle (clean), built core, and ran `MaintenanceLoggingTest` (15), 
`MaintenanceDefragmentationLoggingTest` (3), `MaintenanceRegistrySimpleTest`, 
`IgnitePdsDefragmentationTest`, `WalEnableDisableWithRestartsTest` and 
`IndexCorruptionRebuildTest` — all green.
   
   ### Blocking
   
   1. **Breaking change to the public `MaintenanceAction` interface.** 
`state(MaintenanceTaskState)` is added as an abstract method with no default, 
so every third-party `MaintenanceAction` implementation stops compiling and 
existing binaries get `AbstractMethodError`. The public interface in 
`org.apache.ignite.maintenance` now also imports 
`org.apache.ignite.internal.maintenance.MaintenanceTaskState`, i.e. public API 
depends on an internal type. The decorator approach from round one still 
applies: `MaintenanceProcessor` can wrap every action it hands out (the 
automatic action and the list from `actionsForMaintenanceTask`) and record 
`ACTIVE` before `execute()`, `COMPLETED`/`FAILED` after, with no public API 
change. Only the asynchronous defragmentation completion needs an internal 
hook, which can live in `DefragmentationWorkflowCallback`. If the interface 
change is kept on purpose, it needs at least a default no-op implementation and 
a public (not internal) state type.
   
   2. **Bookkeeping pushed into every action is fragile.** Each implementation 
must remember `state.currAction(name()).state(ACTIVE)` plus a terminal state on 
every return path. `CheckCorruptedCacheStoresCleanAction` already needs two 
`COMPLETED` calls and `RebuildIndexAction` three terminal calls; an action that 
forgets stays `ACTIVE` forever, and one that throws before the processor 
injected the state NPEs. A single wrapper in the processor removes this class 
of bugs.
   
   3. **`MaintenanceTaskState.state` is a plain `ArrayList` mutated from 
several threads.** The defragmentation thread appends, control.sh threads 
append, and the metrics timer iterates it via `stream()` in `tasksStates()`. 
That's a `ConcurrentModificationException` during a long defragmentation. Use 
`CopyOnWriteArrayList` or synchronize; a `lastState()` accessor would also 
replace the repeated `states.get(states.size() - 1)`.
   
   4. **`testRebuildIndexActionCompletedLog` is vacuous.** The thin-client SQL 
(`CREATE TABLE`, `CREATE INDEX`, 2048 inserts) never executes: 
`IgniteClient.query()` returns a lazy cursor and nothing iterates it, and 
core's test classpath has no SQL engine anyway. The test takes ~1.3 s; 
`RebuildIndexAction` finds no index descriptor, skips, and reports `COMPLETED`. 
To cover a real rebuild, the test belongs in `modules/indexing` next to 
`IndexCorruptionRebuildTest`.
   
   ### Should fix
   
   5. **`tasksStates()` returns `List<List<String>>`.** Positional string 
tuples indexed 0..4 in `IgniteLogInfoProviderImpl` are hard to read and easy to 
break. Return `Collection<MaintenanceTaskState>` and format from the object.
   
   6. **`NOT_REGISTERED` state.** `registerWorkflowCallback` for a name with no 
stored task fabricates a `MaintenanceTask(name, "", null)` and logs it. That 
only happens on misuse (all in-core callers are guarded), and the javadoc 
("registered through registerWorkflowCallback, not registered from storage") is 
confusing. Reject or warn instead of inventing a state.
   
   7. **Defragmentation `COMPLETED` after a cancel can never be recorded.** 
`ExecuteDefragmentationAction` checks `state.state().contains(CANCELLED)` over 
the whole history. Cancel once, start again via control.sh, let it finish → 
`COMPLETED` is suppressed. Check the last state, not the history.
   
   8. **State order for index rebuild** reads `ACTIVE->UNREGISTERED->COMPLETED` 
because `unregisterMaintenanceTask()` runs before `state(COMPLETED)`. Swap them 
(or record `COMPLETED` in the wrapper).
   
   9. **Side effects in `peek`.** `actionsForMaintenanceTask` uses 
`stream().peek(a -> a.state(...)).toList()`. `peek` is for debugging and may be 
elided; use a plain loop.
   
   10. **Mixed lifecycle and action states in one history.** 
`REGISTERED`/`UNREGISTERED`/`NOT_REGISTERED` describe the task, 
`ACTIVE`/`COMPLETED`/`FAILED`/`CANCELLED` describe an action, and action names 
aren't in the history — so `ACTIVE->COMPLETED->ACTIVE->COMPLETED` for the 
corrupted-PDS task doesn't say which action ran. Consider 
`actions=[check=COMPLETED, clean=ACTIVE]`, or at least the last action with its 
state.
   
   11. **Style.** Single-line `if (cond) stmt;` throughout the new code 
(`MaintenanceProcessor`, the actions, the log provider). Checkstyle allows it, 
but surrounding code and Ignite convention put the statement on the next line.
   
   ### Test nits
   
   12. `StopAction.execute()` in `MaintenanceLoggingTest` contains 
`assertTrue(... check(2000))` inside the action itself; assertions belong in 
the test method.
   13. `mntcReg` is a static field reassigned per test and read from action 
threads; a per-test instance field avoids cross-test leakage.
   14. `testLogRegisterActiveFailedDefragmentationTask` wraps a Mockito mock of 
`CachePartitionDefragmentationManager` in a real 
`DefragmentationWorkflowCallback`. Works, but `IgnitePdsDefragmentationTest` 
already has infrastructure for failing defragmentation that may be reusable.
   
   ### Process
   
   PR description is still the template — please fill in what/why.
   
   ### Verdict
   
   Not ready yet, mainly because of the public API break in `MaintenanceAction` 
and the unsynchronized state list. The direction is right and the round-one 
semantics issues are fixed for the covered flows; with tracking moved back into 
the processor as a wrapper and the list made thread-safe, this should be close.
   


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