ChangeStream::next() should increment key even if ResumeTokenException is thrown

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Fixed
    • Priority: Major - P3
    • 1.3.1
    • Affects Version/s: 1.3.0
    • Component/s: None
    • None
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      While reviewing the PR for PHPLIB-327, I noticed that the key is only incremented if resume token extraction is successful. In actuality, ChangeStream will already have advanced the underlying current cursor. If the current element is valid after advancing (i.e. we didn't poll the server and find that there's no new event to report), we should increment the key before attempting extraction by swapping the existing two lines:

      if ($this->valid()) {
          $this->key++; // Previously below $this->resumeToken assignment
          $this->resumeToken = $this->extractResumeToken($this->csIt->current());
      }
      

      Test case:

      public function testResumeTokenNotFoundAdvancesKey()
      {
          $pipeline =  [['$project' => ['_id' => 0 ]]];
      
          $operation = new Watch($this->manager, $this->getDatabaseName(), $this->getCollectionName(), $pipeline, $this->defaultOptions);
          $changeStream = $operation->execute($this->getPrimaryServer());
      
          /* Note: we intentionally do not start iteration with rewind() to ensure
           * that we test extraction functionality within next(). */
          $this->insertDocument(['x' => 1]);
          $this->insertDocument(['x' => 2]);
          $this->insertDocument(['x' => 3]);
      
          try {
              $changeStream->rewind();
              $this->fail('ResumeTokenException was not thrown');
          } catch (ResumeTokenException $e) {}
      
          $this->assertSame(0, $changeStream->key());
      
          try {
              $changeStream->next();
              $this->fail('ResumeTokenException was not thrown');
          } catch (ResumeTokenException $e) {}
      
          $this->assertSame(1, $changeStream->key());
      
          try {
              $changeStream->next();
              $this->fail('ResumeTokenException was not thrown');
          } catch (ResumeTokenException $e) {}
      
          $this->assertSame(2, $changeStream->key());
      }
      

            Assignee:
            Katherine Walker (Inactive)
            Reporter:
            Jeremy Mikola
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: