adamsaghy commented on PR #5951:
URL: https://github.com/apache/fineract/pull/5951#issuecomment-4809616915

   @alberto-art3ch Please consider the below recommendations:
   
   <head></head><h3 class="text-text-100 mt-3 -mb-1 text-[1.125rem] font-bold" 
style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; 
font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: 
start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; 
word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-line: none; 
text-decoration-thickness: auto; text-decoration-style: solid;">PR #5951 
(Savings COB) — does it match Loan COB?</h3><p class="font-claude-response-body 
break-words whitespace-normal" style="caret-color: rgb(0, 0, 0); color: rgb(0, 
0, 0); font-style: normal; font-variant-caps: normal; font-weight: 400; 
letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; 
text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; 
-webkit-text-stroke-width: 0px; text-decoration-line: none; 
text-decoration-thickness: auto; text-decoration-style: solid;">Short 
answer:<span class="Apple-con
 verted-space"> </span><strong>no, not in the way you want.</strong><span 
class="Apple-converted-space"> </span>The Spring Batch<span 
class="Apple-converted-space"> </span><em>step topology</em><span 
class="Apple-converted-space"> </span>is a faithful port, but the PR does<span 
class="Apple-converted-space"> </span><strong>not</strong>reuse the generic COB 
framework that Loan COB already sits on — it re-introduces monolithic, 
copy‑pasted implementations under<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">Savings*</code><span class="Apple-converted-space"> 
</span>names. On top of that, several pieces are missing or wrong enough that 
the job can't compile, start, or actually do anything.</p><h4 
class="text-text-100 mt-2 -mb-1 text-base font-bold" style="caret-color: rgb(0, 
0, 0); color: rgb(0, 0, 0); font-style: normal; font-variant-caps:
  normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 
0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; 
-webkit-text-stroke-width: 0px; text-decoration-line: none; 
text-decoration-thickness: auto; text-decoration-style: solid;">The core 
problem: it duplicates instead of reusing the existing generic layer</h4><p 
class="font-claude-response-body break-words whitespace-normal" 
style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; 
font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 
2; text-align: start; text-indent: 0px; text-transform: none; white-space: 
normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; 
text-decoration-line: none; text-decoration-thickness: auto; 
text-decoration-style: solid;">Loan COB was already refactored into 
entity‑agnostic bases in the<span class="Apple-converted-space"> 
</span><strong><code class="bg-text-200/5 border border-0.5 border-border-
 300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">fineract-cob</code></strong><span class="Apple-converted-space"> 
</span>module, and the Loan classes are thin (30–60 line) subclasses. The PR 
ignored all of them and re-implemented the pre‑refactor monoliths. Verified 
mappings:</p><div class="overflow-x-auto w-full px-2 mb-6" style="caret-color: 
rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; font-variant-caps: 
normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: 
start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; 
word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-line: none; 
text-decoration-thickness: auto; text-decoration-style: solid;">
   PR's new Savings class | Existing generic base it should extend (in 
fineract-cob) | What Loan does
   -- | -- | --
   SavingsCOBPartitioner (~107 lines) | cob.common.CommonPartitioner | 
LoanCOBPartitioner extends CommonPartitioner (58 lines)
   SavingsLockingServiceImpl (~117 lines) | cob.domain.AbstractLockingService | 
LoanLockingServiceImpl extends AbstractLockingService (57 lines)
   ApplySavingsLockTasklet (~108 lines) | cob.tasklet.ApplyCommonLockTasklet | 
ApplyLoanLockTasklet extends ApplyCommonLockTasklet (47 lines)
   UnlockProcessedSavingsTasklet | 
cob.tasklet.UnlockProcessedAccountsTasklet<T>+ AccountLockService<T> | 
UnlockProcessedLoansTasklet extends UnlockProcessedAccountsTasklet<>
   ChunkProcessingSavingsItemListener(~103 lines) | 
cob.listener.AbstractLoanItemListener<T>(already generic) | 
ChunkProcessingLoanItemListener extends AbstractLoanItemListener<Loan> (39 
lines)
   SavingsItemReader | cob.service.BeforeStepLockingItemReaderHelper | 
