Google App Engine Python - Protorpc&& TASKQUEUE

时间:2014-10-14 17:21:33

标签: python performance google-app-engine task-queue protorpc

如何使用Protorpc的任务队列(推送队列)。

我有一个目标网页表单,在发送时会执行多项操作:

  • 保存DataStore中的字段
  • 发送电子邮件至表单的发件人
  • 将字段发送到第三方应用程序(比如说CRM)

使用protorpc在服务器端实现表单发送。

class FormRequest(messages.Message)
  field1 = messages.StringField(1, required=True)
  field2 = messages.StringField(2, required=True)

...

class FormApi(remote.Service):
  @remote.method(TravelRequest, message_types.VoidMessage)
  def insert(self, request):
    # Save the form in the DataStore
    travel = FormModel(field1=request.field1, field2=request.field2)
    travel.put()

    # Send an email to the client
    ...

    # Send the data to a third party
    ...

    return message_types.VoidMessage()

此解决方案被卡住,因为用户需要等待所有请求时间。 (在这种情况下,它只有2-3s,但对于登陆页面形式来说很多)

一个好的解决方案是使用taskqueue来最小化用户需要等待的时间:

(例如)

class ...
  @remote ...
  def ...
    # Save the form in the DataStore
    taskqueue.add(url='/api/worker/save_to_db', params={'field1': request.field1, 'field2': request.field2})
    # Send an email to the client
    taskqueue.add(url='/api/worker/send_email', params={'field1': request.field1, 'field2': request.field2})
    # Send the data to a third party (CRM)
    taskqueue.add(url='/api/worker/send_to_crm', params={'field1': request.field1, 'field2': request.field2})

“问题”是protorpc只获取json对象作为请求。 如何使用TaskQueue(推送)执行此操作?

TaskQueue的默认行为是将params作为urlencoded的字符串发送,并且它不符合protorpc。

2 个答案:

答案 0 :(得分:1)

让我们为任务队列定义一个工作服务:

class WorkersApi(remote.Service):
  @remote.method(TravelRequest, message_types.VoidMessage)
  def save_to_db(self, request):
    # Instead of write each parameter, I am using this "cheat"
    params = {}
    for field in request.all_fields():
      params[field.name] = getattr(request, field.name)

    # Save data in the datastore
    form_model = FormModel(**params)
    form_model.put()

    return message_types.VoidMessage()

注意我对真实请求和任务队列请求使用相同的message对象(不需要为每个请求创建和使用不同的message对象,这是一个很大的优势) 问题是如何使用这个protorpc函数使用taskqueue。

正如我在问题中所说,taskqueue的默认行为不是很方便。

解决方案将orignal请求/消息(在我们的示例中为FormRequest)对象转换回字符串并将标头设置为任务队列,有效负载为application/json

以下是代码:

# This format string is take from the util file in the protorpc folder in Google App Engine source code
format_string = '%Y-%m-%dT%H:%M:%S.%f'

params = {}
for field in request.all_fields():
  value = getattr(request, field.name)
  if (isinstance(value, datetime.datetime)):
    value = value.strftime(format_string)
  params[field.name] = value

taskqueue.add(url='/api/workers.save_to_db', payload=json.dumps(params), headers={'content-type':'application/json'})

为"电子邮件"做同样的事情。和" crm"。

答案 1 :(得分:0)

您可以毫不费力地使用put_async()进行写入:将实体的数据异步写入数据存储区。

例如:

travel = FormModel(field1=request.field1, field2=request.field2)
travel.put_async()
# next action