public void setFinalizer(TaskFinalizer f) { TaskFinalizer finalizer = Tasks.tag(this, TaskFinalizer.class, false); if (finalizer!=null && finalizer!=f) throw new IllegalStateException("Cannot apply multiple finalizers"); if (isDone()) throw new IllegalStateException("Finalizer cannot be set on task "+this+" after it is finished"); tags.add(f); }
@Override @Beta public synchronized boolean cancel(TaskCancellationMode mode) { if (isDone()) return false; if (log.isTraceEnabled()) { log.trace("BT cancelling "+this+" mode "+mode+", from thread "+Thread.currentThread()); } cancelled = true; doCancel(mode); notifyAll(); return true; }
@Override public boolean blockUntilEnded(Duration timeout) { Long endTime = timeout==null ? null : System.currentTimeMillis() + timeout.toMillisecondsRoundingUp(); try { boolean started = blockUntilStarted(timeout); if (!started) return false; if (timeout==null) { internalFuture.get(); } else { long remaining = endTime - System.currentTimeMillis(); if (remaining>0) internalFuture.get(remaining, TimeUnit.MILLISECONDS); } return isDone(); } catch (Throwable t) { Exceptions.propagateIfFatal(t); if (!(t instanceof TimeoutException) && log.isDebugEnabled()) log.debug("call from "+Thread.currentThread()+", blocking until '"+this+"' finishes, ended with error: "+t); return isDone(); } }
@Override public T get() throws InterruptedException, ExecutionException { try { if (!isDone()) Tasks.setBlockingTask(this); blockUntilStarted(); return internalFuture.get(); } finally { Tasks.resetBlockingTask(); } }
/** * Returns true if the task has had an error. * * Only true if calling {@link #get()} will throw an exception when it completes (including cancel). * Implementations may set this true before completion if they have that insight, or * (the default) they may compute it lazily after completion (returning false before completion). */ @Override public boolean isError() { if (!isDone()) return false; if (isCancelled()) return true; try { get(); return false; } catch (Throwable t) { return true; } }
fakeTaskForContext = (BasicTask<?>)callableOrSupplier; if (fakeTaskForContext.isQueuedOrSubmitted()) { if (fakeTaskForContext.isDone()) { return Maybe.of((T)fakeTaskForContext.getUnchecked()); } else {
@Test public void cancelAfterRun() throws Exception { BasicTask<Integer> t = new BasicTask<Integer>(Callables.returning(42)); em.submit(MutableMap.of("tag", "A"), t); assertEquals(t.get(), (Integer)42); t.cancel(true); assertFalse(t.isCancelled()); assertFalse(t.isError()); assertTrue(t.isDone()); }
if (isDone()) { return getStatusString(verbosity); } else {
@Test public void testSequentialTaskFailsWhenIntermediateTaskThrowsException() throws Exception { BasicTask<String> t1 = taskReturning("a"); BasicTask<String> t2 = new BasicTask<String>(new Callable<String>() { @Override public String call() throws Exception { throw new IllegalArgumentException("forced exception"); } }); BasicTask<String> t3 = taskReturning("c"); SequentialTask<String> task = new SequentialTask<String>(t1, t2, t3); Task<List<String>> tSequence = ec.submit(task); try { tSequence.get(); fail("t2 should have thrown an exception"); } catch (Exception e) {} assertTrue(task.isDone()); assertTrue(task.isError()); assertTrue(t1.isDone()); assertFalse(t1.isError()); assertTrue(t2.isDone()); assertTrue(t2.isError()); // t3 not run because of t2 exception assertFalse(t3.isDone()); assertFalse(t3.isBegun()); }
@Test public void cancelBeforeRun() throws Exception { final CountDownLatch blockForever = new CountDownLatch(1); BasicTask<Integer> t = new BasicTask<Integer>(new Callable<Integer>() { @Override public Integer call() throws Exception { blockForever.await(); return 42; }}); t.cancel(true); assertTrue(t.isCancelled()); assertTrue(t.isDone()); assertTrue(t.isError()); em.submit(MutableMap.of("tag", "A"), t); try { t.get(); fail("get should have failed due to cancel"); } catch (CancellationException e) { // expected } assertTrue(t.isCancelled()); assertTrue(t.isDone()); assertTrue(t.isError()); log.debug("cancelBeforeRun status: {}", t.getStatusDetail(false)); assertTrue(t.getStatusDetail(false).toLowerCase().contains("cancel")); }
@Test public void errorDuringRun() throws Exception { BasicTask<Void> t = new BasicTask<Void>(new Callable<Void>() { @Override public Void call() throws Exception { throw new IllegalStateException("Simulating failure in errorDuringRun"); }}); em.submit(MutableMap.of("tag", "A"), t); try { t.get(); fail("get should have failed due to error"); } catch (Exception eo) { Throwable e = Throwables.getRootCause(eo); assertEquals("Simulating failure in errorDuringRun", e.getMessage()); } assertFalse(t.isCancelled()); assertTrue(t.isError()); assertTrue(t.isDone()); log.debug("errorDuringRun status: {}", t.getStatusDetail(false)); assertTrue(t.getStatusDetail(false).contains("Simulating failure in errorDuringRun"), "details="+t.getStatusDetail(false)); }
@Test public void testParallelTaskFailsWhenIntermediateTaskThrowsException() throws Exception { // differs from test above of SequentialTask in that expect t3 to be executed, // despite t2 failing. // TODO Do we expect tSequence.get() to block for everything to either fail or complete, // and then to throw exception? Currently it does *not* do that so test was previously failing. BasicTask<String> t1 = taskReturning("a"); BasicTask<String> t2 = new BasicTask<String>(new Callable<String>() { @Override public String call() throws Exception { throw new IllegalArgumentException("forced exception"); } }); BasicTask<String> t3 = slowTaskReturning("c", Duration.millis(100)); ParallelTask<String> task = new ParallelTask<String>(t1, t2, t3); Task<List<String>> tSequence = ec.submit(task); try { tSequence.get(); fail("t2 should have thrown an exception"); } catch (Exception e) {} assertTrue(task.isDone()); assertTrue(task.isError()); assertTrue(t1.isDone()); assertFalse(t1.isError()); assertTrue(t2.isDone()); assertTrue(t2.isError()); assertTrue(t3.isBegun()); assertTrue(t3.isDone()); assertFalse(t3.isError()); }
rv += "\n\n"+getExtraStatusText(); } else if (isDone()) { long elapsed = endTimeUtc - submitTimeUtc; String duration = Time.makeTimeStringRounded(elapsed);