For use by the router only. Not to be used by applications or plugins.
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static classOrders the jobs by their next run time.private static classQueue entry that stops the pumper.private final classThread pumping the ready jobs to the runners.Field Summary
FieldsModifier and TypeFieldDescriptionprivate booleanHave we been killed or are we alive?private booleanWill we allow the # job runners to grow beyond 1?private final RouterContextThe router context.private final AtomicIntegerTrack dropped jobs for UI display.private final BlockingQueue<Job> List of high priority jobs that should run before others.private final ObjectLock for the job queues.private final ConcurrentHashMap<String, JobStats> Job name to JobStat for that job.private longJob delay that restarts the router.private longJob delay that logs a warning.private final LogLogger for the job queue.private final intResolved once fromPROP_MAX_WAITING_JOBSat construction.private longWhen the pumper wakes next.private final JobQueue.QueuePumperThread pumping the ready jobs to the runners.private final AtomicIntegerNumber of TestJob instances in the three ready queues or _timedJobs, i.e.private final Map<Integer, JobQueueRunner> Integer (runnerId) to JobQueueRunner for created runners.Membership index over the three ready queues, so duplicate detection is O(1).private final BlockingQueue<Job> List of jobs that are ready to run ASAP.private longJob run time that logs an error.private static final AtomicIntegerCounter to identify a job runner.private final ObjectQueue runners wait on this whenever they're not doing anything, and this gets notified *once* whenever there are ready jobs.private longJob run time that logs a warning.private final JobQueueScalerDynamic scaling controller for adjusting runner count based on load.private final ConcurrentSkipListSet<Job> SortedSet of jobs that are scheduled for running in the future, earliest first.private final BlockingQueue<Job> Queue of timed jobs that are ready to run (moved from _timedJobs when ready).private longStartup time the lag checks ignore.private static final longIf a job is this lagged, the router is hosed, so spit out a warning (don't shut it down).private static final longIf a job is this lagged, spit out a warning, but keep going.private static final intMax ready and waiting jobs before we start dropping 'em - scale with runner count.private static final longIf a job takes this long to run, the router is hosed, so spit out a warning (don't shut it down).private static final longIf a job takes this long to run, spit out a warning, but keep going.private static final longDon't enforce fatal limits until the router has been up for this long.private static final longMinimum lag (ms) before the drop policy activates.private static final intJob id that stops the pumper.(package private) static final StringRouter.config parameter to override the max runners.private static final StringConfig key limiting how many jobs may wait for a job thread.private static final long[]Rate stat periods for the job statistics.(package private) static intHow many when we go parallel.Constructor Summary
ConstructorsMethod Summary
Modifier and TypeMethodDescriptionvoidEnqueue the specified job for normal processing.voidaddJobToTop(Job job) Enqueue the specified job at the top of the queue, ahead of all normal-priority jobs.(package private) voidaddRunners(int count) Add additional job runners to the pool.private voidAdd to the future-scheduled skip list, keeping_queuedTestJobsin step.voidEnable parallel job execution and start additional queue runner threads.intCurrent number of active job runners.intDropped jobs count (resets on read).longAverage lag time for jobs waiting in the queue.intgetJobs(Collection<Job> readyJobs, Collection<Job> timedJobs, Collection<Job> activeJobs, Collection<Job> justFinishedJobs) Collect statistics about jobs currently in the queue.All job statistics collected by the queue.Last job that was executed.longTimestamp of when the last job began execution.longTimestamp of when the last job finished execution.longMaximum duration of currently running jobs.longMaximum lag time for jobs waiting in the queue.intCurrent maximum number of job runners allowed.(package private) JobgetNext()Next job in queue.intNumber of jobs ready to be executed.intCount TestJob instances that are ready to run or currently running (excluding future-scheduled timed jobs).intCount the number of TestJob instances currently queued in the job queue.booleanisAlive()Check if the job queue is currently alive and processing jobs.private voidofferReady(Job job, BlockingQueue<Job> queue) Claim the job in_readyIndexbeforeoffer()publishes it, so a concurrentaddJob(Job)sees it as already queued in that window.voidreleaseJobRunners(int count, String reason) Release previously requested job runners.(package private) intremoveIdleRunners(int maxToRemove) Remove idle job runners from the pool.voidRemove a job from the job queue.private booleanremoveReady(Job job, BlockingQueue<Job> queue) Remove from a ready queue, releasing the index and TestJob claims only if the job was actually present.(package private) voidremoveRunner(int id) Remove a queue runner from the registry.private booleanremoveTimed(Job job) Remove from the future-scheduled skip list.voidrequestJobRunners(int count, String reason, long autoReleaseMs) Request additional job runners for an anticipated burst.voidrunQueue(int numThreads) Start the job queue with the specified number of runner threads.private booleanshouldDrop(Job job, int numReady) Checks whether a late job should be dropped.(package private) voidshutdown()Shutdown the job queue, stopping all runners and clearing all jobs.voidstartup()Initialize and start the job queue pumper thread.private JobtakeReady(BlockingQueue<Job> queue) Dispatch from a ready queue, releasing the index claim here rather than at completion.private voidupdateJobTimings(long delta) Shifts the scheduled job times by a clock change.(package private) voidupdateStats(Job job, long doStart, long origStartAfter, long duration) Update stats.
Field Details
_log
Logger for the job queue._context
The router context._queueRunners
Integer (runnerId) to JobQueueRunner for created runners._runnerId
Counter to identify a job runner._readyJobs
List of jobs that are ready to run ASAP._highPriorityJobs
List of high priority jobs that should run before others._timedJobs
SortedSet of jobs that are scheduled for running in the future, earliest first. Typed as the concrete skip list because the pumper readsfirst()as the minimum start time rather than re-deriving one per pass._timedJobsReady
Queue of timed jobs that are ready to run (moved from _timedJobs when ready)._readyIndex
Membership index over the three ready queues, so duplicate detection is O(1). Maintained exclusively throughofferReady(Job, BlockingQueue),removeReady(Job, BlockingQueue),takeReady(BlockingQueue),addTimed(Job)andremoveTimed(Job)so that no queue mutation can leave it stale.Membership is released at dispatch, not at completion:
JobImpl.requeue(long)is called fromrunJob()on the running job itself, so holding the entry until completion would swallow every self-requeueing job._queuedTestJobs
Number of TestJob instances in the three ready queues or _timedJobs, i.e. whatgetTestJobCount()reports. Maintained by the same helpers, so the pumper can sample it at 100 Hz without walking three collections under _jobLock._jobStats
Job name to JobStat for that job._pumper
Thread pumping the ready jobs to the runners._allowParallelOperation
private volatile boolean _allowParallelOperationWill we allow the # job runners to grow beyond 1?_alive
private volatile boolean _aliveHave we been killed or are we alive?_jobLock
Lock for the job queues._nextPumperRun
private volatile long _nextPumperRunWhen the pumper wakes next.runners
static int runnersHow many when we go parallel.PROP_MAX_RUNNERS
Router.config parameter to override the max runners.- See Also:
DEFAULT_LAG_WARNING
private static final long DEFAULT_LAG_WARNINGIf a job is this lagged, spit out a warning, but keep going.- See Also:
_lagWarning
private long _lagWarningJob delay that logs a warning.DEFAULT_LAG_FATAL
private static final long DEFAULT_LAG_FATALIf a job is this lagged, the router is hosed, so spit out a warning (don't shut it down).- See Also:
_lagFatal
private long _lagFatalJob delay that restarts the router.DEFAULT_RUN_WARNING
private static final long DEFAULT_RUN_WARNINGIf a job takes this long to run, spit out a warning, but keep going.- See Also:
_runWarning
private long _runWarningJob run time that logs a warning.DEFAULT_RUN_FATAL
private static final long DEFAULT_RUN_FATALIf a job takes this long to run, the router is hosed, so spit out a warning (don't shut it down).- See Also:
_runFatal
private long _runFatalJob run time that logs an error.DEFAULT_WARMUP_TIME
private static final long DEFAULT_WARMUP_TIMEDon't enforce fatal limits until the router has been up for this long.- See Also:
_warmupTime
private long _warmupTimeStartup time the lag checks ignore.DEFAULT_MAX_WAITING_JOBS
private static final int DEFAULT_MAX_WAITING_JOBSMax ready and waiting jobs before we start dropping 'em - scale with runner count._maxWaitingJobs
private final int _maxWaitingJobsResolved once fromPROP_MAX_WAITING_JOBSat construction.shouldDrop(Job, int)read it per addJob() that could exceed the cap. A non-positive value disables dropping.MIN_LAG_TO_DROP
private static final long MIN_LAG_TO_DROPMinimum lag (ms) before the drop policy activates. Must be high enough to avoid drops during normal processing jitter; low enough to shed load before queue saturation causes cascading failure. 500ms means the drop gate is meaningful: with 48+ queued jobs AND a half-second of observed lag, the scaler has failed to keep up.- See Also:
PROP_MAX_WAITING_JOBS
Config key limiting how many jobs may wait for a job thread.- See Also:
_runnerLock
Queue runners wait on this whenever they're not doing anything, and this gets notified *once* whenever there are ready jobs._scaler
Dynamic scaling controller for adjusting runner count based on load.RATES
private static final long[] RATESRate stat periods for the job statistics._droppedJobsCount
Track dropped jobs for UI display.POISON_ID
Constructor Details
JobQueue
Does not start the pumper. Caller MUST call startup.- Parameters:
context- the router context supplying properties, logs and stat manager
Method Details
offerReady
Claim the job in_readyIndexbeforeoffer()publishes it, so a concurrentaddJob(Job)sees it as already queued in that window.- Parameters:
job- the job being publishedqueue- the ready queue to publish it to
removeReady
Remove from a ready queue, releasing the index and TestJob claims only if the job was actually present.- Parameters:
job- the job to removequeue- the ready queue to remove it from- Returns:
- true if the job was in the queue and has been removed
takeReady
Dispatch from a ready queue, releasing the index claim here rather than at completion.- Parameters:
queue- the ready queue to dispatch from- Returns:
- the next job, or null if the queue was empty
addTimed
Add to the future-scheduled skip list, keeping_queuedTestJobsin step.- Parameters:
job- the job scheduled for a future time
removeTimed
Remove from the future-scheduled skip list.- Parameters:
job- the job to unschedule- Returns:
- true if the job was scheduled and has been removed
addJob
Enqueue the specified job for normal processing.- Parameters:
job- job to add to the queue
addJobToTop
Enqueue the specified job at the top of the queue, ahead of all normal-priority jobs. The job is exempt from the drop policy and its scheduled start time is overridden to run immediately. Any existing copy in the timed or ready queues is removed first, so promotion can never cause the job to run twice.- Parameters:
job- the job to promote to the front of the queue
removeJob
Remove a job from the job queue.- Parameters:
job- the job to remove from the queue
getReadyCount
public int getReadyCount()Number of jobs ready to be executed.- Returns:
- count of ready jobs in normal, high priority, and timed-ready queues
getAndResetDroppedCount
public int getAndResetDroppedCount()Dropped jobs count (resets on read).- Returns:
- number of jobs dropped since last call
getMaxLag
public long getMaxLag()Maximum lag time for jobs waiting in the queue. This is the delay between when the earliest job was supposed to start and the current time. Uses peek() on each FIFO queue — the head element is the oldest and therefore has the highest lag.- Returns:
- maximum lag in milliseconds, or 0 if all queues are empty
getMaxActiveJobDuration
public long getMaxActiveJobDuration()Maximum duration of currently running jobs. This measures how long active jobs have been executing, which is important when all runners are busy but queue is empty.- Returns:
- max duration in milliseconds of any currently running job, or 0 if no jobs running
getAvgLag
public long getAvgLag()Average lag time for jobs waiting in the queue. This is the average delay between when jobs were supposed to start and the current time across all ready jobs.Uses weakly-consistent iteration on each BlockingQueue — concurrent additions/removals may be missed or double-counted, but the result is a sufficient approximation for diagnostics and scoring.
- Returns:
- average lag in milliseconds, or 0 if queue is empty
shouldDrop
Checks whether a late job should be dropped.- Parameters:
job- the job being considerednumReady- the jobs already waiting to run- Returns:
- true to drop the job instead of running it
allowParallelOperation
public void allowParallelOperation()Enable parallel job execution and start additional queue runner threads. After calling this, multiple jobs may execute concurrently.startup
public void startup()Initialize and start the job queue pumper thread. Does not start the job runner threads.shutdown
void shutdown()Shutdown the job queue, stopping all runners and clearing all jobs.isAlive
public boolean isAlive()Check if the job queue is currently alive and processing jobs. Public so subsystems that queue long-lived work (notablyTestJob's batch dispatch) can refuse to hand it new jobs once the queue is gone — addJob() silently discards then, which would leave their internal state waiting on a pump that never runs.- Returns:
- true if the queue is alive and running
getLastJobBegin
public long getLastJobBegin()Timestamp of when the last job began execution.- Returns:
- timestamp in milliseconds when the last job started, or -1 if no jobs have run
getLastJobEnd
public long getLastJobEnd()Timestamp of when the last job finished execution.- Returns:
- timestamp in milliseconds when the last job ended, or -1 if no jobs have run
getLastJob
Last job that was executed.- Returns:
- the last Job that was executed, or null if no jobs have run
getNext
Job getNext()Next job in queue.- Returns:
- the next runnable job in priority order, or null once the queue has been shut down
runQueue
public void runQueue(int numThreads) Start the job queue with the specified number of runner threads. Does nothing if parallel operation is not enabled and runners already exist.- Parameters:
numThreads- the number of runner threads to start
removeRunner
void removeRunner(int id) Remove a queue runner from the registry. Package-private for use byJobQueueRunner.- Parameters:
id- the runner ID to remove
getActiveRunnerCount
public int getActiveRunnerCount()Current number of active job runners. Package-private for use byJobQueueScaler.- Returns:
- the number of active runners
getMaxRunnerCount
public int getMaxRunnerCount()Current maximum number of job runners allowed. Returns the RAM-adjusted limit if scaler is active and RAM is constrained, otherwise returns the hard limit (2× configured).- Returns:
- the current effective maximum runner limit
requestJobRunners
Request additional job runners for an anticipated burst. Delegates to JobQueueScaler for tracking and auto-decay.- Parameters:
count- number of additional runners to reservereason- label for logging and trackingautoReleaseMs- if > 0, auto-decay after this many ms
releaseJobRunners
Release previously requested job runners.- Parameters:
count- number of runners to releasereason- must match the reason used in requestJobRunners
addRunners
void addRunners(int count) Add additional job runners to the pool. Package-private for use by JobQueueScaler.- Parameters:
count- the number of runners to add
removeIdleRunners
int removeIdleRunners(int maxToRemove) Remove idle job runners from the pool. Package-private for use by JobQueueScaler. Only removes runners that are not currently processing a job.- Parameters:
maxToRemove- the maximum number of runners to remove- Returns:
- the number of runners actually removed
updateJobTimings
private void updateJobTimings(long delta) Shifts the scheduled job times by a clock change.- Parameters:
delta- the clock change, in ms
updateStats
Update stats.- Parameters:
job- the job that just finished a run, used for its name and timingdoStart- the millisecond timestamp when the job actually beganorigStartAfter- the previously recorded scheduled start timeduration- the wall-clock milliseconds the run consumed, never negative
getJobs
public int getJobs(Collection<Job> readyJobs, Collection<Job> timedJobs, Collection<Job> activeJobs, Collection<Job> justFinishedJobs) Collect statistics about jobs currently in the queue. This includes jobs that are ready, timed, active, and just finished.- Parameters:
readyJobs- collection to populate with ready jobstimedJobs- collection to populate with timed/scheduled jobsactiveJobs- collection to populate with currently running jobsjustFinishedJobs- collection to populate with recently finished jobs- Returns:
- the number of queue runners currently active
getJobStats
All job statistics collected by the queue.- Returns:
- unmodifiable collection of JobStats for all job types
getTestJobCount
public int getTestJobCount()Count the number of TestJob instances currently queued in the job queue. This includes both ready jobs and timed jobs waiting to be executed.O(1): maintained by the queue-mutation helpers, because the pumper samples it on every pass and walking three collections under _jobLock was measurable work for a stat that only feeds a graph.
Counts a pumper-promoted job in
_timedJobsReadyas queued. Those jobs are due to run now, so omitting them understated the queue; this matches thejobQueue.testJobCountdescription and the admission check inaddJob(Job), which treats them as ready.- Returns:
- the total number of TestJob instances in the queue
getReadyTestJobCount
public int getReadyTestJobCount()Count TestJob instances that are ready to run or currently running (excluding future-scheduled timed jobs). Used by the scaler to determine whether TestJobs are dominating runner resources right now.- Returns:
- the number of ready/active TestJob instances