Package com.ultikits.ultitools.utils
Class CommandDedupeSet
java.lang.Object
com.ultikits.ultitools.utils.CommandDedupeSet
The ids of commands the UltiCloud gateway delivered recently, so a redelivered command is acknowledged but not run
twice (D-16, D-17). An id is remembered until either bound is reached first: the most recent
DEFAULT_DEDUPE_MAX ids, or DEFAULT_DEDUPE_TTL_MS after it was first seen. An id older than the TTL
(strictly more than the TTL ago) or pushed out by newer ids is first-seen again.
Thread safety. Every method is synchronized on this set and every eviction runs inside the mutation
that caused it; the monitor is a leaf lock. Dirty tracking matches CloudOutbox: a mutation sets the flag and
increments a modification count, and CloudStateStore clears the flag only if nothing changed since its
snapshot.
Receipts (plan 22-21, S-59, S-65). An id may carry one receipt: the result payload the framework answered a
player.link.completed with, so a redelivery is answered again from the record without asking the module.
A receipt lives and dies with its id -- it is evicted by the same count bound and expires with the same TTL -- and
is at most MAX_RECEIPT_BYTES of compact JSON; a larger one is not recorded.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescription(package private) static final classOne remembered command id, when it was first seen and its receipt, if any. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final LongSupplier(package private) static final intThe default number of remembered ids;welcome.limits.commandDedupeMaxoverrides it (D-13, 22-08).(package private) static final longThe default memory of one id, 24 h;welcome.limits.commandDedupeTtlSecondsoverrides it (D-13).private boolean(package private) static final intThe largest receipt recorded, 4 KiB of compact UTF-8 JSON (S-65).private intprivate longId to its receipt; every key is also a key ofseen.private final LinkedHashMap<String, Long> Id to first-seen time, in the order the ids were first seen.private long -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate static voidcheckLimits(int maxEntries, long ttlMillis) (package private) voidclear()Forgets every id.(package private) voidClears the dirty flag unconditionally.(package private) voidclearDirtyIfUnchanged(long expectedModCount) Clears the dirty flag only if nothing changed sinceexpectedModCountwas read.private booleanprivate booleanexpire(long now) (package private) booleanRecordsidand reports whether it is new.(package private) static booleanfitsReceipt(com.google.gson.JsonObject receipt) (package private) booleanisDirty()(package private) longmodCount()(package private) com.google.gson.JsonObjectreceiptFor(String id) (package private) booleanrecordReceipt(String id, com.google.gson.JsonObject receipt) Recordsreceiptforid, remembering the id as first seen now when it is not remembered yet (a completion is recorded only once it is answered).(package private) voidrestore(List<CommandDedupeSet.Seen> loaded) Replaces the content with ids loaded from the state file, applying both bounds.(package private) voidsetLimits(int newMaxEntries, long newTtlMillis) Changes both bounds and applies them at once.(package private) List<CommandDedupeSet.Seen> snapshot()private voidtouch()
-
Field Details
-
DEFAULT_DEDUPE_MAX
static final int DEFAULT_DEDUPE_MAXThe default number of remembered ids;welcome.limits.commandDedupeMaxoverrides it (D-13, 22-08).- See Also:
-
DEFAULT_DEDUPE_TTL_MS
static final long DEFAULT_DEDUPE_TTL_MSThe default memory of one id, 24 h;welcome.limits.commandDedupeTtlSecondsoverrides it (D-13).- See Also:
-
MAX_RECEIPT_BYTES
static final int MAX_RECEIPT_BYTESThe largest receipt recorded, 4 KiB of compact UTF-8 JSON (S-65).- See Also:
-
clock
-
seen
Id to first-seen time, in the order the ids were first seen. -
receipts
Id to its receipt; every key is also a key ofseen. -
maxEntries
private int maxEntries -
ttlMillis
private long ttlMillis -
dirty
private boolean dirty -
modCount
private long modCount
-
-
Constructor Details
-
CommandDedupeSet
CommandDedupeSet(int maxEntries, long ttlMillis, LongSupplier clock) - Parameters:
maxEntries- the most ids remembered, at least 1ttlMillis- how long one id is remembered, at least 1 msclock- milliseconds since the Unix epoch
-
-
Method Details
-
checkLimits
private static void checkLimits(int maxEntries, long ttlMillis) -
firstSeen
Recordsidand reports whether it is new.- Parameters:
id- a command's envelope id- Returns:
truethe first timeidis seen within both bounds,falsefor a repeat
-
setLimits
void setLimits(int newMaxEntries, long newTtlMillis) Changes both bounds and applies them at once.- Parameters:
newMaxEntries- the most ids remembered, at least 1newTtlMillis- how long one id is remembered, at least 1 ms
-
snapshot
List<CommandDedupeSet.Seen> snapshot()- Returns:
- the remembered ids with their first-seen times, oldest first
-
restore
Replaces the content with ids loaded from the state file, applying both bounds. Marked dirty only when the bounds removed something, so a load alone does not cause a rewrite.- Parameters:
loaded- the ids, oldest first; a repeated id keeps its first occurrence
-
clear
void clear()Forgets every id. -
recordReceipt
Recordsreceiptforid, remembering the id as first seen now when it is not remembered yet (a completion is recorded only once it is answered). A receipt overMAX_RECEIPT_BYTESis not recorded and the set is left unchanged.- Parameters:
id- the envelope id the receipt answersreceipt- the result payload; not copied, so the caller must not mutate it afterwards- Returns:
truewhen recorded,falsewhen the receipt is too large
-
receiptFor
- Parameters:
id- an envelope id- Returns:
- its receipt, or
nullwhen the id has none or is no longer remembered (expired or evicted); the caller must not mutate it
-
fitsReceipt
static boolean fitsReceipt(com.google.gson.JsonObject receipt) - Parameters:
receipt- a candidate receipt- Returns:
- whether its compact UTF-8 JSON is at most
MAX_RECEIPT_BYTES
-
isDirty
boolean isDirty()- Returns:
- whether anything changed since the last successful write
-
clearDirty
void clearDirty()Clears the dirty flag unconditionally. -
modCount
long modCount()- Returns:
- the modification count, for
clearDirtyIfUnchanged(long)
-
clearDirtyIfUnchanged
void clearDirtyIfUnchanged(long expectedModCount) Clears the dirty flag only if nothing changed sinceexpectedModCountwas read.- Parameters:
expectedModCount- themodCount()captured with the persisted snapshot
-
expire
private boolean expire(long now) -
evictToMax
private boolean evictToMax() -
touch
private void touch()
-