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>

@NoRepositoryBean public interface NotificationOutboxRepositoryBase<T extends NotificationOutboxBase> extends org.springframework.data.jpa.repository.JpaRepository<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 Type
    Method
    Description
    int
    claim(UUID id, Instant now, Instant reclaimAt)
    原子認領一列供遞送:到期(nextAttemptAt <= now)且處於可認領狀態 (PENDING / FAILED,或 nextAttemptAt 已逾期的滯留 SENDING)者,一次 UPDATE 翻為 SENDING 並把 nextAttemptAt 推遲至 reclaimAt(= now + claimTimeout)。
    依去重鍵查找既有列(冪等去重用)。租戶範圍由 @TenantId filter 自動限縮 (請求緒=本租戶;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, save

    Methods inherited from interface org.springframework.data.jpa.repository.JpaRepository

    deleteAllByIdInBatch, deleteAllInBatch, deleteAllInBatch, deleteInBatch, findAll, findAll, flush, getById, getOne, getReferenceById, saveAllAndFlush, saveAndFlush

    Methods inherited from interface org.springframework.data.repository.ListCrudRepository

    findAll, findAllById, saveAll

    Methods inherited from interface org.springframework.data.repository.ListPagingAndSortingRepository

    findAll

    Methods inherited from interface org.springframework.data.repository.PagingAndSortingRepository

    findAll

    Methods inherited from interface org.springframework.data.repository.query.QueryByExampleExecutor

    count, exists, findAll, findBy, findOne
  • Method Details

    • findByDedupeKey

      Optional<T> findByDedupeKey(String dedupeKey)
      依去重鍵查找既有列(冪等去重用)。租戶範圍由 @TenantId filter 自動限縮 (請求緒=本租戶;root 緒不限縮——root 發送本就無租戶歸屬)
      Parameters:
      dedupeKey - 去重鍵
      Returns:
      既有列(若有)
    • 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 - 目標列 ID
      now - 當下時間(判定到期用)
      reclaimAt - 認領後的下次可重認領時間(遞送逾此未完成即視為滯留)
      Returns:
      受影響列數(1 = 認領成功,0 = 未認領)