ZhenyuLi created SOLR-18406:
-------------------------------

             Summary: Replication filecontent returns HTTP 500 when the commit 
reservation expires
                 Key: SOLR-18406
                 URL: https://issues.apache.org/jira/browse/SOLR-18406
             Project: Solr
          Issue Type: Bug
          Components: replication (java)
    Affects Versions: 9.10.1, 8.11.4
            Reporter: ZhenyuLi


A follower can receive HTTP 500 while downloading an index if the leader deletes
  the requested index generation after filelist completes but before a 
subsequent
  filecontent request begins.

  Follower index replication consists of separate HTTP requests:

    indexversion
      -> filelist(generation=G)
      -> filecontent(file=X, generation=G)
      -> filecontent(file=Y, generation=G)
      -> ...

  The leader must retain commit G across these requests.

  While a filecontent request is active, the commit is protected with
  saveCommitPoint()/releaseCommitPoint(). Between requests, however, it is only
  protected by a timed reservation. The default commitReserveDuration is 10 
seconds.

  If the follower takes longer than that interval before requesting the next 
file,
  the reservation expires. A later hard commit on the leader invokes the index
  deletion policy and may delete G. The next filecontent request then calls
  saveCommitPoint(G), which throws IllegalStateException.

  This exception is currently exposed as HTTP 500.

  The same stale-generation condition is already handled explicitly by the
  filelist path. filelist catches IllegalStateException from
  getAndSaveCommitPoint(G) and reports:

    invalid index generation

  The filecontent path does not provide equivalent handling.

  In Solr 8.11.4, the relevant difference is approximately:

    ReplicationHandler.getFileList():

      try {
        commit = delPol.getAndSaveCommitPoint(gen);
      } catch (IllegalStateException ignored) {
        // handled as an invalid generation below
      }

    ReplicationHandler.DirectoryFileStream.initWrite():

      if (indexGen != null) {
        delPolicy.saveCommitPoint(indexGen);
      }

  The equivalent behavior is present in the newer replication implementation.

  Reproduction
  ============

  The issue does not require a large index. One committed document is 
sufficient.

  1. Create and hard-commit one document on the leader, producing generation G.
  2. Submit another update or delete without committing it.
  3. Start an explicit fetchindex request on the follower.
  4. Allow the follower to complete indexversion and filelist(G).
  5. Pause before the first filecontent(G) request.
  6. Wait until the reservation for G has expired.
  7. Hard-commit the pending leader update, producing a newer generation and
     allowing the deletion policy to delete G.
  8. Resume the follower so that it requests filecontent(G).

  The hard commit must occur after the reservation expires. Expiration alone 
does
  not delete the commit; the subsequent leader commit is what invokes the 
deletion
  policy.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to