mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-15 08:18:55 +00:00
Merge pull request #1322 from mmews-n4/requestManger_logging
Log Exceptions thrown in futures created by the RequestManger
This commit is contained in:
commit
f8c791989c
8 changed files with 241 additions and 10 deletions
|
@ -9,16 +9,22 @@ package org.eclipse.xtext.ide.tests.server.concurrent
|
|||
|
||||
import com.google.inject.Guice
|
||||
import com.google.inject.Inject
|
||||
import java.util.concurrent.ExecutionException
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import org.apache.log4j.Level
|
||||
import org.eclipse.xtext.ide.server.ServerModule
|
||||
import org.eclipse.xtext.ide.server.concurrent.RequestManager
|
||||
import org.eclipse.xtext.testing.logging.LoggingTester
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
import static org.junit.Assert.*
|
||||
import org.junit.Assert
|
||||
import org.eclipse.xtext.ide.server.concurrent.WriteRequest
|
||||
import org.eclipse.xtext.ide.server.concurrent.ReadRequest
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
|
@ -42,6 +48,80 @@ class RequestManagerTest {
|
|||
sharedState = null
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
def void testRunWriteLogExceptionNonCancellable() {
|
||||
val logResult = LoggingTester.captureLogging(Level.ALL, WriteRequest, [
|
||||
val future = requestManager.runWrite([], [
|
||||
throw new RuntimeException();
|
||||
])
|
||||
|
||||
// join future to assert log later
|
||||
try {
|
||||
future.join
|
||||
} catch (Exception e) {}
|
||||
])
|
||||
|
||||
logResult.assertLogEntry("Error during request:")
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
def void testRunWriteLogExceptionCancellable() {
|
||||
val logResult = LoggingTester.captureLogging(Level.ALL, WriteRequest, [
|
||||
val future = requestManager.runWrite([
|
||||
throw new RuntimeException();
|
||||
], [])
|
||||
|
||||
// join future to assert log later
|
||||
try {
|
||||
future.join
|
||||
} catch (Exception e) {}
|
||||
])
|
||||
|
||||
logResult.assertLogEntry("Error during request:")
|
||||
}
|
||||
|
||||
@Test(timeout = 1000, expected = ExecutionException)
|
||||
def void testRunWriteCatchException() {
|
||||
LoggingTester.captureLogging(Level.ALL, WriteRequest, [
|
||||
val future = requestManager.runWrite([
|
||||
throw new RuntimeException()
|
||||
], [])
|
||||
|
||||
assertEquals('Foo', future.get)
|
||||
])
|
||||
|
||||
Assert.fail("unreachable")
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
def void testRunReadLogException() {
|
||||
val logResult = LoggingTester.captureLogging(Level.ALL, ReadRequest, [
|
||||
val future = requestManager.runRead([
|
||||
throw new RuntimeException();
|
||||
])
|
||||
|
||||
// join future to assert log later
|
||||
try {
|
||||
future.join
|
||||
} catch (Exception e) {}
|
||||
])
|
||||
|
||||
logResult.assertLogEntry("Error during request:")
|
||||
}
|
||||
|
||||
@Test(timeout = 1000, expected = ExecutionException)
|
||||
def void testRunReadCatchException() {
|
||||
LoggingTester.captureLogging(Level.ALL, ReadRequest, [
|
||||
val future = requestManager.runRead([
|
||||
throw new RuntimeException()
|
||||
])
|
||||
|
||||
assertEquals('Foo', future.get)
|
||||
])
|
||||
|
||||
Assert.fail
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
def void testRunRead() {
|
||||
val future = requestManager.runRead [
|
||||
|
@ -132,5 +212,4 @@ class RequestManagerTest {
|
|||
Thread.sleep(10)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,10 +10,15 @@ package org.eclipse.xtext.ide.tests.server.concurrent;
|
|||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.apache.log4j.Level;
|
||||
import org.eclipse.xtext.ide.server.ServerModule;
|
||||
import org.eclipse.xtext.ide.server.concurrent.ReadRequest;
|
||||
import org.eclipse.xtext.ide.server.concurrent.RequestManager;
|
||||
import org.eclipse.xtext.ide.server.concurrent.WriteRequest;
|
||||
import org.eclipse.xtext.testing.logging.LoggingTester;
|
||||
import org.eclipse.xtext.util.CancelIndicator;
|
||||
import org.eclipse.xtext.xbase.lib.Exceptions;
|
||||
import org.eclipse.xtext.xbase.lib.Functions.Function0;
|
||||
|
@ -49,6 +54,109 @@ public class RequestManagerTest {
|
|||
this.sharedState = null;
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
public void testRunWriteLogExceptionNonCancellable() {
|
||||
final Runnable _function = () -> {
|
||||
final Function0<Object> _function_1 = () -> {
|
||||
return null;
|
||||
};
|
||||
final Function2<CancelIndicator, Object, Object> _function_2 = (CancelIndicator $0, Object $1) -> {
|
||||
throw new RuntimeException();
|
||||
};
|
||||
final CompletableFuture<Object> future = this.requestManager.<Object, Object>runWrite(_function_1, _function_2);
|
||||
try {
|
||||
future.join();
|
||||
} catch (final Throwable _t) {
|
||||
if (_t instanceof Exception) {
|
||||
} else {
|
||||
throw Exceptions.sneakyThrow(_t);
|
||||
}
|
||||
}
|
||||
};
|
||||
final LoggingTester.LogCapture logResult = LoggingTester.captureLogging(Level.ALL, WriteRequest.class, _function);
|
||||
logResult.assertLogEntry("Error during request:");
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
public void testRunWriteLogExceptionCancellable() {
|
||||
final Runnable _function = () -> {
|
||||
final Function0<Object> _function_1 = () -> {
|
||||
throw new RuntimeException();
|
||||
};
|
||||
final Function2<CancelIndicator, Object, Object> _function_2 = (CancelIndicator $0, Object $1) -> {
|
||||
return null;
|
||||
};
|
||||
final CompletableFuture<Object> future = this.requestManager.<Object, Object>runWrite(_function_1, _function_2);
|
||||
try {
|
||||
future.join();
|
||||
} catch (final Throwable _t) {
|
||||
if (_t instanceof Exception) {
|
||||
} else {
|
||||
throw Exceptions.sneakyThrow(_t);
|
||||
}
|
||||
}
|
||||
};
|
||||
final LoggingTester.LogCapture logResult = LoggingTester.captureLogging(Level.ALL, WriteRequest.class, _function);
|
||||
logResult.assertLogEntry("Error during request:");
|
||||
}
|
||||
|
||||
@Test(timeout = 1000, expected = ExecutionException.class)
|
||||
public void testRunWriteCatchException() {
|
||||
final Runnable _function = () -> {
|
||||
try {
|
||||
final Function0<Object> _function_1 = () -> {
|
||||
throw new RuntimeException();
|
||||
};
|
||||
final Function2<CancelIndicator, Object, Object> _function_2 = (CancelIndicator $0, Object $1) -> {
|
||||
return null;
|
||||
};
|
||||
final CompletableFuture<Object> future = this.requestManager.<Object, Object>runWrite(_function_1, _function_2);
|
||||
Assert.assertEquals("Foo", future.get());
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
};
|
||||
LoggingTester.captureLogging(Level.ALL, WriteRequest.class, _function);
|
||||
Assert.fail("unreachable");
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
public void testRunReadLogException() {
|
||||
final Runnable _function = () -> {
|
||||
final Function1<CancelIndicator, Object> _function_1 = (CancelIndicator it) -> {
|
||||
throw new RuntimeException();
|
||||
};
|
||||
final CompletableFuture<Object> future = this.requestManager.<Object>runRead(_function_1);
|
||||
try {
|
||||
future.join();
|
||||
} catch (final Throwable _t) {
|
||||
if (_t instanceof Exception) {
|
||||
} else {
|
||||
throw Exceptions.sneakyThrow(_t);
|
||||
}
|
||||
}
|
||||
};
|
||||
final LoggingTester.LogCapture logResult = LoggingTester.captureLogging(Level.ALL, ReadRequest.class, _function);
|
||||
logResult.assertLogEntry("Error during request:");
|
||||
}
|
||||
|
||||
@Test(timeout = 1000, expected = ExecutionException.class)
|
||||
public void testRunReadCatchException() {
|
||||
final Runnable _function = () -> {
|
||||
try {
|
||||
final Function1<CancelIndicator, Object> _function_1 = (CancelIndicator it) -> {
|
||||
throw new RuntimeException();
|
||||
};
|
||||
final CompletableFuture<Object> future = this.requestManager.<Object>runRead(_function_1);
|
||||
Assert.assertEquals("Foo", future.get());
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
};
|
||||
LoggingTester.captureLogging(Level.ALL, ReadRequest.class, _function);
|
||||
Assert.fail();
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
public void testRunRead() {
|
||||
try {
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.concurrent.CompletableFuture
|
|||
import java.util.concurrent.CompletionException
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
import org.apache.log4j.Logger
|
||||
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
|
||||
import org.eclipse.xtext.service.OperationCanceledManager
|
||||
import org.eclipse.xtext.util.CancelIndicator
|
||||
|
@ -42,14 +43,14 @@ class RequestManager {
|
|||
|
||||
def <V> CompletableFuture<V> runRead((CancelIndicator)=>V cancellable) {
|
||||
return submit(
|
||||
new ReadRequest(cancellable, parallel)
|
||||
new ReadRequest(this, cancellable, parallel)
|
||||
)
|
||||
}
|
||||
|
||||
def <U, V> CompletableFuture<V> runWrite(()=>U nonCancellable, (CancelIndicator, U)=>V cancellable) {
|
||||
val cancelFuture = cancel()
|
||||
return submit(
|
||||
new WriteRequest(nonCancellable, cancellable, cancelFuture)
|
||||
new WriteRequest(this, nonCancellable, cancellable, cancelFuture)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -81,6 +82,7 @@ class RequestManager {
|
|||
|
||||
@FinalFieldsConstructor
|
||||
class ReadRequest<V> extends AbstractRequest<V> {
|
||||
static final Logger LOG = Logger.getLogger(ReadRequest);
|
||||
|
||||
val (CancelIndicator)=>V cancellable
|
||||
val ExecutorService executor
|
||||
|
@ -92,6 +94,9 @@ class ReadRequest<V> extends AbstractRequest<V> {
|
|||
cancelIndicator.checkCanceled
|
||||
result.complete(cancellable.apply(cancelIndicator))
|
||||
} catch(Throwable e) {
|
||||
if (e !== null && !requestManager.isCancelException(e)) {
|
||||
LOG.error("Error during request: ", e);
|
||||
}
|
||||
result.completeExceptionally(e)
|
||||
}
|
||||
]
|
||||
|
@ -101,6 +106,7 @@ class ReadRequest<V> extends AbstractRequest<V> {
|
|||
|
||||
@FinalFieldsConstructor
|
||||
class WriteRequest<U, V> extends AbstractRequest<V> {
|
||||
static final Logger LOG = Logger.getLogger(WriteRequest);
|
||||
|
||||
val ()=>U nonCancellable
|
||||
val (CancelIndicator, U)=>V cancellable
|
||||
|
@ -118,6 +124,9 @@ class WriteRequest<U, V> extends AbstractRequest<V> {
|
|||
cancelIndicator.checkCanceled
|
||||
result.complete(cancellable.apply(cancelIndicator, intermediateResult))
|
||||
} catch(Throwable e) {
|
||||
if (e !== null && !requestManager.isCancelException(e)) {
|
||||
LOG.error("Error during request: ", e);
|
||||
}
|
||||
result.completeExceptionally(e)
|
||||
}
|
||||
}
|
||||
|
@ -128,6 +137,11 @@ abstract class AbstractRequest<V> implements Runnable, Cancellable {
|
|||
|
||||
protected val result = new CompletableFuture<V>()
|
||||
protected val cancelIndicator = new RequestCancelIndicator(result)
|
||||
protected val RequestManager requestManager;
|
||||
|
||||
new (RequestManager requestManager) {
|
||||
this.requestManager = requestManager;
|
||||
}
|
||||
|
||||
override cancel() {
|
||||
cancelIndicator.cancel
|
||||
|
|
|
@ -10,6 +10,7 @@ package org.eclipse.xtext.ide.server.concurrent;
|
|||
import java.util.concurrent.CompletableFuture;
|
||||
import org.eclipse.xtext.ide.server.concurrent.Cancellable;
|
||||
import org.eclipse.xtext.ide.server.concurrent.RequestCancelIndicator;
|
||||
import org.eclipse.xtext.ide.server.concurrent.RequestManager;
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public abstract class AbstractRequest<V extends Object> implements Runnable, Cancellable {
|
||||
|
@ -17,6 +18,12 @@ public abstract class AbstractRequest<V extends Object> implements Runnable, Can
|
|||
|
||||
protected final RequestCancelIndicator cancelIndicator = new RequestCancelIndicator(this.result);
|
||||
|
||||
protected final RequestManager requestManager;
|
||||
|
||||
public AbstractRequest(final RequestManager requestManager) {
|
||||
this.requestManager = requestManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
this.cancelIndicator.cancel();
|
||||
|
|
|
@ -9,8 +9,10 @@ package org.eclipse.xtext.ide.server.concurrent;
|
|||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor;
|
||||
import org.eclipse.xtext.ide.server.concurrent.AbstractRequest;
|
||||
import org.eclipse.xtext.ide.server.concurrent.RequestManager;
|
||||
import org.eclipse.xtext.util.CancelIndicator;
|
||||
import org.eclipse.xtext.xbase.lib.Exceptions;
|
||||
import org.eclipse.xtext.xbase.lib.Functions.Function1;
|
||||
|
@ -18,6 +20,8 @@ import org.eclipse.xtext.xbase.lib.Functions.Function1;
|
|||
@FinalFieldsConstructor
|
||||
@SuppressWarnings("all")
|
||||
public class ReadRequest<V extends Object> extends AbstractRequest<V> {
|
||||
private static final Logger LOG = Logger.getLogger(ReadRequest.class);
|
||||
|
||||
private final Function1<? super CancelIndicator, ? extends V> cancellable;
|
||||
|
||||
private final ExecutorService executor;
|
||||
|
@ -40,7 +44,14 @@ public class ReadRequest<V extends Object> extends AbstractRequest<V> {
|
|||
} catch (final Throwable _t) {
|
||||
if (_t instanceof Throwable) {
|
||||
final Throwable e = (Throwable)_t;
|
||||
_xtrycatchfinallyexpression = this.result.completeExceptionally(e);
|
||||
boolean _xblockexpression_1 = false;
|
||||
{
|
||||
if (((e != null) && (!this.requestManager.isCancelException(e)))) {
|
||||
ReadRequest.LOG.error("Error during request: ", e);
|
||||
}
|
||||
_xblockexpression_1 = this.result.completeExceptionally(e);
|
||||
}
|
||||
_xtrycatchfinallyexpression = _xblockexpression_1;
|
||||
} else {
|
||||
throw Exceptions.sneakyThrow(_t);
|
||||
}
|
||||
|
@ -50,8 +61,8 @@ public class ReadRequest<V extends Object> extends AbstractRequest<V> {
|
|||
this.executor.<Boolean>submit(_function);
|
||||
}
|
||||
|
||||
public ReadRequest(final Function1<? super CancelIndicator, ? extends V> cancellable, final ExecutorService executor) {
|
||||
super();
|
||||
public ReadRequest(final RequestManager requestManager, final Function1<? super CancelIndicator, ? extends V> cancellable, final ExecutorService executor) {
|
||||
super(requestManager);
|
||||
this.cancellable = cancellable;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
|
|
@ -49,13 +49,13 @@ public class RequestManager {
|
|||
}
|
||||
|
||||
public <V extends Object> CompletableFuture<V> runRead(final Function1<? super CancelIndicator, ? extends V> cancellable) {
|
||||
ReadRequest<V> _readRequest = new ReadRequest<V>(cancellable, this.parallel);
|
||||
ReadRequest<V> _readRequest = new ReadRequest<V>(this, cancellable, this.parallel);
|
||||
return this.<V>submit(_readRequest);
|
||||
}
|
||||
|
||||
public <U extends Object, V extends Object> CompletableFuture<V> runWrite(final Function0<? extends U> nonCancellable, final Function2<? super CancelIndicator, ? super U, ? extends V> cancellable) {
|
||||
final CompletableFuture<Void> cancelFuture = this.cancel();
|
||||
WriteRequest<U, V> _writeRequest = new WriteRequest<U, V>(nonCancellable, cancellable, cancelFuture);
|
||||
WriteRequest<U, V> _writeRequest = new WriteRequest<U, V>(this, nonCancellable, cancellable, cancelFuture);
|
||||
return this.<V>submit(_writeRequest);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
package org.eclipse.xtext.ide.server.concurrent;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor;
|
||||
import org.eclipse.xtext.ide.server.concurrent.AbstractRequest;
|
||||
import org.eclipse.xtext.ide.server.concurrent.RequestManager;
|
||||
import org.eclipse.xtext.util.CancelIndicator;
|
||||
import org.eclipse.xtext.xbase.lib.Exceptions;
|
||||
import org.eclipse.xtext.xbase.lib.Functions.Function0;
|
||||
|
@ -18,6 +20,8 @@ import org.eclipse.xtext.xbase.lib.Functions.Function2;
|
|||
@FinalFieldsConstructor
|
||||
@SuppressWarnings("all")
|
||||
public class WriteRequest<U extends Object, V extends Object> extends AbstractRequest<V> {
|
||||
private static final Logger LOG = Logger.getLogger(WriteRequest.class);
|
||||
|
||||
private final Function0<? extends U> nonCancellable;
|
||||
|
||||
private final Function2<? super CancelIndicator, ? super U, ? extends V> cancellable;
|
||||
|
@ -41,6 +45,9 @@ public class WriteRequest<U extends Object, V extends Object> extends AbstractRe
|
|||
} catch (final Throwable _t) {
|
||||
if (_t instanceof Throwable) {
|
||||
final Throwable e = (Throwable)_t;
|
||||
if (((e != null) && (!this.requestManager.isCancelException(e)))) {
|
||||
WriteRequest.LOG.error("Error during request: ", e);
|
||||
}
|
||||
this.result.completeExceptionally(e);
|
||||
} else {
|
||||
throw Exceptions.sneakyThrow(_t);
|
||||
|
@ -48,8 +55,8 @@ public class WriteRequest<U extends Object, V extends Object> extends AbstractRe
|
|||
}
|
||||
}
|
||||
|
||||
public WriteRequest(final Function0<? extends U> nonCancellable, final Function2<? super CancelIndicator, ? super U, ? extends V> cancellable, final CompletableFuture<Void> previous) {
|
||||
super();
|
||||
public WriteRequest(final RequestManager requestManager, final Function0<? extends U> nonCancellable, final Function2<? super CancelIndicator, ? super U, ? extends V> cancellable, final CompletableFuture<Void> previous) {
|
||||
super(requestManager);
|
||||
this.nonCancellable = nonCancellable;
|
||||
this.cancellable = cancellable;
|
||||
this.previous = previous;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
*/
|
||||
package org.eclipse.xtext.service;
|
||||
|
||||
import java.util.concurrent.CancellationException;
|
||||
|
||||
import org.eclipse.core.runtime.OperationCanceledException;
|
||||
import org.eclipse.xtext.util.CancelIndicator;
|
||||
|
||||
|
@ -19,6 +21,9 @@ import org.eclipse.xtext.util.CancelIndicator;
|
|||
*/
|
||||
public class OperationCanceledManager {
|
||||
protected RuntimeException getPlatformOperationCanceledException(Throwable t) {
|
||||
if (t instanceof CancellationException) {
|
||||
return (RuntimeException) t;
|
||||
}
|
||||
if (t instanceof OperationCanceledException) {
|
||||
return (RuntimeException) t;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue