Advance the cursor without blocking indefinitely. This method returns the next change document without waiting indefinitely for the next change. For example:: with db.collection.watch() as stream: while stream.alive: change = stream.t
(self)
| 338 | |
| 339 | @_csot.apply |
| 340 | def try_next(self) -> Optional[_DocumentType]: |
| 341 | """Advance the cursor without blocking indefinitely. |
| 342 | |
| 343 | This method returns the next change document without waiting |
| 344 | indefinitely for the next change. For example:: |
| 345 | |
| 346 | with db.collection.watch() as stream: |
| 347 | while stream.alive: |
| 348 | change = stream.try_next() |
| 349 | # Note that the ChangeStream's resume token may be updated |
| 350 | # even when no changes are returned. |
| 351 | print("Current resume token: %r" % (stream.resume_token,)) |
| 352 | if change is not None: |
| 353 | print("Change document: %r" % (change,)) |
| 354 | continue |
| 355 | # We end up here when there are no recent changes. |
| 356 | # Sleep for a while before trying again to avoid flooding |
| 357 | # the server with getMore requests when no changes are |
| 358 | # available. |
| 359 | time.sleep(10) |
| 360 | |
| 361 | If no change document is cached locally then this method runs a single |
| 362 | getMore command. If the getMore yields any documents, the next |
| 363 | document is returned, otherwise, if the getMore returns no documents |
| 364 | (because there have been no changes) then ``None`` is returned. |
| 365 | |
| 366 | :return: The next change document or ``None`` when no document is available |
| 367 | after running a single getMore or when the cursor is closed. |
| 368 | |
| 369 | .. versionadded:: 3.8 |
| 370 | """ |
| 371 | if not self._closed and not self._cursor.alive: |
| 372 | self._resume() |
| 373 | |
| 374 | # Attempt to get the next change with at most one getMore and at most |
| 375 | # one resume attempt. |
| 376 | try: |
| 377 | try: |
| 378 | change = self._cursor._try_next(True) |
| 379 | except PyMongoError as exc: |
| 380 | if not _resumable(exc): |
| 381 | raise |
| 382 | self._resume() |
| 383 | change = self._cursor._try_next(False) |
| 384 | except PyMongoError as exc: |
| 385 | # Close the stream after a fatal error. |
| 386 | if not _resumable(exc) and not exc.timeout: |
| 387 | self.close() |
| 388 | raise |
| 389 | # Catch KeyboardInterrupt, CancelledError, etc. and cleanup. |
| 390 | except BaseException: |
| 391 | self.close() |
| 392 | raise |
| 393 | |
| 394 | # Check if the cursor was invalidated. |
| 395 | if not self._cursor.alive: |
| 396 | self._closed = True |
| 397 |