Reputation: 121
Using SDN 3.3.1 and Neo4j 2.1.7 in external server setup.
I am having java.net.SocketTimeoutException: Read timed out
whenever I do the following execution pattern :
MyEntity entity = myRepository.findByUuid(uuid);
neo4jOperations.query("match (e{uuid:"theuuid"})<-[r:THE_RELATION]-() delete r);
entity.setTitle("New title");
myRepository.save(entity);
--> waiting a long time then got the SocketTimeoutException
After some analysis, it appears to me that 1. does http calls inside AND outside the transaction as you can see in this Neo4j http log extract :
127.0.0.1 - - [20/août/2015:10:47:57 +0200] "POST /db/data/transaction HTTP/1.1" 201 659 "-" "neo4j-rest-graphdb/0"
127.0.0.1 - - [20/août/2015:10:47:57 +0200] "GET /db/data/node/135/relationships/in/WITH_ROLE HTTP/1.1" 200 391 "-" "neo4j-rest-graphdb/0"
127.0.0.1 - - [20/août/2015:10:47:57 +0200] "GET /db/data/node/149 HTTP/1.1" 200 1780 "-" "neo4j-rest-graphdb/0"
127.0.0.1 - - [20/août/2015:10:47:57 +0200] "GET /db/data/node/135/relationships/out/DEFAULT_ENTITY HTTP/1.1" 200 401 "-" "neo4j-rest-graphdb/0"
127.0.0.1 - - [20/août/2015:10:47:57 +0200] "GET /db/data/node/227 HTTP/1.1" 200 1884 "-" "neo4j-rest-graphdb/0"
127.0.0.1 - - [20/août/2015:10:47:57 +0200] "GET /db/data/node/135/relationships/in/WITH_PENDING_ROLE HTTP/1.1" 200 2 "-" "neo4j-rest-graphdb/0"
So my first question would be :
Then, the delete operation in 2. is correctly done inside the transaction :
127.0.0.1 - - [20/août/2015:10:47:58 +0200] "POST /db/data/transaction/2720 HTTP/1.1" 200 254 "-" "neo4j-rest-graphdb/0"
The point 3. obviously generates no http request.
And at the end, the point 4. which generate a SocketTimeoutException
after being "blocked" for a time (30 sec to be precise), finally generate 2 http requests :
127.0.0.1 - - [20/août/2015:10:48:28 +0200] "DELETE /db/data/transaction/2720 HTTP/1.1" 200 26 "-" "neo4j-rest-graphdb/0"
127.0.0.1 - - [20/août/2015:10:48:28 +0200] "PUT /db/data/node/135/properties HTTP/1.1" 204 0 "-" "neo4j-rest-graphdb/0"
The delete is because the transaction is rollbacked, and I think the PUT corresponds to the save()
In my opinion, a deadlock is happening because of the PUT being outside of the transaction ! So, the main question is :
save()
making a PUT outside of the transaction and not a POST inside the transaction ? Is there a way to force the entity update to be done using the transactional endpoint ?Thanks :)
EDIT : Added SDN config
<beans ...>
<tx:annotation-driven />
<context:component-scan base-package="com.myproject.mw.neo4j.service,com.myproject.mw.neo4j.aspect" />
<aop:aspectj-autoproxy />
<!-- External database config -->
<bean id="graphDatabaseServiceExternal" class="org.springframework.data.neo4j.rest.SpringCypherRestGraphDatabase"
lazy-init="true">
<constructor-arg index="0" value="${neo4j.path}" />
</bean>
<alias name="graphDatabaseService${neo4j.mode}" alias="graphDatabaseService" />
<neo4j:config base-package="com.myproject.mw.neo4j.domain"
graphDatabaseService="graphDatabaseService" />
<neo4j:repositories base-package="com.myproject.mw.neo4j.repository" />
</beans>
EDIT 2 : Added entities definition and simple test to reproduce
Note that my Neo4j server is on localhost.
The test :
@Test
@Transactional
@Rollback(false)
public void testEntityNotFound() {
BusinessCard card = genericRepository.findByUuid("4bce6162-bc6f-bce2-bc71-bc70b63dff00");
Entity entity = genericRepository.findByUuid("04947df8-0e9e-4471-a2f9-9af509fb5889");
neo4jOperations.createRelationshipBetween(neo4jOperations.getNode(entity.getId()),
neo4jOperations.getNode(card.getId()), "FAKE2", null);
neo4jOperations.save(card);
}
BusinessCard entity :
public class BusinessCard extends GenericNode {
@Indexed
private String title;
@RelatedTo(type = RelationNames.WITH_ROLE, direction = Direction.INCOMING)
private User user;
@RelatedTo(type = RelationNames.WITH_PENDING_ROLE, direction = Direction.INCOMING)
private User pendingUser;
@RelatedTo(type = RelationNames.DEFAULT_ENTITY)
private Entity defaultEntity;
}
And the Entity entity :
public class Entity extends GenericNode {
private String logo;
@Indexed
private String entityName;
@RelatedTo(type = RelationNames.IS_IN_CITY)
private CityNode mainCity;
@RelatedTo(type = RelationNames.IS_IN_COUNTRY)
private CountryNode mainCountry;
@RelatedTo(type = RelationNames.IS_IN_COUNTRIES)
private Set<CountryNode> countries;
@Fetch
@RelatedToVia(type = RelationNames.TRANSLATION)
private Set<EntityToEntityTranslatedContent> entityTranslatedContent;
@Fetch
@RelatedTo(type = RelationNames.HAS_KEY_STAGES)
private KeyStage lastKeyStage;
@GraphProperty(propertyType = Long.class)
private Date lastProfileUpdateDateTime;
private Integer profilCompletionIndice;
@RelatedToVia(type = RelationNames.WORKS_AT, direction = Direction.INCOMING)
private Set<BusinessCardWorkAt> employees = new HashSet<>();
...+34 more fields...
}
Upvotes: 2
Views: 249
Reputation: 121
This was fixed in SDN 3.4 (see https://jira.spring.io/browse/DATAGRAPH-699). This jira ticket content is a different topic but you can rely on the modified title "Implement missing operations for Cypher based REST-API separately". Since 3.4 there is no more out of transaction REST requests when using @Transactional.
Upvotes: 0
Reputation: 41676
Something is off with your entities then, it seems to spend a lot of time writing data to the server. From your thread dumps:
at org.neo4j.rest.graphdb.ExecutingRestRequest.put(ExecutingRestRequest.java:155)
at org.neo4j.rest.graphdb.RestAPIImpl.setPropertiesOnEntity(RestAPIImpl.java:633)
at org.neo4j.rest.graphdb.entity.RestEntity.flush(RestEntity.java:189)
at org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.copyPropertiesTo(SourceStateTransmitter.java:109)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.write(Neo4jEntityConverterImpl.java:170)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedConverter.write(Neo4jEntityPersister.java:179)
and for dump 2:
at org.neo4j.rest.graphdb.ExecutingRestRequest.put(ExecutingRestRequest.java:155)
at org.neo4j.rest.graphdb.RestAPIImpl.setPropertiesOnEntity(RestAPIImpl.java:633)
at org.neo4j.rest.graphdb.entity.RestEntity.flush(RestEntity.java:189)
at org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.copyPropertiesTo(SourceStateTransmitter.java:109)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.write(Neo4jEntityConverterImpl.java:170)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedConverter.write(Neo4jEntityPersister.java:179)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:247)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:235)
at org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:365)
There must be also something other off, because
org.springframework.data.neo4j.rest.SpringCypherRestGraphDatabase
should NOT use the normal Rest endpoints with GET,PUT,DELETE etc. but just plain Cypher.
You should also check the latency and bandwidth to your server, SDN3 is still quite chatty.
So you should share the code for your entities, what you exactly do before/when you called that save and how much data is sent to the server.
For a better SDN + Server experience I recommend to have a look at SDN4 which was written from scratch for that purpose. SDN4 RC2 was released last Friday:
http://docs.spring.io/spring-data/neo4j/docs/4.0.0.RC2/reference/html/
Upvotes: 0
Reputation: 15076
I assume you are using org.springframework.data.neo4j.rest.SpringRestGraphDatabase
, which is now deprecated, and doesn't support transactions properly. (see this code that generates your PUT)
There is a new cypher based database org.springframework.data.neo4j.rest.SpringCypherRestGraphDatabase
, which might do what you want.
You also want to look into 4.x version, which is an overhaul of SDN focused on using neo4j remotely over rest, in a more efficient way. It is supposed to go GA soon.
Some more explanation is provided on this blog http://jexp.de/blog/2014/12/spring-data-neo4j-improving-remoting-performance/
Upvotes: 1