- All Implemented Interfaces:
Job
Handles the lifecycle of lease set publication including:
- Initial publication after sufficient uptime (deferred until target tunnels built)
- Periodic republishing before lease expiration (default 5 min)
- On-success global fail count reset
- Retry with exponential backoff on failure
- Floodfill verification after repeated failures
- Cleanup when the client is no longer local
Thread-safe via concurrent maps across instances.
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate classHandles a publish timeout, retrying with floodfill verification on recurring failures, or cancelling when a newer lease set appeared locally.private classFired on a successful store, resetting the global fail counter and clearing the first-publish gate so later renewals proceed immediately.Field Summary
Modifier and TypeFieldDescriptionprivate final HashDestination hash.private final KademliaNetworkDatabaseFacadeKademlia network database facade instance.private static final ConcurrentHashMap<Hash, Long> When the first publish was deferred, per destination, cleared on success or on the first publish timeout.private static final ConcurrentHashMap<Hash, AtomicInteger> Persistent per-destination store failure count, never reset, surviving job instances, used to decide when to do the expensive floodfill verification.private static longWhen the stale entry cleanup last ran, to guard against redundant sweeps.private static final ConcurrentHashMap<Hash, Long> When this destination last ran a re-mint that could not improve anything.private static final ConcurrentHashMap<Hash, Long> Last log timestamp per destination to throttle missing-LeaseSet log messages.private static final ConcurrentHashMap<Hash, Long> Last log timestamp per destination to throttle no-requeue log messages.private longLast published time.private static final ConcurrentHashMap<Hash, Long> Last publish attempt per destination.private static final ConcurrentHashMap<Hash, Long> Last short-expiry warning per destination, for rate limiting.private static final ConcurrentHashMap<Hash, Long> Last log timestamp per destination to throttle verification log messages.private final LogClass logger.private final AtomicBooleanWhether a floodfill verification lookup is in progress.Destinations that have published successfully at least once — never defer these again.private booleanRegistered flag.private static final ConcurrentHashMap<Hash, AtomicInteger> Consecutive re-mint deferral count per destination, to bound fresh-build waiting.private static final ConcurrentHashMap<Hash, Boolean> Tracks destinations currently being retried to prevent duplicate retries.private static final ConcurrentHashMap<Hash, Integer> Consecutive supply-check deferrals per destination, bounded so a pool that never reaches the freshness threshold cannot defer its LeaseSet forever.private static final longStaleness threshold for cleaning up tracking maps.private static final longEmergency re-mint window: when the stored copy is within this much of expiring, re-mint whatever the pool holds down to a single viable lease, skipping the normal required-count gate.private static final longWindow before lease expiry to trigger a re-mint instead of flooding the dying copy.private final AtomicIntegerPer-instance retry counter for exponential backoff.private static final longMax time to defer first publish while waiting for target tunnels.private booleanWhether this job instance is promoted to high priority.(package private) static final longThe pool's own lease-eligibility floor, mirrored fromTunnelPool.LEASE_MIN_REMAINING_MS.private static final longHow long before a LeaseSet expires we start insisting the pool holds genuinely fresh tunnels, rather than minting whatever is on hand.private static final intMax verifications per destination before falling back to direct retry.private static final intConsecutive fresh-build deferrals before falling back to a thin re-mint.private static final intConsecutive supply checks a destination may defer before minting anyway.private static final longMinimum reschedule interval — prevents sub-minute flood treadmills.private static final longRetry interval after a missing local LeaseSet — long enough for the pool to build and test a replacement tunnel before we ask again.private static final StringConfig property for max publish retry delay.private static final StringConfig property for publish retry base delay.private static final StringConfig property for LeaseSet publish timeout.private static final longMinimum interval between repeated publish log messages for one destination.static final longDefault timeout for LeaseSet publication to floodfills.static final intDefault base delay before retrying a failed publish.static final intMaximum backoff delay for publish retries.private static final longMinimum gap between short-expiry warnings for one destination.Constructor Summary
ConstructorsConstructorDescriptionRepublishLeaseSetJob(RouterContext ctx, KademliaNetworkDatabaseFacade facade, Hash destHash) Creates a new job to republish a LeaseSet for the given destination.Method Summary
Modifier and TypeMethodDescriptionprivate static voidcleanupGlobalFailCount(long now) Cleanup global fail count: reset the counters of destinations no longer being tracked, assuming their publication has finished.private static voidcleanupMap(ConcurrentHashMap<Hash, Long> map, long now) Cleanup map: drop the entries whose timestamp is older than the cleanup threshold.private static voidDrop _publishedOnce entries for destinations no longer being tracked.private static voidReset re-mint deferral counters for destinations no longer tracked.private static voidCleanup stale entries.private voidClear retry in progress.private longcomputeNextRepublish(long timeUntilExpiry) Next republish delay: the configured interval floored at MIN_RESCHEDULE, but capped so the next check fires before the current LeaseSet hits the EXPIRY_WINDOW re-mint threshold.private intcountFreshLeases(LeaseSet ls, long now) Counts the leases that are still fresh.(package private) static booleaneffectiveExpiryAnomalouslyShort(long effectiveExpiry) Whether a LeaseSet expiry is short enough to indicate the inbound pool could not supply a viable lease.(package private) HashThe destination hash this job publishes for.private LeaseSetThe inbound pool's current tunnels as a re-mintable LeaseSet, or null if the client has no inbound pool or no usable leases.private static longA lease is viable for a re-mint while it has at least this much time remaining: the re-sign request, floodfill propagation, and connection establishment all need the lease alive, and a tunnel closer to expiry than this is already inside the pool's proactive replacement window, so counting it would overstate the pool's health.private intThe largest retry delay allowed.getName()Human-readable name for the job queue.private longThe time allowed for one publish.private longThe interval between republishes.private intThe delay before a retry.private intThe number of inbound leases a re-mint should carry to be useful: the inbound tunnel quantity for a server pool, 1 otherwise.Look up the tunnel nickname for a destination.private voidhandleExpiredLeaseSet(LeaseSet ls, String name) Handle expired lease set: request a fresh one and check back soon.private voidHandles a local lease set that needs publication.private voidHandles a missing lease set by asking the client to create one.private voidHandles a client that is no longer local, cleaning up and stopping publication.private voidHandles the client asking to stop publishing this lease set.private voidhandleValidLeaseSet(LeaseSet ls, String name, long now, long timeUntilExpiry) Handle valid lease set: publish it.(package private) static longineffectiveRemintDelay(long timeUntilExpiry) How long to hold off a further re-mint after one that changed nothing.private booleanDetermine if client is still a configured local tunnel even when its I2CP session is closed (close-on-idle), that is, a pool still exists.longTimestamp of the last successful publication.private booleanmaybeDeferFirstPublish(int leaseCount, int targetLeases) Whether publication was deferred while waiting for target tunnels.private booleanpoolHasAnyViableLease(LeaseSet fresh, long now) Whether the pool can sign anything at all right now.(package private) static booleanrecordPublishAttempt(ConcurrentHashMap<Hash, Long> times, Hash dest, Long previous, long now) Record that we tried to publish for this destination, and report whether the event is worth logging.private voidrefloatLeaseSet(LeaseSet storedLeaseSet, String name, long now, long timeUntilExpiry) Re-publish the lease set before it expires from the network DB.booleanAttempt to register this job with the facade.private RepublishLeaseSetJobregisterSuccessor(long delayMs) Schedules the next republish job.(package private) voidRequeues the republish after a failed publish, with exponential backoff, an aggressive first retry, and every fourth attempt promoted to high priority.voidrunJob()Republish the LeaseSet if this job is still registered, then reschedule.(package private) static booleansameLeaseTunnels(LeaseSet stored, LeaseSet fresh) Whether two lease sets advertise exactly the same tunnels.private voidscheduleRepublish(long delayMs) Schedule republish: queue the next republish cycle, unregistering the current job first so hasActiveRepublishJob() doesn't block the successor.private StringThe short hash of the local destination for logs.(package private) static booleanshouldRemint(int freshCount, int required, boolean extendsExpiry, long timeUntilExpiry, long emergencyRemintWindow) Whether a re-mint may proceed now using the pool's current LeaseSet.Methods inherited from class JobImpl
dropped, getContext, getJobId, getMadeReadyOn, getTiming, madeReady, requeue, toStringModifier and TypeMethodDescriptionvoiddropped()Default implementation does nothing.final RouterContextThe router context that this job belongs to.longgetJobId()The unique job ID for this job.longThe timestamp when this job was last made ready for execution.The timing object for this job.voidmadeReady(long now) For JobQueue only, not for external use.protected voidrequeue(long delayMs) Requeue this job to run after the specified delay.toString()
Field Details
_log
Class logger.PROP_TIMEOUT
Config property for LeaseSet publish timeout.- See Also:
PROP_RETRY_DELAY
Config property for publish retry base delay.- See Also:
PROP_MAX_RETRY_DELAY
Config property for max publish retry delay.- See Also:
REPUBLISH_LEASESET_TIMEOUT_DEFAULT
public static final long REPUBLISH_LEASESET_TIMEOUT_DEFAULTDefault timeout for LeaseSet publication to floodfills.- See Also:
RETRY_DELAY_DEFAULT
public static final int RETRY_DELAY_DEFAULTDefault base delay before retrying a failed publish.- See Also:
RETRY_MAX_DELAY_DEFAULT
public static final int RETRY_MAX_DELAY_DEFAULTMaximum backoff delay for publish retries.- See Also:
EXPIRY_WINDOW
private static final long EXPIRY_WINDOWWindow before lease expiry to trigger a re-mint instead of flooding the dying copy. Must stay below (lease cap - republish interval) — here 240s < 600s - 300s — so a freshly re-minted copy (capped at ~600s) still presents above this window at the next interval check and gets flooded directly; with an equal boundary the check lands at the knife edge and re-mints forever, starving the floodfill.- See Also:
MIN_RESCHEDULE
private static final long MIN_RESCHEDULEMinimum reschedule interval — prevents sub-minute flood treadmills.- See Also:
LEASE_SUPPLY_WINDOW
private static final long LEASE_SUPPLY_WINDOWHow long before a LeaseSet expires we start insisting the pool holds genuinely fresh tunnels, rather than minting whatever is on hand.The mint used to be purely reactive: expiry came into range, we asked the pool for a copy and signed whatever it held. Since a LeaseSet's date is the earliest lease end, one near-floor lease caps the whole copy, which is how published sets ended up at 76-120s. Starting the supply check this far ahead leaves time to wait for a build.
Three minutes is chosen against
EXPIRY_WINDOW(4m) so the check engages one interval before the renew path does, and againstEMERGENCY_REMINT_WINDOW(2m) so there is a full minute of pre-flight before the mint is allowed to become thin.- See Also:
MAX_SUPPLY_DEFERRALS
private static final int MAX_SUPPLY_DEFERRALSConsecutive supply checks a destination may defer before minting anyway.- See Also:
LEASE_ELIGIBILITY_FLOOR_MS
static final long LEASE_ELIGIBILITY_FLOOR_MSThe pool's own lease-eligibility floor, mirrored fromTunnelPool.LEASE_MIN_REMAINING_MS. A tunnel with less than this remaining is refused for publication, so a LeaseSet minted from a healthy pool cannot present below it.This is the correct yardstick for the anomaly check. An earlier version compared against the ~600s design target, which is unreachable in practice: a LeaseSet's expiry is the minimum across its leases, so holding 600s requires every lease to be simultaneously fresh, and the target sat far above the floor. That combination made the check true for essentially every LeaseSet on every pass — 129 warnings in twelve minutes — which is log volume, not a fault signal.
- See Also:
SHORT_EXPIRY_LOG_INTERVAL
private static final long SHORT_EXPIRY_LOG_INTERVALMinimum gap between short-expiry warnings for one destination.- See Also:
_lastShortExpiryLog
Last short-expiry warning per destination, for rate limiting._supplyDeferrals
Consecutive supply-check deferrals per destination, bounded so a pool that never reaches the freshness threshold cannot defer its LeaseSet forever.EMERGENCY_REMINT_WINDOW
private static final long EMERGENCY_REMINT_WINDOWEmergency re-mint window: when the stored copy is within this much of expiring, re-mint whatever the pool holds down to a single viable lease, skipping the normal required-count gate. A thin-but-alive public LeaseSet beats letting the copy lapse while the deferral waits for capacity, and every lease the pool hands back is newer than the dying copy's (the 10-minute lease cap guarantees a later earliest-lease-date), so the floodfill accepts and re-floods the rescue copy. Matches the pool's own lease-eligibility floor (LEASE_MIN_REMAINING_MS = 2 min): a lease the pool refuses to publish cannot outlive floodfill propagation, so once we are inside that floor there is no further capacity to wait for.- See Also:
MISSING_LEASESET_RETRY
private static final long MISSING_LEASESET_RETRYRetry interval after a missing local LeaseSet — long enough for the pool to build and test a replacement tunnel before we ask again.- See Also:
MAX_REMINT_DEFERS
private static final int MAX_REMINT_DEFERSConsecutive fresh-build deferrals before falling back to a thin re-mint.- See Also:
CACHE_CLEANUP_THRESHOLD
private static final long CACHE_CLEANUP_THRESHOLDStaleness threshold for cleaning up tracking maps.- See Also:
_lastCleanupTime
private static volatile long _lastCleanupTimeWhen the stale entry cleanup last ran, to guard against redundant sweeps._retryInProgress
Tracks destinations currently being retried to prevent duplicate retries._lastPublishLogTime
Last publish attempt per destination. Doubles as the throttle for publish log messages and as the liveness set the stale-entry cleanups key off, so it is written regardless of log level.PUBLISH_LOG_THROTTLE
private static final long PUBLISH_LOG_THROTTLEMinimum interval between repeated publish log messages for one destination.- See Also:
_lastVerifyLogTime
Last log timestamp per destination to throttle verification log messages._lastNotRequeueLogTime
Last log timestamp per destination to throttle no-requeue log messages._lastMissingLogTime
Last log timestamp per destination to throttle missing-LeaseSet log messages._globalFailCount
Persistent per-destination store failure count, never reset, surviving job instances, used to decide when to do the expensive floodfill verification._remintDefers
Consecutive re-mint deferral count per destination, to bound fresh-build waiting._lastIneffectiveRemint
When this destination last ran a re-mint that could not improve anything. @since 0.9.71+.MAX_FLOODFILL_VERIFICATIONS
private static final int MAX_FLOODFILL_VERIFICATIONSMax verifications per destination before falling back to direct retry.- See Also:
_firstDeferredAt
When the first publish was deferred, per destination, cleared on success or on the first publish timeout.FIRST_PUBLISH_TIMEOUT
private static final long FIRST_PUBLISH_TIMEOUTMax time to defer first publish while waiting for target tunnels.- See Also:
_publishedOnce
_dest
Destination hash._facade
Kademlia network database facade instance._lastPublished
private volatile long _lastPublishedLast published time.failCount
Per-instance retry counter for exponential backoff.highPriority
private boolean highPriorityWhether this job instance is promoted to high priority._lookupInProgress
Whether a floodfill verification lookup is in progress._registered
private boolean _registeredRegistered flag.
Constructor Details
RepublishLeaseSetJob
Creates a new job to republish a LeaseSet for the given destination.- Parameters:
ctx- the router contextfacade- the network database facadedestHash- the destination hash to republish
Method Details
effectiveExpiryAnomalouslyShort
static boolean effectiveExpiryAnomalouslyShort(long effectiveExpiry) Whether a LeaseSet expiry is short enough to indicate the inbound pool could not supply a viable lease.The threshold is the pool's eligibility floor, not the design target: presenting at or below the floor means no lease in the copy had the minimum remaining life the pool requires to publish, which is the actual fault this signal exists to name. Anything above the floor is ordinary decay and must stay silent, or the signal costs log volume while pointing at nothing.
- Parameters:
effectiveExpiry- ms until the copy currently in effect expires- Returns:
- true if the pool could barely qualify any lease in the copy
getLeaseViabilityWindow
A lease is viable for a re-mint while it has at least this much time remaining: the re-sign request, floodfill propagation, and connection establishment all need the lease alive, and a tunnel closer to expiry than this is already inside the pool's proactive replacement window, so counting it would overstate the pool's health. A healthy pool therefore reads close to its target count, and re-mints proceed without requesting extra builds.- Parameters:
ctx- the router context- Returns:
- the lease viability window in ms
registerSelf
public boolean registerSelf()Attempt to register this job with the facade.- Returns:
- true if registered, false if a job was already active
runJob
public void runJob()Republish the LeaseSet if this job is still registered, then reschedule. An unregistered job has been superseded and does nothing.handleShouldNotPublish
private void handleShouldNotPublish()Handles the client asking to stop publishing this lease set.handleLocalLeaseSet
private void handleLocalLeaseSet()Handles a local lease set that needs publication.handleExpiredLeaseSet
handleMissingLeaseSet
private void handleMissingLeaseSet()Handles a missing lease set by asking the client to create one.handleNotLocal
private void handleNotLocal()Handles a client that is no longer local, cleaning up and stopping publication.isTrackedLocal
private boolean isTrackedLocal()Determine if client is still a configured local tunnel even when its I2CP session is closed (close-on-idle), that is, a pool still exists.- Returns:
- true if the destination is local, or has inbound or outbound tunnel settings
handleValidLeaseSet
Handle valid lease set: publish it. The startup gate defers the first publication until the target tunnel count is met, or FIRST_PUBLISH_TIMEOUT elapses. After the first successful publish, subsequent renewals proceed immediately.- Parameters:
ls- the unexpired lease set to publishname- the log suffix naming the destination, " for 'nickname'" or " for key"now- the current time in millisecondstimeUntilExpiry- milliseconds until the earliest lease of ls expires
maybeDeferFirstPublish
private boolean maybeDeferFirstPublish(int leaseCount, int targetLeases) Whether publication was deferred while waiting for target tunnels. At startup the first publication is deferred until the target tunnel count is met; it falls through after FIRST_PUBLISH_TIMEOUT so pools at partial capacity (e.g. 70% build success) do not block indefinitely. One-time only: once a destination publishes, _publishedOnce prevents re-deferral on subsequent cycles (no 15s treadmill).- Parameters:
leaseCount- the leases the published lease set currently carriestargetLeases- the inbound tunnel count the destination's pool is configured for- Returns:
- true if publication was deferred
getName
Human-readable name for the job queue.- Returns:
- "Republish Local LeaseSet" with optional high-priority marker
getPublishTimeout
private long getPublishTimeout()The time allowed for one publish.- Returns:
- the timeout, in milliseconds
getRetryDelay
private int getRetryDelay()The delay before a retry.- Returns:
- the delay, in milliseconds
getMaxRetryDelay
private int getMaxRetryDelay()The largest retry delay allowed.- Returns:
- the delay, in milliseconds
getRepublishInterval
private long getRepublishInterval()The interval between republishes.- Returns:
- the interval, in milliseconds
computeNextRepublish
private long computeNextRepublish(long timeUntilExpiry) Next republish delay: the configured interval floored at MIN_RESCHEDULE, but capped so the next check fires before the current LeaseSet hits the EXPIRY_WINDOW re-mint threshold. A fresh 10-minute lease with a 5-min interval schedules at the interval; a shorter/thinner lease schedules sooner, so a re-mint that only slightly extends expiry is re-flooded again before the copy dies instead of rotting for a full interval. With the lease cap at 600s the alternation is: re-mint lands ~594s, the next check at the interval sees it above EXPIRY_WINDOW and floods directly, then the 60s re-check crosses the window and re-mints again — every cycle both refreshes and floodfills.- Parameters:
timeUntilExpiry- ms until the current LeaseSet expires- Returns:
- delay in ms
getFreshPoolLeaseSet
The inbound pool's current tunnels as a re-mintable LeaseSet, or null if the client has no inbound pool or no usable leases.- Returns:
- current-pool LeaseSet, or null
shouldRemint
static boolean shouldRemint(int freshCount, int required, boolean extendsExpiry, long timeUntilExpiry, long emergencyRemintWindow) Whether a re-mint may proceed now using the pool's current LeaseSet.Two independent gates, either of which is enough:
- Emergency backstop: the stored copy is inside
EMERGENCY_REMINT_WINDOWand the pool holds at least one viable lease. Waiting costs nothing — every viable lease ends after the dying copy's, so the rescue copy strictly extends it — but deferring risks a fully-lapsed stored copy and the visible outage that follows while handleExpiredLeaseSet rebuilds. - Normal gate: outside the emergency window the re-mint proceeds only when the pool copy extends the stored copy and carries at least
requiredviable leases, so the re-signed LeaseSet is not unnecessarily thin.
- Parameters:
freshCount- number of pool leases with a viability window remainingrequired- minimum viable leases for a normal (non-emergency) re-mintextendsExpiry- true if the pool copy's latest lease exceeds the stored copy'stimeUntilExpiry- ms until the stored copy expiresemergencyRemintWindow- the emergency threshold in ms- Returns:
- true if the re-mint should be requested now
- Emergency backstop: the stored copy is inside
ineffectiveRemintDelay
static long ineffectiveRemintDelay(long timeUntilExpiry) How long to hold off a further re-mint after one that changed nothing.A re-mint inside the emergency window is permitted even when it does not extend the stored copy, because a thin copy the pool can still serve beats letting the LeaseSet die. That exemption is what makes the loop possible: if the fresh copy expires no later than the stored one, publishing it does not move
timeUntilExpiry, so the next cycle is still inside the emergency window and re-arms immediately. Measured in production that was roughly one re-mint per second per pool, all of it re-advertising the same two aging leases.The hold-off is deliberately not a fixed interval. It is half the time the stored copy has left, so however close to expiry the copy is, a further attempt is always scheduled before it can lapse. A fixed floor would have to be small enough for a nearly-dead copy and would then be needlessly slow for a healthy one: these LeaseSets are designed to last around ten minutes but were observed at sixty seconds, so no single constant is right for both. Five minutes, the obvious choice, would let a sixty-second copy lapse unrepublished for four minutes, which is the exact outage the emergency path exists to prevent.
Always strictly less than
timeUntilExpiryfor any positive value, which is the invariant that matters: holding off can never be the reason a LeaseSet lapses unrepublished.- Parameters:
timeUntilExpiry- ms until the stored copy expires- Returns:
- minimum ms to wait before another re-mint attempt
sameLeaseTunnels
Whether two lease sets advertise exactly the same tunnels.Compares tunnel ids as a set, so a re-mint that merely reorders the same leases is recognised as a no-op. This is the loop's true cause: inside the emergency window the viability gate is skipped, so a pool that cannot replace its aging tunnels re-mints the identical set, the stored expiry does not move, the next pass is still inside the emergency window, and the cycle repeats. Measured in production that was ~170 re-mints per burst, six milliseconds apart.
- Parameters:
stored- the currently published lease set, may be nullfresh- the candidate from the pool, may be null- Returns:
- true if both carry the same non-empty set of tunnel ids
refloatLeaseSet
Re-publish the lease set before it expires from the network DB.- Parameters:
storedLeaseSet- the LeaseSet currently published, for no-op detectionname- the log suffix naming the destination, " for 'nickname'" or " for key"now- the current time in millisecondstimeUntilExpiry- milliseconds until the earliest lease of the stored set expires
poolHasAnyViableLease
Whether the pool can sign anything at all right now.Deliberately a starvation test, not a sufficiency test. Being below the target lease count is an ordinary, already-handled condition:
shouldRemint(int, int, boolean, long, long)defers on it and falls back to a thin copy after a bounded number of attempts. Re-deciding it here with a second threshold and a second counter meant the two mechanisms shadowed each other, and a pool that was merely one lease short could defer indefinitely.So the question here is strictly "is there anything publishable at all", read from the pool's own LeaseSet -- the same input the surrounding decision already uses -- rather than from raw tunnel state.
- Parameters:
fresh- the pool's current LeaseSet, may be nullnow- current time in ms- Returns:
- true when the pool has at least one lease still viable for a re-mint
countFreshLeases
Counts the leases that are still fresh.- Parameters:
ls- the lease set to checknow- the current time- Returns:
- the number of fresh leases
getTargetLeaseCount
private int getTargetLeaseCount()The number of inbound leases a re-mint should carry to be useful: the inbound tunnel quantity for a server pool, 1 otherwise.- Returns:
- the target lease count
registerSuccessor
Schedules the next republish job.- Parameters:
delayMs- the delay before the next job- Returns:
- the new job
scheduleRepublish
private void scheduleRepublish(long delayMs) Schedule republish: queue the next republish cycle, unregistering the current job first so hasActiveRepublishJob() doesn't block the successor.- Parameters:
delayMs- how long from now the successor job should start, in milliseconds
requeueRepublish
void requeueRepublish()Requeues the republish after a failed publish, with exponential backoff, an aggressive first retry, and every fourth attempt promoted to high priority.clearRetryInProgress
private void clearRetryInProgress()Clear retry in progress.shortHash
The short hash of the local destination for logs.- Returns:
- the first eight base32 characters
cleanupStaleEntries
private static void cleanupStaleEntries()Cleanup stale entries.cleanupPublishedOnce
private static void cleanupPublishedOnce()Drop _publishedOnce entries for destinations no longer being tracked.recordPublishAttempt
static boolean recordPublishAttempt(ConcurrentHashMap<Hash, Long> times, Hash dest, Long previous, long now) Record that we tried to publish for this destination, and report whether the event is worth logging.The timestamp is written unconditionally. Several cleanups key off
_lastPublishLogTime- cleanupPublishedOnce(), cleanupGlobalFailCount() and cleanupRemintDefers() - so writing it only inside a shouldInfo() guard left those maps permanently empty at the default log level, wiping the failure counters every cleanup cycle and leaving the escalation path unable to fire. State must never depend on the log level.- Parameters:
times- the per-destination last-log timestampsdest- the destination being publishedprevious- the timestamp already recorded for it, or nullnow- current time in ms- Returns:
- true if enough time has passed that the event should be logged
cleanupMap
Cleanup map: drop the entries whose timestamp is older than the cleanup threshold.- Parameters:
map- the destination to timestamp map to prune in placenow- the current time in milliseconds, compared against each entry's timestamp
cleanupGlobalFailCount
private static void cleanupGlobalFailCount(long now) Cleanup global fail count: reset the counters of destinations no longer being tracked, assuming their publication has finished.- Parameters:
now- the current time in milliseconds, unused because the counters carry no timestamps
cleanupRemintDefers
private static void cleanupRemintDefers()Reset re-mint deferral counters for destinations no longer tracked.lastPublished
public long lastPublished()Timestamp of the last successful publication.- Returns:
- timestamp in ms, or 0 if never published
getDestHash
Hash getDestHash()The destination hash this job publishes for.- Returns:
- the hash of the destination whose LeaseSet this job publishes
getTunnelName
Look up the tunnel nickname for a destination.- Parameters:
d- the destination whose tunnel nickname is wanted- Returns:
- tunnel nickname if configured, or the short base32 hash as fallback