freme-project / e-Link

Apache License 2.0
0 stars 0 forks source link

Parallel creation of templates results in ConstraintViolationException #52

Closed ghsnd closed 9 years ago

ghsnd commented 9 years ago

I don't know if this is an issue related to e-Link or to the Broker, but it is easily reproducable with e-Link.

Creating templates in parallel results in a ConstraintViolationException.

Execute this in a bash shell (but change the curl command according to your test environment first). It just creates 10 templates in parallel:

for req in {1..10}
do
    curl -X POST --header "x-auth-token: <yourToken>" --header "content-type: application/json" -d "@template.json" "http://localhost:8080/e-link/templates" &
done

Where template.json is for example:

{
    "query":" PREFIX geo-pos: <http://www.w3.org/2003/01/geo/wgs84_pos#> CONSTRUCT { <@@@entity_uri@@@> geo-pos:lat ?lat . <@@@entity_uri@@@> geo-pos:long ?long . } WHERE { <@@@entity_uri@@@> geo-pos:lat ?lat . <@@@entity_uri@@@> geo-pos:long ?long . }",
    "endpoint":"http://factforge.net/sparql",
    "label":"Good name for template",
    "description":"This template finds the geo coordinates of a place.",
    "type": "SPARQL"
}

but it can be any template.

Some requests execute well, some give this response:

{
  "exception": "eu.freme.broker.exception.InternalServerErrorException",
  "path": "/e-link/templates",
  "message": "could not execute statement; SQL [n/a]; constraint [\"PRIMARY KEY ON PUBLIC.TEMPLATE(ID)\"; SQL statement:\ninsert into template (owner_name, visibility, description, endpoint, label, query, type, id) values (?, ?, ?, ?, ?, ?, ?, ?) [23505-187]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
  "error": "Internal Server Error",
  "status": 500,
  "timestamp": 1445435916506
}

I will also test this on pipelines later on.

jnehring commented 9 years ago

@ArneBinder please take a look at this.

jnehring commented 9 years ago

We hope this is going to be solved by freme-project/FREMECommon#11

ArneBinder commented 9 years ago

@ghsnd could you have a look, if this problem still occurs? Please reassign to me or close this issue, if it's solved. thanks!

ghsnd commented 9 years ago

It still occurs. Plus, sometimes the response is

{
  "exception": "eu.freme.broker.exception.InternalServerErrorException",
  "path": "/e-link/templates",
  "message": "A different object with the same identifier value was already associated with the session : [eu.freme.common.persistence.model.Template#1]; nested exception is javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [eu.freme.common.persistence.model.Template#1]",
  "error": "Internal Server Error",
  "status": 500,
  "timestamp": 1445961839333
}

On the Broker, this is logged:

org.springframework.dao.DataIntegrityViolationException: A different object with the same identifier value was already associated with the session : [eu.freme.common.persistence.model.Template#1]; nested exception is javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [eu.freme.common.persistence.model.Template#9]
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:407)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy95.save(Unknown Source)
    at eu.freme.common.persistence.dao.DAO.save(DAO.java:58)
    at eu.freme.common.persistence.dao.OwnedResourceDAO.save(OwnedResourceDAO.java:78)
    at eu.freme.broker.eservices.ELink.createTemplate(ELink.java:259)

And when returning a 200 OK, it happens that templates get the same id in the response. Example (mind the difference in timestamp, though they have the same id):

{
  "id" : 2,
  "creationTime" : 1445961839666,
    ... rest of the template
}

{
  "id" : 2,
  "creationTime" : 1445961839722,
  ... rest of the template
}

Only the second one is saved (overwrites the first one) and listed when getting al the templates.

ArneBinder commented 9 years ago

Ok, this is strange. Does this also happen on freme-dev or just at your local instance? At the moment I'm not able to reproduce this.

ghsnd commented 9 years ago

Ok, this is strange. Does this also happen on freme-dev or just at your local instance? At the moment I'm not able to reproduce this.

You 're right: it doesn't happen on the dev server. Before I close this issue, I will try again locally after a fresh update.

ghsnd commented 9 years ago

Now it works.

However, if I raise the number of concurrent requests to 300, a org.hibernate.PessimisticLockException occurs (only locally, not on the dev server). It boils down to the in-memory h2 database. It can be avoided if this method in the TokenService gets synchronized:

public synchronized Token updateLastUsed(Token token){

But this slows things down enormously.

So I consider this issue closed as it works on the dev server. I will open a new issue for the case of using the in-memory database, but this is probably not to be fixed in Prototype 4. (Or is it, @jnehring ?)

ghsnd commented 9 years ago

See also issue freme-project/Broker#130.