LoanItemReader delegates to it (44 lines)
   new SavingsLockOwner enum | existing cob.domain.LockOwner | reuses LockOwner
   
   </div><p class="font-claude-response-body break-words whitespace-normal" 
style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; 
font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 
2; text-align: start; text-indent: 0px; text-transform: none; white-space: 
normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; 
text-decoration-line: none; text-decoration-thickness: auto; 
text-decoration-style: solid;">The uniform approach you're after already 
exists. Savings COB should shrink to ~6 thin subclasses + supply 
entity-specific table/SQL/lock-owner/parameter keys, exactly like Loan and 
Working‑Capital‑Loan do. Where a base is "Loan"‑named but already generic 
(<code class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 
whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">AbstractLoanItemListener&lt;T&gt;</code>,<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border border-
 0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] 
px-1 py-px text-[0.9rem]">AbstractLoanItemReader&lt;T&gt;</code>), rename it to 
a neutral<span class="Apple-converted-space"> </span><code class="bg-text-200/5 
border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">Abstract*</code>/<code 
class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 
whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">Common*</code><span class="Apple-converted-space"> </span>as 
part of this PR.</p><h4 class="text-text-100 mt-2 -mb-1 text-base font-bold" 
style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; 
font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: 
start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; 
word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-line: none; 
text-decoration-thickness: auto; text-de
 coration-style: solid;">Verified findings, most severe first</h4><ol 
class="[li_&amp;]:mb-0 [li_&amp;]:mt-1 [li_&amp;]:gap-1 
[&amp;:not(:last-child)_ul]:pb-1 [&amp;:not(:last-child)_ol]:pb-1 list-decimal 
flex flex-col gap-1 pl-8 mb-3" style="caret-color: rgb(0, 0, 0); color: rgb(0, 
0, 0); font-style: normal; font-variant-caps: normal; font-weight: 400; 
letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; 
text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; 
-webkit-text-stroke-width: 0px; text-decoration-line: none; 
text-decoration-thickness: auto; text-decoration-style: solid;"><li 
class="font-claude-response-body whitespace-normal break-words 
pl-2"><strong><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">UnlockProcessedSavingsTasklet:44</code><span 
class="Apple-converted-space"> </span>won't compile</strong><span 
class="Apple-converted-space"> </spa
 n>— calls<span class="Apple-converted-space"> </span><code 
class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 
whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">savingsAccountLockRepository.removeOrphanedLocksForProcessedAccounts()</code>,
 but that method does not exist on<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">SavingsAccountLockRepository</code><span 
class="Apple-converted-space"> </span>(it only has<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">removeLockByOwner()</code><span 
class="Apple-converted-space"> </span>/<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap round
 ed-[0.4rem] px-1 py-px text-[0.9rem]">existsBy…</code>). The generic<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">AccountLockService.removeOrphanedLocksForProcessedAccounts()</code><span
 class="Apple-converted-space"> </span>that Loan uses<span 
class="Apple-converted-space"> </span><em>does</em><span 
class="Apple-converted-space"> </span>exist — reuse it. (Note<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">removeLockByOwner</code><span 
class="Apple-converted-space"> </span>deletes rows where<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">error IS NOT NULL</code><
 span class="Apple-converted-space"> </span>— the opposite of orphan 
cleanup.)</li><li class="font-claude-response-body whitespace-normal 
break-words pl-2"><strong>Lock table is never created</strong><span 
class="Apple-converted-space"> </span>—<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">SavingsAccountLock</code><span class="Apple-converted-space"> 
</span>maps to<span class="Apple-converted-space"> </span><code 
class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 
whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">@Table(name = 
"m_savings_account_locks")</code>, but no Liquibase changelog creates that 
table (<code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">grep</code><span class="Apple-converted-space"> </span>fi
 nds none; Loan ships<span class="Apple-converted-space"> </span><code 
class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 
whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">0039_add_loan_account_locks.xml</code>). First<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">applyLock</code>→ SQL error on every 
tenant.</li><li class="font-claude-response-body whitespace-normal break-words 
pl-2"><strong><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">batchJdbcTransactionTemplate</code><span 
class="Apple-converted-space"> </span>bean is undefined</strong><span 
class="Apple-converted-space"> </span>— injected with<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-da
 nger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">@Qualifier("batchJdbcTransactionTemplate")</code><span 
class="Apple-converted-space"> </span>in<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">SavingsCOBWorkerConfiguration</code>,<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">ApplySavingsLockTasklet:54</code>,<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">ChunkProcessingSavingsItemListener</code>, but no such bean 
exists anywhere. Loan uses the existing<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-b
 order-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">requiresNewTransactionJdbcTemplate</code><span 
class="Apple-converted-space"> </span>(<code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">JdbcTransactionConfig:51</code>,<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">PROPAGATION_REQUIRES_NEW</code>). 
→<span class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">NoSuchBeanDefinitionException</code><span 
class="Apple-converted-space"> </span>at startup.</li><li 
class="font-claude-response-body whitespace-normal break-words 
pl-2"><strong>Retry contract broken in<span class="Apple-converted-space
 "> </span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">ApplySavingsLockTasklet</code></strong><span 
class="Apple-converted-space"> </span>— gates retries on<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">contribution.getStepExecution().getCommitCount()</code>(diff 
line 729) instead of the persisted attempt counter<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">ApplyCommonLockTasklet</code><span 
class="Apple-converted-space"> </span>uses (<code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">executionContext.getLong(getApply
 LockAttemptsKey())</code>, lines 88–99).<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">getCommitCount()</code><span class="Apple-converted-space"> 
