[
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]