[Neo] Estrange exception when running multithreaded
Mattias Persson
mattias at neotechnology.com
Fri Feb 26 09:52:54 CET 2010
2010/2/26 Raul Raja Martinez <raulraja at gmail.com>:
> Hi Mattias,
>
> Thanks for the docs.
> I'm trying to solve this issue now and here is the problem I'm facing...
>
> Where it says in the wiki:
> "Rewrite your code, making sure that such scenarios won't happen.
> Run your deadlock-prone code in a try-catch(DeadlockDetectedException)
> block and just rerun the entire transaction if such an exception is
> caught."
>
> My transactions start and end in an interceptor that provides advice
> to method invokations.
> The invokations happen inside a thread pool concurrently.
>
> This is what the interceptor looks like. I have no way to recover from
> the deadlock. Are you implying in that advice that
> I should synchronize in the operation that is causing the write lock?
> Is there anyway to configure Neo to wait on deadlock for a release up
> to certain time?
> If I reissue a method call that is transactional other state not
> related to the neo transactions such as indexes, etc... may modify
> other state objects, I'd rather have the transaction wait for release
> and continue as other transactions are completing.
To make the executing thread wait would result in a deadlock, that's
why the exception is thrown so that isn't really an option.
Regarding state: if you're referring to components in neo4j, they all
handle state correctly if a transaction is rolled back (in this case
where a DeadlockDetectedException is thrown)... even the IndexService
and such components so that won't be a problem.
>
> Here is the code for the interceptor. The advised methods are
> Runnables that get executed async by a threadpool.
>
> /**
> * A method interceptor that provides transaction advice around a
> method invocation opening and closing a transaction accordingly
> */
> public class Neo4JTransactionAdviceInterceptor implements MethodInterceptor {
>
> private final static Logger log =
> Logger.getLogger(Neo4JTransactionAdviceInterceptor.class);
>
> private GraphDatabaseService neoService;
>
> public void setNeoService(GraphDatabaseService neoService) {
> this.neoService = neoService;
> }
>
> /**
> * provides transaction advice around a method invocation opening
> and closing a transaction accordingly
> *
> * @param invocation the method invocation joinpoint
> * @return the result of the call to {@link
> * org.aopalliance.intercept.Joinpoint#proceed()}, might
> be intercepted by the
> * interceptor.
> * @throws Throwable if the interceptors or the
> * target-object throws an exception.
> */
> public Object invoke(MethodInvocation invocation) throws Throwable {
> Transaction tx = neoService.beginTx();
> Object result = null;
> try {
> result = invocation.proceed();
> tx.success();
> } catch (DeadlockDetectedException e) {
> tx.failure();
> log.debug("deadlock detected for invocation " + invocation
> + " result: " + result + " transaction: " + tx);
> } catch (Throwable t) {
> tx.failure();
> throw t;
> } finally {
> tx.finish();
> }
> return result;
> }
> }
>
>
How about making your code look something like (I removed unecessary
tx.failure() calls, see
http://wiki.neo4j.org/content/Transactions#Controlling_success):
public Object invoke(MethodInvocation invocation) throws Throwable {
Object result = null;
for ( int i = 0; i < 10; i++ ) {
Transaction tx = neoService.beginTx();
try {
result = invocation.proceed();
tx.success();
return result;
} catch (DeadlockDetectedException e) {
log.debug("deadlock detected for invocation " + invocation
+ " result: " + result + " transaction: " + tx);
} finally {
tx.finish();
}
}
return result;
}
Where 10 is the number of retries to do before giving up. It may not
look very elegant, but there's really no "silver bullet" for the the
deadlock problem.
--
Mattias Persson, [mattias at neotechnology.com]
Neo Technology, www.neotechnology.com
More information about the User
mailing list