Class CaldavPendingPushStorage
No business logic: which copies are owed a write, how hard to try and when to stop belong to the service. What lives here is the mechanical part — that an obligation is one per copy, so recording the same one twice replaces it rather than queueing it, and that renewing it resets the attempt count because a new edit deserves its own patience.
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionbooleanabandoned(long id, org.exoplatform.caldav.model.PendingPushKind kind, int maxAttempts) Records that an obligation is given up on, without counting toward the bound first, unless it has been settled or replaced with the other kind since it was read.List<org.exoplatform.caldav.model.PendingPush> attemptable(long userIdentityId, int maxAttempts, int limit) What one account is owed and is still worth attempting, oldest first.org.exoplatform.caldav.model.PendingPushowe(long objectSyncId, long userIdentityId, org.exoplatform.caldav.model.PendingPushKind kind, Long localEventId, String icsUid) Records that one copy is behind, replacing whatever was owed to it before.longowed(long userIdentityId) How many copies of one account are behind, abandoned ones included.longowedAndStillTrying(long userIdentityId, int maxAttempts) How many copies of one account are behind and still being argued for.Optional<org.exoplatform.caldav.model.PendingPush> owedTo(long objectSyncId) What is owed to one copy as it stands now.booleanrefused(long id, org.exoplatform.caldav.model.PendingPushKind kind) Records that one more attempt was refused, unless the obligation has been settled or replaced with the other kind since it was read.removalsOwed(Collection<Long> objectSyncIds) Which of these mapping rows are still owed a removal, abandoned or not.voidsettled(long objectSyncId, org.exoplatform.caldav.model.PendingPushKind kind) Forgets what was owed to one copy, because a write of that kind landed.
-
Constructor Details
-
CaldavPendingPushStorage
public CaldavPendingPushStorage()
-
-
Method Details
-
owe
@Transactional public org.exoplatform.caldav.model.PendingPush owe(long objectSyncId, long userIdentityId, org.exoplatform.caldav.model.PendingPushKind kind, Long localEventId, String icsUid) Records that one copy is behind, replacing whatever was owed to it before.Replacing, not queueing, and the attempt count goes back to zero with it. Both follow from what an obligation says: not "this write failed" but "this copy does not yet show what eXo holds". Five edits in a minute leave one write owed, and the latest instruction is the one that describes the copy — a rewrite recorded after a removal would otherwise put back a meeting somebody destroyed.
The lookup before the write is a check-then-act, and the database is what settles it. Two listener threads carrying two edits of the same meeting can both read "nothing owed" before either has written, and the unique constraint on the mapping row is what makes the outcome one row rather than two — the loser's insert is refused and its caller says so. Nothing is lost by that: the winner's row already records the same instruction about the same copy. The only case where the two differ is an edit and a deletion of one meeting in the same instant, and there the refusal is visible in the log rather than silent.
- Parameters:
objectSyncId- the mapping row whose copy is behinduserIdentityId- whose calendar the copy sits inkind- whether the copy has to be written again or removedlocalEventId- the eXo event to render, null for a removalicsUid- the iCalendar identity a removal addresses the object by- Returns:
- the obligation as it now stands
-
settled
@Transactional public void settled(long objectSyncId, org.exoplatform.caldav.model.PendingPushKind kind) Forgets what was owed to one copy, because a write of that kind landed.By the mapping row rather than by the obligation's own identifier: the caller settling a copy knows which copy it settled, and an obligation of the same kind renewed in the meantime goes too. A rewrite renders the event as agenda holds it when the write reads it, so it carries every edit agenda saved before that read; one saved after it is not carried, and is left to that edit's own write, which this write overwrites when that one lands before this one reads the copy's version.
Only of that kind. A rewrite landing while a removal was recorded for the same copy, or a removal landing while a rewrite was, carried out an instruction that no longer stands, and the obligation recorded since is left for whoever recorded it or the next retry pass. One statement, so a kind changed by another thread between a read and the deletion is never deleted with it.
- Parameters:
objectSyncId- the mapping row whose copy was writtenkind- the kind of write that landed
-
owedTo
What is owed to one copy as it stands now.Read from the database on each call: the retry pass asks it just before carrying out an obligation it read in a batch, which another thread may have settled or replaced since.
- Parameters:
objectSyncId- the mapping row- Returns:
- the obligation recorded against it, empty when nothing is owed
-
refused
@Transactional public boolean refused(long id, org.exoplatform.caldav.model.PendingPushKind kind) Records that one more attempt was refused, unless the obligation has been settled or replaced with the other kind since it was read.- Parameters:
id- the obligationkind- the kind of write that was refused- Returns:
- true when the refusal was counted
-
abandoned
@Transactional public boolean abandoned(long id, org.exoplatform.caldav.model.PendingPushKind kind, int maxAttempts) Records that an obligation is given up on, without counting toward the bound first, unless it has been settled or replaced with the other kind since it was read.- Parameters:
id- the obligationkind- the kind of write given up onmaxAttempts- the configured bound, written whole- Returns:
- true when the obligation was given up on
-
attemptable
public List<org.exoplatform.caldav.model.PendingPush> attemptable(long userIdentityId, int maxAttempts, int limit) What one account is owed and is still worth attempting, oldest first.Oldest first because a backlog is drained rather than shuffled: a copy that has been wrong the longest is the one somebody is most likely to be acting on.
- Parameters:
userIdentityId- whose calendar the copies sit inmaxAttempts- how many refusals are argued with before stoppinglimit- how many to take in one pass- Returns:
- the obligations to attempt now, possibly none
-
removalsOwed
Which of these mapping rows are still owed a removal, abandoned or not.Asked once per edit or answer, before a rewrite is recorded over the same rows, in chunks of 500. The bound is this class's own, not an engine's: the holders of a meeting are not bounded, and no statement's
INlist carries more identifiers than that, however many there are.- Parameters:
objectSyncIds- the mapping rows- Returns:
- the mapping rows among them owed a removal, empty when none are
-
owed
public long owed(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 an account whose copies all landed
-
owedAndStillTrying
public long owedAndStillTrying(long userIdentityId, int maxAttempts) How many copies of one account are behind and still being argued for.Deliberately not
owed(long): that one counts every row, the abandoned ones included, which is the right number for a report about the store and the wrong one for a sentence telling somebody to wait.- Parameters:
userIdentityId- whose calendar the copies sit inmaxAttempts- how many refusals are argued with before stopping- Returns:
- the count, zero on an account whose copies all landed
-