Contention happens using Task Queue

174 views
Skip to first unread message

Yun Li

unread,
Dec 3, 2015, 9:14:36 PM12/3/15
to Google App Engine
I am using Objectify. This error happens when updating a single datastore entity. There is NO TRANSACTION. My working flow as follows:

1 Entity entity1 = Objectify.read(id1)
2 Modify entity1's property and put "update(entity1)" in a taskqueue
3 When task executes: Objectify.save(entity1)

Then I get java.util.ConcurrentModificationException: too much contention on these datastore entities

It's so weird because the log shows that even two requests try to update entity1, their execution interval could be more than 10s. I am a new GAE user, anybody helps me ?

Jeff Schnitzer

unread,
Dec 4, 2015, 12:59:00 AM12/4/15
to Google App Engine
You'll need to post some more code details - including the structure of the object you are trying to change. Also you don't mention whether this is an exception or just a log message. It's easy to accidentally create contention with the task queue, especially if you're in a transaction and enqueueing non-transactional tasks (which often start immediately).

Jeff

--
You received this message because you are subscribed to the Google Groups "Google App Engine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-appengi...@googlegroups.com.
To post to this group, send email to google-a...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-appengine.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-appengine/52790fdf-d521-4f95-b35d-217bcbe2379c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Yun Li

unread,
Dec 15, 2015, 2:59:45 PM12/15/15
to Google App Engine, je...@infohazard.org

Entity entity= EntityDao.get(entityID);

// get parameters, gpsLat, batteryLevel...etc.

        queue.add(TaskOptions.Builder.withUrl("/update").param(Parameters.EntityID, entityID).param("gpsLong", gpsLong)
.param("gpsLat", gpsLat)
.param("batt", batteryLevel)
.param("connection", connectedState)
.param("time", lastTimeUpdated)
);


After some updating---> set the gpsLat, batt, connection, etc. 

EntityDao.put(updatedEntity);

which is:
ofy().save().entity(updatedEntity).now();


And my GAE log says:

java.util.ConcurrentModificationException: too much contention on these datastore entities. please try again. at com.google.appengine.api.datastore.DatastoreApiHelper.translateError(DatastoreApiHelper.java:57) at com.google.appengine.api.datastore.DatastoreApiHelper$1.convertException(DatastoreApiHelper.java:129) at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:96) at com.google.appengine.api.datastore.Batcher$ReorderingMultiFuture.get(Batcher.java:131) at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:88) at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:88) at com.googlecode.objectify.cache.TriggerFuture.get(TriggerFuture.java:102) at com.googlecode.objectify.impl.ResultAdapter.now(ResultAdapter.java:34) at com.googlecode.objectify.util.ResultWrapper.translate(ResultWrapper.java:22) at com.googlecode.objectify.util.ResultWrapper.translate(ResultWrapper.java:10) at com.googlecode.objectify.util.ResultTranslator.nowUncached(ResultTranslator.java:21) at com.googlecode.objectify.util.ResultCache.now(ResultCache.java:30) at com.googlecode.objectify.util.ResultWrapper.translate(ResultWrapper.java:22) at com.googlecode.objectify.util.ResultWrapper.translate(ResultWrapper.java:10) at com.googlecode.objectify.util.ResultTranslator.nowUncached(ResultTranslator.java:21) at com.googlecode.objectify.util.ResultCache.now(ResultCache.java:30) at com.phonehalo.server.dao.TrackerDao.put(TrackerDao.java:17) at com.phonehalo.server.servlet.TrackRupdate.doPost(TrackRupdate.java:65) at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:263) at com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:178) at com.google.inject.servlet.ManagedServletPipeline.service(ManagedServletPipeline.java:91) at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:62) at com.google.inject.servlet.FilterDefinition.doFilter(FilterDefinition.java:168) at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:58) at com.googlecode.objectify.cache.AsyncCacheFilter.doFilter(AsyncCacheFilter.java:59) at com.googlecode.objectify.ObjectifyFilter.doFilter(ObjectifyFilter.java:49) at com.google.inject.servlet.FilterDefinition.doFilter(FilterDefinition.java:163) at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:58) at com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:118) at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:113)
.....

Yun Li

unread,
Dec 15, 2015, 3:02:23 PM12/15/15
to Google App Engine, je...@infohazard.org
And there is NO transaction at all. We don't use transaction. But I am not sure if objectify uses the transaction in put. 


On Thursday, December 3, 2015 at 9:59:00 PM UTC-8, Jeff Schnitzer wrote:

Christian F. Howes

unread,
Dec 16, 2015, 9:20:14 PM12/16/15
to Google App Engine, je...@infohazard.org
is the object part of an entity group?  there is a limit on the number of writes to an entity group (with or without transactions)

Alex Martelli

unread,
Dec 17, 2015, 5:42:08 PM12/17/15
to google-a...@googlegroups.com, je...@infohazard.org
On Wed, Dec 16, 2015 at 6:20 PM, Christian F. Howes <christi...@starmakerinteractive.com> wrote:
is the object part of an entity group?  there is a limit on the number of writes to an entity group (with or without transactions)

Yep, and, note that "being part of an entity group" just means "having an ancestor"...


Alex
 

Jeff Schnitzer

unread,
Dec 17, 2015, 6:55:44 PM12/17/15
to Google App Engine
Also a nearly guaranteed way to create contention is to modify an entity and then non-transactionally enqueue a task which modifies that entity. The task fires immediately and the two writes conflict.

The great thing about enqueueing transactional tasks is that the task is guaranteed to fire *after* the commit.

Jeff


Reply all
Reply to author
Forward
0 new messages