/** * Returns a key that can be used by the WorkManager implementation to guarantee that works with the same partition * key will be executed in the order they are submitted. * * @since 9.3 */ default String getPartitionKey() { return getId(); }
synchronized WorkQueueMetrics workRunning(Work work) { String id = work.getId(); scheduledWorks.remove(id); works.put(id, work); // update state runningWorks.add(id); scheduledCount -= 1; runningCount += 1; return metrics(); }
@Override public boolean equals(Object other) { if (!(other instanceof Work)) { return false; } return ((Work) other).getId().equals(getId()); }
private boolean anotherWorkIsAlreadyRunning(Runnable r) throws InterruptedException { Work work = WorkHolder.getWork(r); String id = work.getId(); if (runningWorks.contains(id)) { return true; } return false; }
synchronized WorkQueueMetrics workCompleted(Work work) { String id = work.getId(); if (runningWorks.remove(id) && !scheduledWorks.contains(id)) { works.remove(id); } runningCount -= 1; completedCount += 1; return metrics(); }
protected byte[] workId(Work work) { return workId(work.getId()); }
protected static String name(Work work) { return work.getCategory() + ":" + work.getId(); }
synchronized WorkQueueMetrics workRescheduleRunning(Work work) { String id = work.getId(); if (!runningWorks.remove(id)) { return metrics(); } works.remove(id); runningCount -= 1; return workSchedule(work); }
synchronized WorkQueueMetrics workCanceled(Work work) { String id = work.getId(); for (Iterator<Runnable> it = queue.iterator(); it.hasNext();) { if (id.equals(WorkHolder.getWork(it.next()) .getId())) { it.remove(); scheduledWorks.remove(id); works.remove(id); scheduledCount -= 1; cancelledCount +=1 ; break; } } return metrics(); }
log.warn("Not scheduled work after commit because of missing transaction manager: " + work.getId()); return false; if (transaction == null) { if (log.isDebugEnabled()) { log.debug("Not scheduled work after commit because of missing transaction: " + work.getId()); if (status == Status.STATUS_ACTIVE) { if (log.isDebugEnabled()) { log.debug("Scheduled after commit: " + work.getId()); log.debug("Scheduled immediately: " + work.getId()); log.debug("Cancelling schedule because transaction marked rollback-only: " + work.getId()); if (log.isDebugEnabled()) { log.debug("Not scheduling work after commit because transaction is in status " + status + ": " + work.getId());
@Override public void run() { final Thread currentThread = Thread.currentThread(); String name = currentThread.getName(); currentThread.setName(name + ":" + work.getId()); ThreadEvent.onEnter(this, false).send(); try { work.run(); } finally { currentThread.setName(name); ThreadEvent.onLeave(this).send(); } }
synchronized WorkQueueMetrics workSchedule(Work work) { String id = work.getId(); if (scheduledWorks.contains(id)) { return metrics(); } if (!offer(new WorkHolder(work))) { return metrics(); } works.put(id, work); scheduledWorks.add(id); scheduledCount += 1; return metrics(); }
work = deserialize(record.getData()); try { if (work.isCoalescing() && WorkStateHelper.getLastOffset(work.getId()) > context.getLastOffset().offset()) { log.debug("Skipping duplicate of coalescing work id: " + work.getId() + " " + work); } else if (work.isIdempotent() && workIds.contains(work.getId())) { log.debug("Skipping duplicate of idempotent work id: " + work.getId()); } else { boolean storeState = Framework.getService(ConfigurationService.class) .isBooleanPropertyTrue(STORESTATE_KEY); if (storeState) { if (WorkStateHelper.getState(work.getId()) != Work.State.SCHEDULED) { log.warn("work has been canceled, saving and returning"); context.askForCheckpoint(); return; WorkStateHelper.setState(work.getId(), Work.State.RUNNING, stateTTL); if (storeState && WorkStateHelper.getState(work.getId()) == Work.State.RUNNING) { WorkStateHelper.setState(work.getId(), null, stateTTL); workIds.add(work.getId()); work.getId(), work.getTitle(), record)); } else { work.getId(), work.getTitle(), record)); context.askForCheckpoint(); log.debug("Exception during work " + work.getId(), e);
log.debug(String.format( "Scheduling: workId: %s, category: %s, queue: %s, scheduling: %s, afterCommit: %s, work: %s", work.getId(), work.getCategory(), queueId, scheduling, afterCommit, work)); if (WorkStateHelper.getState(work.getId()) != null) { WorkStateHelper.setCanceled(work.getId()); LogOffset offset = appender.append(key, Record.of(key, WorkComputation.serialize(work))); if (work.isCoalescing()) { WorkStateHelper.setLastOffset(work.getId(), offset.offset(), stateTTL); WorkStateHelper.setState(work.getId(), Work.State.SCHEDULED, stateTTL);
/** * Initiates a shutdown of this executor and asks for work instances to suspend themselves. * * @throws InterruptedException */ public void shutdownAndSuspend() throws InterruptedException { try { // don't consume the queue anymore deactivateQueueMetrics(queueId); queuing.setActive(queueId, false); // suspend all running work boolean hasRunningWork = false; for (Work work : running) { work.setWorkInstanceSuspending(); log.trace("suspending and rescheduling {}", work.getId()); work.setWorkInstanceState(State.SCHEDULED); queuing.workReschedule(queueId, work); hasRunningWork = true; } if (hasRunningWork) { long shutdownDelay = Long.parseLong( Framework.getService(ConfigurationService.class).getProperty(SHUTDOWN_DELAY_MS_KEY, "0")); // sleep for a given amount of time for works to have time to persist their state and stop properly Thread.sleep(shutdownDelay); } shutdownNow(); } finally { executors.remove(queueId); } }
@Override public void schedule(Work work, Scheduling scheduling, boolean afterCommit) { String workId = work.getId(); String queueId = getCategoryQueueId(work.getCategory()); if (!isQueuingEnabled(queueId)) { case CANCEL_SCHEDULED: getExecutor(queueId).removeScheduled(workId); WorkStateHelper.setCanceled(work.getId()); break; case IF_NOT_SCHEDULED:
@Override protected void afterExecute(Runnable r, Throwable t) { Work work = WorkHolder.getWork(r); try { if (work.isSuspending()) { log.trace("{} is suspending, giving up", work); return; } if (isShutdown()) { log.trace("rescheduling {}", work.getId(), t); work.setWorkInstanceState(State.SCHEDULED); queuing.workReschedule(queueId, work); return; } work.setWorkInstanceState(State.UNKNOWN); queuing.workCompleted(queueId, work); } finally { running.remove(work); runningCount.dec(); completedCount.inc(); workTimer.update(work.getCompletionTime() - work.getStartTime(), TimeUnit.MILLISECONDS); completionSynchronizer.signalCompletedWork(); } }
@Override public VideoConversionStatus getProgressStatus(String repositoryName, String docId, String conversionName) { WorkManager workManager = Framework.getService(WorkManager.class); Work work = new VideoConversionWork(repositoryName, docId, conversionName); State state = workManager.getWorkState(work.getId()); if (state == null) { // DONE return null; } else if (state == State.SCHEDULED) { String queueId = workManager.getCategoryQueueId(VideoConversionWork.CATEGORY_VIDEO_CONVERSION); long queueSize = workManager.getQueueSize(queueId, State.SCHEDULED); return new VideoConversionStatus(VideoConversionStatus.STATUS_CONVERSION_QUEUED, 0L, queueSize); } else { // RUNNING return new VideoConversionStatus(VideoConversionStatus.STATUS_CONVERSION_PENDING, 0L, 0L); } }