How to return data from a deferred task in Google App Engine

Original question

I have a working version of my web application that I am trying to update at the moment, and I encountered the problem of completing a task that takes too long to complete in one HTTP request. The application receives the JSON list from the external JavaScript interface using the HTTP Post operation and returns a sorted / cut version of this list. As the input list grows, the sort operation takes a lot more time (obviously), so on suitable long input lists, I delete the 60-minute timeout of the HTTP request and the application fails.

I would like to start using the lazy library to do the sorting task, but I don’t understand how to store / retrieve data after this task is done. Here is my current code:

class getLineups(webapp2.RequestHandler):
  def post(self):
    jsonstring = self.request.body
    inputData = json.loads(jsonstring)
    playerList = inputData["pList"]
    positions = ["QB","RB","WR","TE","DST"]

    playersPos = sortByPos(playerList,positions)
    rosters, playerUse = getNFLRosters(playersPos, positions)
    try:
      # This step is computationally expensive, it will fail on large player lists.
      lineups = makeLineups(rosters,playerUse,50000)

      self.response.headers["Content-Type"] = "application/json"
      self.response.out.write(json.dumps(lineups))
    except:
      logging.error("60 second timeout reached on player list of length:", len(playerList))
      self.response.headers["Content-Type"] = "text/plain"
      self.response.set_status(504)

app = webapp2.WSGIApplication([
  ('/lineup',getLineups),
], debug = True)

Ideally, I would like to replace the entire try / except block with a call to the deferred task library:

deferred.defer(makeLineups,rosters,playerUse,50000)

But I do not understand how I will get the result from this operation. I think I will need to store it in the data store and then restore it, but how will my JavaScript interface know when the operation is complete? I read the documentation on Google, but I'm still unclear how to complete this task.

How i decided this

Using the main outline in the accepted answer, here is how I solved this problem:

def solveResult(result_key):
  result = result_key.get()

  playersPos = sortByPos(result.playerList, result.positions)
  rosters, playerUse = getNFLRosters(playersPos,result.positions)

  lineups = makeLineups(rosters,playerUse,50000)
  storeResult(result_key,lineups)

@ndb.transactional
def storeResult(result_key,lineups):
  result = result_key.get()
  result.lineups = lineups
  result.solveComplete = True
  result.put()

class Result(ndb.Model):
  playerList = ndb.JsonProperty()
  positions = ndb.JsonProperty()
  solveComplete = ndb.BooleanProperty()

class getLineups(webapp2.RequestHandler):
  def post(self):
    jsonstring = self.request.body
    inputData = json.loads(jsonstring)

    deferredResult = Result(
      playerList = inputData["pList"],
      positions = ["QB","RB","WR","TE","DST"],
      solveComplete = False
    )

    deferredResult_key = deferredResult.put()

    deferred.defer(solveResult,deferredResult_key)

    self.response.headers["Content-Type"] = "text/plain"
    self.response.out.write(deferredResult_key.urlsafe())

class queryResults(webapp2.RequestHandler):
  def post(self):
    safe_result_key = self.request.body
    result_key = ndb.Key(urlsafe=safe_result_key)

    result = result_key.get()
    self.response.headers["Content-Type"] = "application/json"

    if result.solveComplete:
      self.response.out.write(json.dumps(result.lineups))
    else:
      self.response.out.write(json.dumps([]))

Javascript URL- queryLineups , , . , , . , , - , .

+4
3

GAE, , .

, . :

  • . . ( ) (PENDING | DONE | FAILED). , .
  • . . , . , .
  • , . setTimeout setInterval, ( ). , ( ).
  • .
+4

, . , , , - , , , - , () ... .

, :  - ,  -

, , , . , , , , , . , , Google, , -.

0

, -, , 1 , . , HTTP- 1 . 60 , GAE, .

, , , :

, .

0

Source: https://habr.com/ru/post/1618489/


All Articles