Interface CleanupScanUnitDAO

All Superinterfaces:
org.springframework.data.repository.CrudRepository<CleanupScanUnitEntity,Long>, org.springframework.data.jpa.repository.JpaRepository<CleanupScanUnitEntity,Long>, org.springframework.data.repository.ListCrudRepository<CleanupScanUnitEntity,Long>, org.springframework.data.repository.ListPagingAndSortingRepository<CleanupScanUnitEntity,Long>, org.springframework.data.repository.PagingAndSortingRepository<CleanupScanUnitEntity,Long>, org.springframework.data.repository.query.QueryByExampleExecutor<CleanupScanUnitEntity>, org.springframework.data.repository.Repository<CleanupScanUnitEntity,Long>

public interface CleanupScanUnitDAO extends org.springframework.data.jpa.repository.JpaRepository<CleanupScanUnitEntity,Long>
  • Method Summary

    Modifier and Type
    Method
    Description
    long
    countByCampaignId(long campaignId)
     
    long
    countByCampaignIdAndState(long campaignId, String state)
     
    countByState(long campaignId)
    Per-STATE unit counts of a campaign, in ONE grouped query (rows: state, unit count) — never by loading the unit rows, whose number is one per space plus one per /Users bucket.
    countFailuresByReason(long campaignId, String state)
    Per-reason unit counts of a campaign's failed subtrees, in ONE grouped query (rows: failure reason, unit count) — the very shape CleanupCampaignItemDAO#countFailuresByReason answers for items, so the console renders both through the same block.
    long
    countSettledFailures(long campaignId, String state, long maxAttemptCount)
    Units of a campaign whose walk failed and which spent every attempt they had: they are SETTLED, so they no longer hold the dry-run's completion back — and they are exactly what makes the produced report INCOMPLETE.
    void
    deleteByCampaignId(long campaignId)
    Drops every unit row of a campaign, in ONE statement (declared, not derived — see CleanupCampaignItemDAO#deleteByCampaignId for why that matters).
    findByState(long campaignId, String state)
    The units of a campaign in one given state, oldest id first.
    Campaign ids that have unit rows but NO campaign row: the scan-unit half of CleanupCampaignItemDAO#findOrphanCampaignIds, swept at startup for the same reason.
    findUnitPathsByCampaignId(long campaignId)
    Unit PATHS of a campaign, as a projection: planning only needs to know which paths already exist, and loading whole rows to read one column of each would be wasted work on every resume.
    findUnitsToProcess(long campaignId, String doneState, String failedState, long maxAttemptCount)
    The units of a campaign still to process, oldest id first: everything but DONE, MINUS the settled-failed ones — a unit that FAILED after spending every walk attempt it had.
    findUnitsWithEvalFailures(long campaignId, org.springframework.data.domain.Pageable pageable)
    The units of a campaign that lost at least one node, worst first.
    long
    maxAttemptCount(long campaignId)
    Deepest walk attempt any unit of a campaign has spent — how many times the most-retried subtree was re-walked, which is what tells an administrator that a scan is going round in circles rather than progressing.
    long
    sumEvalFailureCount(long campaignId)
    Nodes the scan of a campaign walked but could not EVALUATE, summed over its units — the count of files silently missing from its report.
    long
    sumScannedCount(long campaignId)
    Scanned-nodes sum over the units of a campaign — the progress numerator, computed by the database.
    long
    sumTotalCount(long campaignId)
    Counted-nodes sum over the units of a campaign — the ETA denominator.

    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

    • findUnitsToProcess

      @Query("SELECT u FROM CleanupScanUnit u WHERE u.campaignId = :campaignId AND u.state <> :doneState AND NOT (u.state = :failedState AND u.attemptCount >= :maxAttemptCount) ORDER BY u.id ASC") List<CleanupScanUnitEntity> findUnitsToProcess(@Param("campaignId") long campaignId, @Param("doneState") String doneState, @Param("failedState") String failedState, @Param("maxAttemptCount") long maxAttemptCount)
      The units of a campaign still to process, oldest id first: everything but DONE, MINUS the settled-failed ones — a unit that FAILED after spending every walk attempt it had. So a unit left RUNNING by an interrupted run and a FAILED one with attempts LEFT are both picked up again, each from its own persisted path checkpoint, while a subtree already proved unreadable is never walked again.

      The exclusion is STATE-AWARE — state = FAILED AND attemptCount >= :maxAttemptCount, never a bare attemptCount < :maxAttemptCount — and that is the trap of this query, not a stylistic choice: a unit interrupted three times is RUNNING with three attempts spent, so a state-blind bound would drop it from the work list while it is neither DONE nor settled-FAILED. It could then never reach an outcome, and CleanupScanService#completeCampaign would hold the dry-run open forever over a unit nothing walks.

    • findUnitPathsByCampaignId

      @Query("SELECT u.unitPath FROM CleanupScanUnit u WHERE u.campaignId = :campaignId") List<String> findUnitPathsByCampaignId(@Param("campaignId") long campaignId)
      Unit PATHS of a campaign, as a projection: planning only needs to know which paths already exist, and loading whole rows to read one column of each would be wasted work on every resume.
    • countByCampaignId

      long countByCampaignId(long campaignId)
    • countByCampaignIdAndState

      long countByCampaignIdAndState(long campaignId, String state)
    • countSettledFailures

      @Query("SELECT COUNT(u) FROM CleanupScanUnit u WHERE u.campaignId = :campaignId AND u.state = :state AND u.attemptCount >= :maxAttemptCount") long countSettledFailures(@Param("campaignId") long campaignId, @Param("state") String state, @Param("maxAttemptCount") long maxAttemptCount)
      Units of a campaign whose walk failed and which spent every attempt they had: they are SETTLED, so they no longer hold the dry-run's completion back — and they are exactly what makes the produced report INCOMPLETE.

      Its >= comparison must stay the EXACT complement of the exclusion in findUnitsToProcess(long, java.lang.String, java.lang.String, long): the units this counts as settled are the units that one stops handing out, so a unit falling between the two would be neither walked nor settled — a dry-run nothing can ever finish.

    • countFailuresByReason

      @Query("SELECT u.failureReason, COUNT(u) FROM CleanupScanUnit u WHERE u.campaignId = :campaignId AND u.state = :state GROUP BY u.failureReason") List<Object[]> countFailuresByReason(@Param("campaignId") long campaignId, @Param("state") String state)
      Per-reason unit counts of a campaign's failed subtrees, in ONE grouped query (rows: failure reason, unit count) — the very shape CleanupCampaignItemDAO#countFailuresByReason answers for items, so the console renders both through the same block.
    • deleteByCampaignId

      @Modifying @Transactional @Query("DELETE FROM CleanupScanUnit u WHERE u.campaignId = :campaignId") void deleteByCampaignId(@Param("campaignId") long campaignId)
      Drops every unit row of a campaign, in ONE statement (declared, not derived — see CleanupCampaignItemDAO#deleteByCampaignId for why that matters). Only ever called when the campaign itself is being deleted, and only from a state no worker can be walking in.
    • findOrphanCampaignIds

      @Query("SELECT DISTINCT u.campaignId FROM CleanupScanUnit u WHERE u.campaignId NOT IN (SELECT c.id FROM CleanupCampaign c)") List<Long> findOrphanCampaignIds()
      Campaign ids that have unit rows but NO campaign row: the scan-unit half of CleanupCampaignItemDAO#findOrphanCampaignIds, swept at startup for the same reason.
    • sumEvalFailureCount

      @Query("SELECT COALESCE(SUM(u.evalFailureCount), 0) FROM CleanupScanUnit u WHERE u.campaignId = :campaignId") long sumEvalFailureCount(@Param("campaignId") long campaignId)
      Nodes the scan of a campaign walked but could not EVALUATE, summed over its units — the count of files silently missing from its report.
    • findUnitsWithEvalFailures

      @Query("SELECT u FROM CleanupScanUnit u WHERE u.campaignId = :campaignId AND u.evalFailureCount > 0 ORDER BY u.evalFailureCount DESC, u.id ASC") List<CleanupScanUnitEntity> findUnitsWithEvalFailures(@Param("campaignId") long campaignId, org.springframework.data.domain.Pageable pageable)
      The units of a campaign that lost at least one node, worst first. Bounded by the caller: a campaign can plan one unit per space, and a repository-wide problem makes every one of them fail.
    • countByState

      @Query("SELECT u.state, COUNT(u) FROM CleanupScanUnit u WHERE u.campaignId = :campaignId GROUP BY u.state") List<Object[]> countByState(@Param("campaignId") long campaignId)
      Per-STATE unit counts of a campaign, in ONE grouped query (rows: state, unit count) — never by loading the unit rows, whose number is one per space plus one per /Users bucket.
    • maxAttemptCount

      @Query("SELECT COALESCE(MAX(u.attemptCount), 0) FROM CleanupScanUnit u WHERE u.campaignId = :campaignId") long maxAttemptCount(@Param("campaignId") long campaignId)
      Deepest walk attempt any unit of a campaign has spent — how many times the most-retried subtree was re-walked, which is what tells an administrator that a scan is going round in circles rather than progressing.
    • findByState

      @Query("SELECT u FROM CleanupScanUnit u WHERE u.campaignId = :campaignId AND u.state = :state ORDER BY u.id ASC") List<CleanupScanUnitEntity> findByState(@Param("campaignId") long campaignId, @Param("state") String state)
      The units of a campaign in one given state, oldest id first. Used for the RUNNING ones only, so the result is bounded by the reader count — do NOT reach for it with DONE on a large campaign.
    • sumScannedCount

      @Query("SELECT COALESCE(SUM(u.scannedCount), 0) FROM CleanupScanUnit u WHERE u.campaignId = :campaignId") long sumScannedCount(@Param("campaignId") long campaignId)
      Scanned-nodes sum over the units of a campaign — the progress numerator, computed by the database. NEVER by loading the unit rows: the numerator is re-read on every resume, and a run only ever needs the total.
    • sumTotalCount

      @Query("SELECT COALESCE(SUM(u.totalCount), 0) FROM CleanupScanUnit u WHERE u.campaignId = :campaignId") long sumTotalCount(@Param("campaignId") long campaignId)
      Counted-nodes sum over the units of a campaign — the ETA denominator.