我需要遍历appengine中的大型数据集。当然,由于数据存储在一段时间后超时,我决定使用任务来解决这个问题,这是试图解释我试图使用的方法:
Initialization of task via http post
0) Create query (entity.query()), and set a batch_size limit (i.e. 500)
1) Check if there are any cursors--if this is the first time running, there won't be any.
2a) If there are no cursors, use iter() with the following options: produce_cursors = true, limit= batch_size
2b) If there are curors, use iter() with same options as 2a + set start_cursor to the cursor.
3) Do a for loop to iterate through the results pulled by iter()
4) Get cursor_after()
5) Queue new task (basically re-run the task that was running) passing the cursor into the payload.
因此,如果此代码以我想要的方式工作,那么在队列中的任何特定时间只能运行1个任务。但是,我今天早上开始运行任务,3个小时后,当我查看队列时,其中有4个任务!这很奇怪,因为新任务只应在启动它的任务结束时启动。
这是没有编辑的实际代码:
class send_missed_swipes(BaseHandler): #disabled
def post(self):
"""Loops across entire database (as filtered) """
#Settings
BATCH_SIZE = 500
cursor = self.request.get('cursor')
start = datetime.datetime(2014, 2, 13, 0, 0, 0, 0)
end = datetime.datetime(2014, 3, 5, 0, 0, 00, 0)
#Filters
swipes = responses.query()
swipes = swipes.filter(responses.date>start)
if cursor:
num_updated = int(self.request.get('num_updated'))
cursor = ndb.Cursor.from_websafe_string(cursor)
swipes = swipes.iter(produce_cursors=True,limit=BATCH_SIZE,start_cursor=cursor)
else:
num_updated = 0
swipes = swipes.iter(produce_cursors=True,limit=BATCH_SIZE)
count = 0
for swipe in swipes:
count += 1
if swipe.date>end:
pass
else:
uKey = str(swipe.uuId.urlsafe())
pKey = str(swipe.pId.urlsafe())
act = swipe.act
taskqueue.add(queue_name="analyzeData", url="/admin/analyzeData/send_swipes", params={'act':act,'uKey':uKey,'pKey':pKey})
num_updated += 1
logging.info('count = '+str(count))
logging.info('num updated = '+str(num_updated))
cursor = swipes.cursor_after().to_websafe_string()
taskqueue.add(queue_name="default", url="/admin/analyzeData/send_missed_swipes", params={'cursor':cursor,'num_updated':num_updated})
这是一个复杂的问题,如果我需要更好地解释,请告诉我。谢谢你的帮助!
P.S。 app.yaml中的Threadsafe为false
答案 0 :(得分:1)
我相信任务可以多次执行,因此让您的流程具有幂等性非常重要。
来自doc https://developers.google.com/appengine/docs/python/taskqueue/overview-push
请注意,此示例不是幂等的。这项任务是可能的 队列以多次执行任务。在这种情况下,计数器是 每次运行任务时都会增加,可能会导致结果偏差。
您可以使用名称创建任务来处理此问题 https://developers.google.com/appengine/docs/python/taskqueue/#Python_Task_names
我很好奇为什么你的yaml中的线程安全=假?
答案 1 :(得分:1)
有点偏离主题(因为我没有解决你的问题),但这听起来像是map reduce的工作。
关于主题:您可以使用max_concurrent_requests=1
创建自定义队列。您仍然可以在队列中拥有多个任务,但一次只能执行一个任务。