[ 
https://issues.apache.org/jira/browse/SOLR-18406?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

ZhenyuLi updated SOLR-18406:
----------------------------
    Description: 
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.

A simplified graph to illustrate:

  Follower fetch thread                 Test/leader thread

  indexversion -> G
  filelist(G)
                   \
                    reservation for G expires
                                        pending update
                                        hard commit -> G+1
                                        deletion policy deletes G
  filecontent(G)
    -> saveCommitPoint(G)
    -> IllegalStateException
    -> HTTP 500

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

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.

  was:
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.

A simplified graph to illustrate:

  Follower fetch thread                 Test/leader thread

  indexversion -> G
  filelist(G)
                   \
                    reservation for G expires
                                        pending update
                                        hard commit -> G+1
                                        deletion policy deletes G
  filecontent(G)
    -> saveCommitPoint(G)
    -> IllegalStateException
    -> HTTP 500

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.


> 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: 8.11.4, 9.10.1
>            Reporter: ZhenyuLi
>            Priority: Major
>              Labels: pull-request-available
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> 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.
> A simplified graph to illustrate:
>   Follower fetch thread                 Test/leader thread
>   indexversion -> G
>   filelist(G)
>                    \
>                     reservation for G expires
>                                         pending update
>                                         hard commit -> G+1
>                                         deletion policy deletes G
>   filecontent(G)
>     -> saveCommitPoint(G)
>     -> IllegalStateException
>     -> HTTP 500
> Reproduction
> ============
> 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