package sample.usecase; import java.time.LocalDate; import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import lombok.extern.slf4j.Slf4j; import sample.context.lock.IdLockHandler.LockType; import sample.context.orm.DefaultRepository; import sample.model.asset.*; import sample.model.asset.CashInOut.FindCashInOut; /** * 資産ドメインに対する社内ユースケース処理。 */ @Service @Slf4j public class AssetAdminService extends ServiceSupport { /** * 振込入出金依頼を検索します。 * low: 口座横断的なので割り切りでREADロックはかけません。 */ @Transactional(DefaultRepository.BeanNameTx) public List<CashInOut> findCashInOut(final FindCashInOut p) { return CashInOut.find(rep(), p); } /** * 振込出金依頼を締めます。 */ public void closingCashOut() { audit().audit("振込出金依頼の締め処理をする", () -> tx(() -> closingCashOutInTx())); } private void closingCashOutInTx() { //low: 以降の処理は口座単位でfilter束ねしてから実行する方が望ましい。 //low: 大量件数の処理が必要な時はそのままやるとヒープが死ぬため、idソートでページング分割して差分実行していく。 CashInOut.findUnprocessed(rep()).forEach(cio -> { //low: TX内のロックが適切に動くかはIdLockHandlerの実装次第。 // 調整が難しいようなら大人しく営業停止時間(IdLock必要な処理のみ非活性化されている状態)を作って、 // ロック無しで一気に処理してしまう方がシンプル。 idLock().call(cio.getAccountId(), LockType.Write, () -> { try { cio.process(rep()); //low: SQLの発行担保。扱う情報に相互依存が無く、セッションキャッシュはリークしがちなので都度消しておく。 rep().flushAndClear(); } catch (Exception e) { log.error("[" + cio.getId() + "] 振込出金依頼の締め処理に失敗しました。", e); try { cio.error(rep()); rep().flush(); } catch (Exception ex) { //low: 2重障害(恐らくDB起因)なのでloggerのみの記載に留める } } }); }); } /** * キャッシュフローを実現します。 * <p>受渡日を迎えたキャッシュフローを残高に反映します。 */ public void realizeCashflow() { audit().audit("キャッシュフローを実現する", () -> tx(() -> realizeCashflowInTx())); } private void realizeCashflowInTx() { //low: 日回し後の実行を想定 LocalDate day = dh().time().day(); for (final Cashflow cf : Cashflow.findDoRealize(rep(), day)) { idLock().call(cf.getAccountId(), LockType.Write, () -> { try { cf.realize(rep()); rep().flushAndClear(); } catch (Exception e) { log.error("[" + cf.getId() + "] キャッシュフローの実現に失敗しました。", e); try { cf.error(rep()); rep().flush(); } catch (Exception ex) { } } }); } } }