Merge branch 'stable-3.1'

* stable-3.1:
  Prevent persistent task listing interruptions on IOExceptions

Change-Id: Iaa7a6e354b629fac9afdb8bf18074a4662b61541
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorage.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorage.java
index b805c72..49cb059 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorage.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorage.java
@@ -28,6 +28,7 @@
 import java.nio.file.DirectoryStream;
 import java.nio.file.FileAlreadyExistsException;
 import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
 import java.util.ArrayList;
@@ -222,13 +223,21 @@
   private List<ReplicateRefUpdate> list(Path tasks) {
     List<ReplicateRefUpdate> results = new ArrayList<>();
     try (DirectoryStream<Path> events = Files.newDirectoryStream(tasks)) {
-      for (Path e : events) {
-        if (Files.isRegularFile(e)) {
-          String json = new String(Files.readAllBytes(e), UTF_8);
-          results.add(GSON.fromJson(json, ReplicateRefUpdate.class));
-        } else if (Files.isDirectory(e)) {
+      for (Path path : events) {
+        if (Files.isRegularFile(path)) {
           try {
-            results.addAll(list(e));
+            String json = new String(Files.readAllBytes(path), UTF_8);
+            results.add(GSON.fromJson(json, ReplicateRefUpdate.class));
+          } catch (NoSuchFileException ex) {
+            logger.atFine().log(
+                "File %s not found while listing waiting tasks (likely in-flight or completed by another node)",
+                path);
+          } catch (IOException e) {
+            logger.atSevere().withCause(e).log("Error when firing pending event %s", path);
+          }
+        } else if (Files.isDirectory(path)) {
+          try {
+            results.addAll(list(path));
           } catch (DirectoryIteratorException d) {
             // iterating over the sub-directories is expected to have dirs disappear
             Nfs.throwIfNotStaleFileHandle(d.getCause());