"BadRequestError: cursor position out of range of original request" when receiving next batch of request

I have this handler to do some sort of process for all users of our application. Basically, it takes 1 packet, processes the records of that batch, and then enqueues a new task for the next batch.

QueueAllUsers(BaseHandler):
    FETCH_SIZE = 10
    FILTERS = [
        UserConfig.level != 0,
        UserConfig.is_configured == True
    ]
    ORDER = [UserConfig.level, UserConfig._key]

    def get(self):
        cursor_key = self.request.get('cursor')
        cursor = None
        if cursor_key:
            # if `cursor` param is provided, use it
            cursor = Cursor(urlsafe=str(cursor_key))
        q = UserConfig.query(*self.FILTERS).order(*self.ORDER)
        total = q.count()  # 31 total records
        logging.info(total)
        users, next_cursor, more = q.fetch_page(self.FETCH_SIZE,
                                                keys_only=True,
                                                start_cursor=cursor)
        self.process_users(users)
        if more:
            self.queue_next_batch(next_cursor)

    def queue_next_batch(self, next_cursor):
        # Call get() again but this time pass `cursor` param to process next batch
        logging.info(next_cursor.urlsafe())
        url = '/queue_all_users?cursor=%s' % (next_cursor.urlsafe())
        taskqueue.add(
            url=url,
            method='get',
            queue_name='cronjobs'
        )

    def process_users(self, users):
        logging.info(len(users))
        # trimmed

      

But when the task for the second batch is run, NDB throws an error BadRequest

saying that the cursor is out of range.

I don't understand why this is out of range? I fetched 10

records from the total 31

, so the cursor will still be valid.

Note that the bug is picked in the second batch (i.e. recording 11-20

).

So the stream looks like this:

  • Call /queue_all_users

    for processing the first batch (without cursor). Everything works fine.
  • Step 1 creates a task /queue_all_users?cursor=123456

    for the next batch.
  • Call /queue_all_users?cursor=123456

    (cursor provided). fetch_page

    throws BadRequestErrror

    .

EDIT : I tried setting FETCH_SIZE

on 17

and the 2nd batch fetch worked! It seems that something below 17

is causing the error, and it works 17

. So ... what the hell?

+3


source to share


1 answer


I had the same problem. When I make the first request everything goes well and a cursor is returned. The second query using a cursor will give me an error:

BadRequestError: cursor position is outside the range of the original query.

      

I tried your solution but doesn't work for me. So I change my filters in my request and it works , I don't know why, but maybe there might be a solution for you and others.

My old query:



page_size = 10
query = Sale.query(ancestor=self.key).filter(ndb.AND(
    Sale.current_status.status != SaleStatusEnum.WAITING_PAYMENT,
    Sale.current_status.status != SaleStatusEnum.WAITING_PAYMENT
    ).order(Sale.current_status.status, Sale._key)
query.fetch_page(page_size, start_cursor=cursor)

      

Then a change all the "! =" Operations to IN, for example:

page_size = 10
query = Sale.query(ancestor=self.key).filter(
    Sale.current_status.status.IN([
        SaleStatusEnum.PROCESSING, 
        SaleStatusEnum.PAID, 
        SaleStatusEnum.SHIPPING, 
        SaleStatusEnum.FINALIZED,
        SaleStatusEnum.REFUSED])
    ).order(Sale.current_status.status, Sale._key)
query.fetch_page(page_size, start_cursor=cursor)

      

+1


source







All Articles