Arnold Galovics created FINERACT-2926:
-----------------------------------------

             Summary: StuckJobListener waits forever when a COB partition was 
killed
                 Key: FINERACT-2926
                 URL: https://issues.apache.org/jira/browse/FINERACT-2926
             Project: Apache Fineract
          Issue Type: Bug
            Reporter: Arnold Galovics
            Assignee: Arnold Galovics


🐛 Steps to Reproduce
1. Run Fineract 1.15.0 with batch manager and batch worker enabled in one 
container, business date enabled, and 2 loans lagging behind the COB date.
2. Start Loan COB with POST /jobs/\{id}?command=executeJob.
3. Kill the container (docker kill) while the COB partition step is STARTED.
4. Start the container again and read the application log and the 
batch_job_execution and batch_step_execution tables.
 
❌ Actual Result
• The job execution stays STARTED/UNKNOWN and the partition step stays STARTED 
forever.
• StuckJobListener logs "Sleeping for a second to wait for the partitions to 
complete for job <id>" in an endless loop and never restarts the job. Readiness 
is not blocked.
• Boot resets job.currently_running, but the execution is never closed.
• Marking the partition FAILED does not help: the loop exits only on COMPLETED.
 
✅ Expected Result
• A partition step that has not been updated for longer than a timeout 
(proposed: fineract.job.stuck-partition-timeout, default 10m) is marked FAILED, 
so the job is restarted and re-runs only the unfinished partitions. COMPLETED 
partitions are not re-run.
• No endless loop, and one stuck tenant does not block stuck-job recovery for 
the tenants after it.
 
ℹ️ Notes
• Observed on Fineract 1.15.0, Docker, Postgres 16, single-instance topology. 
Not tested: multi-instance topology.
• Workaround: set the STARTED step and job executions to ABANDONED and reboot. 
ABANDONED only closes the execution; it cannot be restarted.
• is_suspended is deliberately not honoured: restarting a stuck job is crash 
recovery, not a scheduled run.
 
🔧 Technical Notes
• StuckJobListener.java:17-45. 
StuckJobExecutorServiceImpl#waitUntilAllPartitionsFinished loops on 
JobExecutionRepository#getNotCompletedPartitionsCount, which counts every 
non-partitioner step with STATUS <> COMPLETED, so FAILED, STOPPED and ABANDONED 
worker steps also loop forever. The listener runs on an event thread and 
handles tenants one after another.
• Fix: count only STARTING, STARTED and STOPPING steps; in each loop iteration 
run an UPDATE setting such steps to FAILED (EXIT_CODE FAILED, END_TIME now) 
where LAST_UPDATED is older than now minus the timeout. The existing 
updateJobStatusToFailed and restart then re-run only FAILED partitions 
(SimpleStepExecutionSplitter#shouldStart restarts only FAILED and STOPPED, 
which is why ABANDONED is not the target state).
• A live worker updates LAST_UPDATED on every chunk commit, so it is not marked 
dead. The timeout must exceed the slowest chunk. LAST_UPDATED is written in the 
JVM time zone, so pods with mixed time zones would break the cutoff.
• Test: StuckJobExecutorServiceImplTest (Mockito): count 1 then 0 calls the 
stale update with the right cutoff, then updateJobStatusToFailed, then restart; 
count 0 goes straight to restart.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to