Interface CaldavPendingPushDAO

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

public interface CaldavPendingPushDAO extends org.springframework.data.jpa.repository.JpaRepository<CaldavPendingPushEntity,Long>
Persistence access to the writes eXo owes but has not made.

Every listing is bounded, like every other listing in this add-on — and here the bound carries a second meaning: this table is empty once everything has landed, so a query able to return "all of it" would be a query whose cost is a backlog nobody is watching.

  • Method Summary

    Modifier and Type
    Method
    Description
    long
    countAttemptable(long userIdentityId, int maxAttempts)
    How many of one account's copies are behind and still worth attempting.
    long
    countByUserIdentityId(long userIdentityId)
    How many copies of one account are behind, abandoned ones included.
    findAttemptable(long userIdentityId, int maxAttempts, org.springframework.data.domain.Pageable pageable)
    The writes still worth attempting for one account.
    findByObjectSyncId(long objectSyncId)
    The obligation recorded against one mapping row, if there is one.
    int
    recordAttempt(long id)
    Records one more refusal against an obligation.
    int
    spendBudget(long id, int attempts)
    Spends an obligation's whole attempt budget at once, so it is never read again.

    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

    • findByObjectSyncId

      Optional<CaldavPendingPushEntity> findByObjectSyncId(long objectSyncId)
      The obligation recorded against one mapping row, if there is one.

      One per copy, which is what makes recording an obligation idempotent: a meeting edited five times in a minute owes its copy one write, not five.

      Parameters:
      objectSyncId - the mapping row
      Returns:
      the obligation, when the copy is behind
    • countByUserIdentityId

      long countByUserIdentityId(long userIdentityId)
      How many copies of one account are behind, abandoned ones included.
      Parameters:
      userIdentityId - whose calendar the copies sit in
      Returns:
      the count, zero on a converged account
    • findAttemptable

      @Query("SELECT q FROM CaldavPendingPushEntity q WHERE q.userIdentityId = :userIdentityId AND q.attempts < :maxAttempts") List<CaldavPendingPushEntity> findAttemptable(@Param("userIdentityId") long userIdentityId, @Param("maxAttempts") int maxAttempts, org.springframework.data.domain.Pageable pageable)
      The writes still worth attempting for one account.

      The attempt bound sits in the query rather than in the loop that reads it, so an abandoned obligation costs nothing to skip: the row stays as the record that eXo gave up — the only place anybody can see that it did — while this pass never reads it again unless a later edit renews it.

      Spelled out rather than derived from the method name: the derived spelling would be findByUserIdentityIdAndAttemptsLessThan, whose LessThan reads as a property to anything checking that the names in a derived query exist — including this module's own repository contract test.

      Parameters:
      userIdentityId - whose calendar the copies sit in
      maxAttempts - how many refusals are argued with before stopping
      pageable - how many to take and in which order; required
      Returns:
      the obligations to attempt now
    • countAttemptable

      @Query("SELECT COUNT(q) FROM CaldavPendingPushEntity q WHERE q.userIdentityId = :userIdentityId AND q.attempts < :maxAttempts") long countAttemptable(@Param("userIdentityId") long userIdentityId, @Param("maxAttempts") int maxAttempts)
      How many of one account's copies are behind and still worth attempting.

      The same predicate as findAttemptable(long, int, org.springframework.data.domain.Pageable), counted rather than listed, and it has to stay the same predicate: this number is shown to the user as "copies eXo has not managed to write yet", and a count that included the obligations eXo has given up on would promise a retry that is never coming. Those are a different sentence, said once at WARN to whoever runs the platform.

      Spelled out as a query for the reason findAttemptable(long, int, org.springframework.data.domain.Pageable) is: the derived spelling would carry a LessThan that reads as a property name to anything checking this repository's method names.

      Parameters:
      userIdentityId - whose calendar the copies sit in
      maxAttempts - how many refusals are argued with before stopping
      Returns:
      the count, zero on a converged account
    • recordAttempt

      @Modifying(flushAutomatically=true) @Transactional @Query("UPDATE CaldavPendingPushEntity q SET q.attempts = q.attempts + 1 WHERE q.id = :id") int recordAttempt(@Param("id") long id)
      Records one more refusal against an obligation.

      An increment in the database rather than a read, an add and a save: the counter bounds how hard eXo argues with one server, and two passes racing must not both write "attempt 3".

      Parameters:
      id - the obligation
      Returns:
      how many rows were updated; zero when it has since been settled
    • spendBudget

      @Modifying(flushAutomatically=true) @Transactional @Query("UPDATE CaldavPendingPushEntity q SET q.attempts = :attempts WHERE q.id = :id") int spendBudget(@Param("id") long id, @Param("attempts") int attempts)
      Spends an obligation's whole attempt budget at once, so it is never read again.

      For a refusal no amount of waiting can change. The budget exists to bound how hard eXo argues with a calendar server having a bad day; a copy eXo declines to write because it belongs to another user is not that, and four further identical refusals over twenty minutes tell nobody anything. Set rather than incremented, so the row leaves the attemptable set on the first refusal whatever it had counted before.

      Parameters:
      id - the obligation
      attempts - the bound to write, which is the configured maximum
      Returns:
      how many rows were updated; zero when it has since been settled