</span>is committed-chunk count, not failed-lock attempts, so<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">&gt; 3</code><span 
class="Apple-converted-space"> </span>is typically never true → tasklet 
returns<span class="Apple-converted-space"> </span><code class="bg-text-200/5 
border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">CONTINUABLE</code><span 
class="Apple-converted-space"> </span>and can spin instead of failing after 3 
attempts. Disappears entirely if you extend the base.</li><li class=
 "font-claude-response-body whitespace-normal break-words 
pl-2"><strong>Stayed-locked detection is a no-op</strong><span 
class="Apple-converted-space"> </span>—<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">RetrieveSavingsIdServiceImpl.findAllStayedLockedByCobBusinessDate</code><span
 class="Apple-converted-space"> </span>returns<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">List.of()</code><span 
class="Apple-converted-space"> </span>with comment<span 
class="Apple-converted-space"> </span><em>"implemented when we add the query… 
lock table doesn't exist yet"</em>. So<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-
 wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">StayedLockedSavingsTasklet</code><span 
class="Apple-converted-space"> </span>can never emit<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">SavingsAccountsStayedLockedBusinessEvent</code>.</li><li 
class="font-claude-response-body whitespace-normal break-words 
pl-2"><strong>Job has no business steps → stops immediately</strong><span 
class="Apple-converted-space"> </span>— there is zero<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">implements 
SavingsCOBBusinessStep</code><span class="Apple-converted-space"> </span>and 
no<span class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-w
 rap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">m_batch_business_steps</code><span 
class="Apple-converted-space"> </span>seed for<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">SAVINGS_CLOSE_OF_BUSINESS</code>.<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">SavingsCOBPartitioner</code><span 
class="Apple-converted-space"> </span>calls<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">stopJobExecution()</code><span class="Apple-converted-space"> 
</span>when steps are empty, so every run stops without processing 
anything.</li><li class="font-claude-response-body whitespace-norm
 al break-words pl-2"><strong>No<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">job</code><span class="Apple-converted-space"> </span>row → 
never scheduled</strong><span class="Apple-converted-space"> </span>— no 
migration inserts a "Savings COB"<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">ScheduledJobDetail</code><span class="Apple-converted-space"> 
</span>(Loan ships<span class="Apple-converted-space"> </span><code 
class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 
whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">0037_add_loan_cob_job_data.xml</code>). The bean exists but the 
scheduler never triggers it and it's invisible in the Scheduler Jobs 
API.</li><li class=
 "font-claude-response-body whitespace-normal break-words pl-2"><strong><code 
class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 
whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">PartitionedJob</code><span class="Apple-converted-space"> 
</span>enum not extended</strong><span class="Apple-converted-space"> </span>— 
still only<span class="Apple-converted-space"> </span><code 
class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 
whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">LOAN_COB</code>. 
A stuck<span class="Apple-converted-space"> </span><code class="bg-text-200/5 
border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">SAVINGS_COB</code><span 
class="Apple-converted-space"> </span>execution fails<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4r
 em] px-1 py-px text-[0.9rem]">existsByJobName</code>, so<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">StuckJobExecutorServiceImpl</code><span 
