@@ -240,6 +240,13 @@ public void downloadSnapshot(long snapshotId) throws Exception {
240240 }
241241 CompletedSnapshot completedSnapshot =
242242 snapshotContext .getCompletedSnapshotProvider (tableBucket , snapshotId );
243+ if (completedSnapshot == null ) {
244+ LOG .warn (
245+ "Snapshot {} not found for bucket {}, skip downloading." ,
246+ snapshotId ,
247+ tableBucket );
248+ return ;
249+ }
243250 incrementalDownloadSnapshot (completedSnapshot );
244251 standbySnapshotSize = completedSnapshot .getSnapshotSize ();
245252 }
@@ -253,23 +260,26 @@ public void downloadSnapshot(long snapshotId) throws Exception {
253260 * @return the latest snapshot
254261 */
255262 public Optional <CompletedSnapshot > downloadLatestSnapshot () throws Exception {
256- // standbyInitializing is used to prevent concurrent download.
263+ // standbyInitializing is used to prevent concurrent download via
264+ // downloadSnapshot(snapshotId).
257265 standbyInitializing = true ;
266+ try {
267+ // Note: no isStandby check here. This method is called from both:
268+ // 1. initKvTablet() during leader initialization - isStandby is already false
269+ // 2. becomeStandbyAsync() during standby initialization - isStandby is true
270+ // The isStandby guard is only needed in downloadSnapshot(snapshotId) which is
271+ // called from the notification path exclusively for standby replicas.
272+ Optional <CompletedSnapshot > latestSnapshot = getLatestSnapshot ();
273+ if (latestSnapshot .isPresent ()) {
274+ CompletedSnapshot completedSnapshot = latestSnapshot .get ();
275+ incrementalDownloadSnapshot (completedSnapshot );
276+ standbySnapshotSize = completedSnapshot .getSnapshotSize ();
277+ }
258278
259- // Note: no isStandby check here. This method is called from both:
260- // 1. initKvTablet() during leader initialization - isStandby is already false
261- // 2. becomeStandbyAsync() during standby initialization - isStandby is true
262- // The isStandby guard is only needed in downloadSnapshot(snapshotId) which is
263- // called from the notification path exclusively for standby replicas.
264- Optional <CompletedSnapshot > latestSnapshot = getLatestSnapshot ();
265- if (latestSnapshot .isPresent ()) {
266- CompletedSnapshot completedSnapshot = latestSnapshot .get ();
267- incrementalDownloadSnapshot (completedSnapshot );
268- standbySnapshotSize = completedSnapshot .getSnapshotSize ();
279+ return latestSnapshot ;
280+ } finally {
281+ standbyInitializing = false ;
269282 }
270-
271- standbyInitializing = false ;
272- return latestSnapshot ;
273283 }
274284
275285 private void incrementalDownloadSnapshot (CompletedSnapshot completedSnapshot ) throws Exception {
0 commit comments