final AtomicReference<Throwable> errorRef = new AtomicReference<>(); final SystemProcessingTimeService timer = new SystemProcessingTimeService( new ReferenceSettingExceptionHandler(errorRef), lock); assertEquals(0, timer.getNumTasksScheduled()); ScheduledFuture<?> future = timer.registerTimer(System.currentTimeMillis() + 100000000, new ProcessingTimeCallback() { @Override public void onProcessingTime(long timestamp) {} }); assertEquals(1, timer.getNumTasksScheduled()); assertEquals(0, timer.getNumTasksScheduled()); future = timer.scheduleAtFixedRate( new ProcessingTimeCallback() { @Override }, 10000000000L, 50L); assertEquals(1, timer.getNumTasksScheduled()); assertEquals(0, timer.getNumTasksScheduled()); timer.shutdownService();
final AtomicReference<Throwable> errorRef = new AtomicReference<>(); final SystemProcessingTimeService timer = new SystemProcessingTimeService( new ReferenceSettingExceptionHandler(errorRef), lock); timer.registerTimer(timer.getCurrentProcessingTime() + 20L, new ProcessingTimeCallback() { @Override public void onProcessingTime(long timestamp) throws Exception { timer.quiesce(); timer.awaitPendingAfterQuiesce(); ScheduledFuture<?> future = timer.registerTimer(timer.getCurrentProcessingTime() - 5L, new ProcessingTimeCallback() { @Override public void onProcessingTime(long timestamp) throws Exception { assertEquals(0L, timer.getNumTasksScheduled()); timer.shutdownService();
@Override public boolean shutdownServiceUninterruptible(long timeoutMs) { final Deadline deadline = Deadline.fromNow(Duration.ofMillis(timeoutMs)); boolean shutdownComplete = false; boolean receivedInterrupt = false; do { try { // wait for a reasonable time for all pending timer threads to finish shutdownComplete = shutdownAndAwaitPending(deadline.timeLeft().toMillis(), TimeUnit.MILLISECONDS); } catch (InterruptedException iex) { receivedInterrupt = true; LOG.trace("Intercepted attempt to interrupt timer service shutdown.", iex); } } while (deadline.hasTimeLeft() && !shutdownComplete); if (receivedInterrupt) { Thread.currentThread().interrupt(); } return shutdownComplete; }
/** * Tests that SystemProcessingTimeService#scheduleAtFixedRate is actually triggered multiple * times. */ @Test(timeout = 10000) public void testScheduleAtFixedRate() throws Exception { final Object lock = new Object(); final AtomicReference<Throwable> errorRef = new AtomicReference<>(); final long period = 10L; final int countDown = 3; final SystemProcessingTimeService timer = new SystemProcessingTimeService( new ReferenceSettingExceptionHandler(errorRef), lock); final CountDownLatch countDownLatch = new CountDownLatch(countDown); try { timer.scheduleAtFixedRate(new ProcessingTimeCallback() { @Override public void onProcessingTime(long timestamp) throws Exception { countDownLatch.countDown(); } }, 0L, period); countDownLatch.await(); if (errorRef.get() != null) { throw new Exception(errorRef.get()); } } finally { timer.shutdownService(); } }
final long period = 10L; final SystemProcessingTimeService timer = new SystemProcessingTimeService( new ReferenceSettingExceptionHandler(errorRef), lock); ScheduledFuture<?> scheduledFuture = timer.scheduleAtFixedRate(new ProcessingTimeCallback() { @Override public void onProcessingTime(long timestamp) throws Exception { timer.quiesce(); timer.awaitPendingAfterQuiesce(); scheduledFuture = timer.scheduleAtFixedRate(new ProcessingTimeCallback() { @Override public void onProcessingTime(long timestamp) throws Exception { assertEquals(0, timer.getNumTasksScheduled()); timer.shutdownService();
@Override public ScheduledFuture<?> scheduleAtFixedRate(ProcessingTimeCallback callback, long initialDelay, long period) { long nextTimestamp = getCurrentProcessingTime() + initialDelay; // we directly try to register the timer and only react to the status on exception // that way we save unnecessary volatile accesses for each timer try { return timerService.scheduleAtFixedRate( new RepeatedTriggerTask(status, task, checkpointLock, callback, nextTimestamp, period), initialDelay, period, TimeUnit.MILLISECONDS); } catch (RejectedExecutionException e) { final int status = this.status.get(); if (status == STATUS_QUIESCED) { return new NeverCompleteFuture(initialDelay); } else if (status == STATUS_SHUTDOWN) { throw new IllegalStateException("Timer service is shut down"); } else { // something else happened, so propagate the exception throw e; } } }
@Test public void testExceptionReporting() throws InterruptedException { final AtomicBoolean exceptionWasThrown = new AtomicBoolean(false); final OneShotLatch latch = new OneShotLatch(); final Object lock = new Object(); ProcessingTimeService timeServiceProvider = new SystemProcessingTimeService( new AsyncExceptionHandler() { @Override public void handleAsyncException(String message, Throwable exception) { exceptionWasThrown.set(true); latch.trigger(); } }, lock); timeServiceProvider.registerTimer(System.currentTimeMillis(), new ProcessingTimeCallback() { @Override public void onProcessingTime(long timestamp) throws Exception { throw new Exception("Exception in Timer"); } }); latch.await(); assertTrue(exceptionWasThrown.get()); }
final SystemProcessingTimeService timeService = new SystemProcessingTimeService( (message, exception) -> { }, lock); timeService.scheduleAtFixedRate( timestamp -> {
@Override public boolean shutdownAndAwaitPending(long time, TimeUnit timeUnit) throws InterruptedException { shutdownService(); return timerService.awaitTermination(time, timeUnit); }
@Test public void testShutdownAndWaitPending() { final Object lock = new Object(); final OneShotLatch blockUntilTriggered = new OneShotLatch(); final AtomicBoolean timerExecutionFinished = new AtomicBoolean(false); final SystemProcessingTimeService timeService = createBlockingSystemProcessingTimeService(lock, blockUntilTriggered, timerExecutionFinished); Assert.assertFalse(timeService.isTerminated()); // Check that we wait for the timer to terminate. As the timer blocks on the second latch, this should time out. try { Assert.assertFalse(timeService.shutdownAndAwaitPending(1, TimeUnit.SECONDS)); } catch (InterruptedException e) { Assert.fail("Unexpected interruption."); } // Let the timer proceed. blockUntilTriggered.trigger(); // Now we should succeed in terminating the timer. try { Assert.assertTrue(timeService.shutdownAndAwaitPending(60, TimeUnit.SECONDS)); } catch (InterruptedException e) { Assert.fail("Unexpected interruption."); } Assert.assertTrue(timerExecutionFinished.get()); Assert.assertTrue(timeService.isTerminated()); }
@Test public void testQuiesceTimerServiceAfterOpClose() throws Exception { final OneInputStreamTaskTestHarness<String, String> testHarness = new OneInputStreamTaskTestHarness<>( OneInputStreamTask::new, 2, 2, BasicTypeInfo.STRING_TYPE_INFO, BasicTypeInfo.STRING_TYPE_INFO); testHarness.setupOutputForSingletonOperatorChain(); StreamConfig streamConfig = testHarness.getStreamConfig(); streamConfig.setStreamOperator(new TestOperator()); streamConfig.setOperatorID(new OperatorID()); testHarness.invoke(); testHarness.waitForTaskRunning(); SystemProcessingTimeService timeService = (SystemProcessingTimeService) testHarness.getTask().getProcessingTimeService(); // verify that the timer service is running Assert.assertTrue(timeService.isAlive()); testHarness.endInput(); testHarness.waitForTaskCompletion(); timeService.shutdownService(); }
@Override public void close() throws Exception { // verify that the timer service is still running Assert.assertTrue( ((SystemProcessingTimeService) getContainingTask().getProcessingTimeService()) .isAlive()); super.close(); } }
long delay = Math.max(timestamp - getCurrentProcessingTime(), 0) + 1;
@Test public void testExceptionReportingScheduleAtFixedRate() throws InterruptedException { final AtomicBoolean exceptionWasThrown = new AtomicBoolean(false); final OneShotLatch latch = new OneShotLatch(); final Object lock = new Object(); ProcessingTimeService timeServiceProvider = new SystemProcessingTimeService( new AsyncExceptionHandler() { @Override public void handleAsyncException(String message, Throwable exception) { exceptionWasThrown.set(true); latch.trigger(); } }, lock); timeServiceProvider.scheduleAtFixedRate( new ProcessingTimeCallback() { @Override public void onProcessingTime(long timestamp) throws Exception { throw new Exception("Exception in Timer"); } }, 0L, 100L); latch.await(); assertTrue(exceptionWasThrown.get()); }
@Override public boolean shutdownAndAwaitPending(long time, TimeUnit timeUnit) throws InterruptedException { shutdownService(); return timerService.awaitTermination(time, timeUnit); }
@Test public void testTriggerHoldsLock() throws Exception { final Object lock = new Object(); final AtomicReference<Throwable> errorRef = new AtomicReference<>(); final SystemProcessingTimeService timer = new SystemProcessingTimeService( new ReferenceSettingExceptionHandler(errorRef), lock); try { assertEquals(0, timer.getNumTasksScheduled()); // schedule something ScheduledFuture<?> future = timer.registerTimer(System.currentTimeMillis(), new ProcessingTimeCallback() { @Override public void onProcessingTime(long timestamp) { assertTrue(Thread.holdsLock(lock)); } }); // wait until the execution is over future.get(); assertEquals(0, timer.getNumTasksScheduled()); // check that no asynchronous error was reported if (errorRef.get() != null) { throw new Exception(errorRef.get()); } } finally { timer.shutdownService(); } }
@Override public ScheduledFuture<?> scheduleAtFixedRate(ProcessingTimeCallback callback, long initialDelay, long period) { long nextTimestamp = getCurrentProcessingTime() + initialDelay; // we directly try to register the timer and only react to the status on exception // that way we save unnecessary volatile accesses for each timer try { return timerService.scheduleAtFixedRate( new RepeatedTriggerTask(status, task, checkpointLock, callback, nextTimestamp, period), initialDelay, period, TimeUnit.MILLISECONDS); } catch (RejectedExecutionException e) { final int status = this.status.get(); if (status == STATUS_QUIESCED) { return new NeverCompleteFuture(initialDelay); } else if (status == STATUS_SHUTDOWN) { throw new IllegalStateException("Timer service is shut down"); } else { // something else happened, so propagate the exception throw e; } } }
"Time Trigger for " + getName(), getUserCodeClassLoader()); timerService = new SystemProcessingTimeService(this, getCheckpointLock(), timerThreadFactory);
@Override public boolean shutdownAndAwaitPending(long time, TimeUnit timeUnit) throws InterruptedException { shutdownService(); return timerService.awaitTermination(time, timeUnit); }
@Override public boolean shutdownServiceUninterruptible(long timeoutMs) { final Deadline deadline = Deadline.fromNow(Duration.ofMillis(timeoutMs)); boolean shutdownComplete = false; boolean receivedInterrupt = false; do { try { // wait for a reasonable time for all pending timer threads to finish shutdownComplete = shutdownAndAwaitPending(deadline.timeLeft().toMillis(), TimeUnit.MILLISECONDS); } catch (InterruptedException iex) { receivedInterrupt = true; LOG.trace("Intercepted attempt to interrupt timer service shutdown.", iex); } } while (deadline.hasTimeLeft() && !shutdownComplete); if (receivedInterrupt) { Thread.currentThread().interrupt(); } return shutdownComplete; }