class="Apple-converted-space"> </span>treats it as a plain tasklet job — 
stuck-job recovery diverges from Loan.</li></ol><p 
class="font-claude-response-body break-words whitespace-normal" 
style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; 
font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 
2; text-align: start; text-indent: 0px; text-transform: none; white-space: 
normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; 
text-decoration-line: none; text-decoration-thickness: auto; 
text-decoration-style: solid;">Also worth fixing:<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-da
 nger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">ApplySavingsLockTasklet</code>/<code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">ChunkProcessingSavingsItemListener</code><span 
class="Apple-converted-space"> </span>mutate a shared<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">TransactionTemplate</code><span 
class="Apple-converted-space"> </span>via<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">setPropagationBehavior(...)</code><span 
class="Apple-converted-space"> </span>per call (diff 450, 766) under the 
multi-threaded worker step — a data race the Loan path avoids by using a 
pre-configured
  bean; and<span class="Apple-converted-space"> </span><code 
class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 
whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">AbstractSavingsItemReader</code><span 
class="Apple-converted-space"> </span>throws raw<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">RuntimeException</code><span 
class="Apple-converted-space"> </span>instead of a typed not-found exception 
(loses meaning in the recorded lock stacktrace).</p><h4 class="text-text-100 
mt-2 -mb-1 text-base font-bold" style="caret-color: rgb(0, 0, 0); color: rgb(0, 
0, 0); font-style: normal; font-variant-caps: normal; letter-spacing: normal; 
orphans: 2; text-align: start; text-indent: 0px; text-transform: none; 
white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 
0px; text-decoration-line: none; te
 xt-decoration-thickness: auto; text-decoration-style: 
solid;">Recommendation</h4><p class="font-claude-response-body break-words 
whitespace-normal" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); 
font-style: normal; font-variant-caps: normal; font-weight: 400; 
letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; 
text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; 
-webkit-text-stroke-width: 0px; text-decoration-line: none; 
text-decoration-thickness: auto; text-decoration-style: solid;">Reframe the PR 
around the existing<span class="Apple-converted-space"> </span><code 
class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 
whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">fineract-cob</code><span class="Apple-converted-space"> 
</span>generics rather than parallel copies: extend<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whites
 pace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">CommonPartitioner</code>,<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">AbstractLockingService</code>,<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">ApplyCommonLockTasklet</code>,<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">UnlockProcessedAccountsTasklet&lt;T&gt;</code>,<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">AbstractLoanItemListener&lt;T&gt;</code><span class="Apple-c
 onverted-space"> </span>(rename it),<span class="Apple-converted-space"> 
</span><code class="bg-text-200/5 border border-0.5 border-border-300 
text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">BeforeStepLockingItemReaderHelper</code>, and reuse<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">LockOwner</code>/<code 
class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 
whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">AccountLockService</code>. Then add the missing artifacts Loan 
ships as standard — the lock-table migration, the<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">job</code><span 
class="Apple-converted-space"> </span>row, the business-st
 ep seed, at least one<span class="Apple-converted-space"> </span><code 
class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 
whitespace-pre-wrap rounded-[0.4rem] px-1 py-px 
text-[0.9rem]">SavingsCOBBusinessStep</code><span 
class="Apple-converted-space"> </span>impl, and the<span 
class="Apple-converted-space"> </span><code class="bg-text-200/5 border 
border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap 
rounded-[0.4rem] px-1 py-px text-[0.9rem]">PartitionedJob</code><span 
class="Apple-converted-space"> </span>enum entry. That gets you the uniform, 
single-maintenance-point COB you're describing, and every future COB fix 
applies to both account types at once.</p>


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