Interface NotificationOutboxRepositoryBase<T extends NotificationOutboxBase>
- Type Parameters:
T- 應用宣告的具體 Outbox entity(繼承NotificationOutboxBase)
- All Superinterfaces:
org.springframework.data.repository.CrudRepository<T,UUID>, org.springframework.data.jpa.repository.JpaRepository<T, UUID>, org.springframework.data.repository.ListCrudRepository<T, UUID>, org.springframework.data.repository.ListPagingAndSortingRepository<T, UUID>, org.springframework.data.repository.PagingAndSortingRepository<T, UUID>, org.springframework.data.repository.query.QueryByExampleExecutor<T>, org.springframework.data.repository.Repository<T, UUID>
通知 Outbox 的資料存取基底
依 ADR-017:jar 不擁有
具體 @Entity,本介面為 @NoRepositoryBean 泛型基底,由應用帶入具體 entity 型參成為可注入
repository。@Query 以 SpEL #{#entityName} 指涉應用的 entity 名,不硬編類名。
查詢不帶 tenantId(決策三):findByDedupeKey(String) 為單欄查詢——tenant 專案的應用 entity 帶
@TenantId,請求緒的去重查詢由 Hibernate 於 Session 建構時自動限縮本租戶;findDueForDispatch(Collection, Instant, Pageable)
在背景輪詢器(無 TenantContext = root)呼叫時 filter 跳過、天然跨租戶撈取;ownership 專案無
租戶欄位、天然全域。claim(UUID, Instant, Instant) 原子認領一列供遞送,確保叢集多節點下同一列只被一個執行緒送出。
- Since:
- 4.0.0
-
Method Summary
Modifier and TypeMethodDescriptionint原子認領一列供遞送:到期(nextAttemptAt <= now)且處於可認領狀態 (PENDING/FAILED,或nextAttemptAt已逾期的滯留SENDING)者,一次 UPDATE 翻為SENDING並把nextAttemptAt推遲至reclaimAt(=now + claimTimeout)。findByDedupeKey(String dedupeKey) 依去重鍵查找既有列(冪等去重用)。租戶範圍由@TenantIdfilter 自動限縮 (請求緒=本租戶;root 緒不限縮——root 發送本就無租戶歸屬)findDueForDispatch(Collection<OutboxStatus> statuses, Instant now, org.springframework.data.domain.Pageable pageable) 撈取到期、可遞送的列(跨租戶;須在無 TenantContext 的執行緒呼叫)Methods inherited from interface org.springframework.data.repository.CrudRepository
count, delete, deleteAll, deleteAll, deleteAllById, deleteById, existsById, findById, saveMethods inherited from interface org.springframework.data.jpa.repository.JpaRepository
deleteAllByIdInBatch, deleteAllInBatch, deleteAllInBatch, deleteInBatch, findAll, findAll, flush, getById, getOne, getReferenceById, saveAllAndFlush, saveAndFlushMethods inherited from interface org.springframework.data.repository.ListCrudRepository
findAll, findAllById, saveAllMethods inherited from interface org.springframework.data.repository.ListPagingAndSortingRepository
findAllMethods inherited from interface org.springframework.data.repository.PagingAndSortingRepository
findAllMethods inherited from interface org.springframework.data.repository.query.QueryByExampleExecutor
count, exists, findAll, findBy, findOne
-
Method Details
-
findByDedupeKey
-
findDueForDispatch
@Query("select o from #{#entityName} o where o.status in :statuses and o.nextAttemptAt <= :now order by o.nextAttemptAt asc") List<T> findDueForDispatch(@Param("statuses") Collection<OutboxStatus> statuses, @Param("now") Instant now, org.springframework.data.domain.Pageable pageable) 撈取到期、可遞送的列(跨租戶;須在無 TenantContext 的執行緒呼叫)- Parameters:
statuses- 納入的狀態(通常PENDING+FAILED)now- 當下時間(撈nextAttemptAt <= now者)pageable- 批次大小限制(如PageRequest.of(0, batchSize))- Returns:
- 到期列,依
nextAttemptAt由舊至新
-
claim
@Transactional @Modifying(clearAutomatically=true) @Query("update #{#entityName} o set o.status = io.leandev.appfuse.notification.outbox.OutboxStatus.SENDING, o.nextAttemptAt = :reclaimAt, o.lastModifiedDate = :now where o.id = :id and o.nextAttemptAt <= :now and o.status in (io.leandev.appfuse.notification.outbox.OutboxStatus.PENDING, io.leandev.appfuse.notification.outbox.OutboxStatus.FAILED, io.leandev.appfuse.notification.outbox.OutboxStatus.SENDING)") int claim(@Param("id") UUID id, @Param("now") Instant now, @Param("reclaimAt") Instant reclaimAt) 原子認領一列供遞送:到期(
nextAttemptAt <= now)且處於可認領狀態 (PENDING/FAILED,或nextAttemptAt已逾期的滯留SENDING)者,一次 UPDATE 翻為SENDING並把nextAttemptAt推遲至reclaimAt(=now + claimTimeout)。回傳受影響列數即認領結果:
1= 本執行緒認領成功、應繼續遞送;0= 別人已認領 / 已達終態 / 尚未到期 → 略過。因是資料庫層的條件式原子 UPDATE,fast-path 與任意數量的輪詢節點競爭同一列時, 至多一個得到1,故不會重複遞送(叢集安全)。認領把
nextAttemptAt推到未來,遞送中的SENDING不會被其他執行緒重認領;若遞送節點崩潰、 列滯留SENDING,逾reclaimAt後本查詢的nextAttemptAt <= now條件再度成立、可被重新認領。 因 JPQL bulk update 繞過生命週期回呼,故明確設定lastModifiedDate。- Parameters:
id- 目標列 IDnow- 當下時間(判定到期用)reclaimAt- 認領後的下次可重認領時間(遞送逾此未完成即視為滯留)- Returns:
- 受影響列數(
1= 認領成功,0= 未認領)
-