From eb963c36c674561195a72dc44ba92d99b22c4bbd Mon Sep 17 00:00:00 2001
From: Rudolf Meijering <skaapgif@gmail.com>
Date: Fri, 28 Feb 2020 16:34:25 +0100
Subject: [PATCH] Retry migration operations which fail due to snapshot in
 progress

---
 .../server/elasticsearch/retry_call_cluster.test.ts | 13 +++++++++++++
 src/core/server/elasticsearch/retry_call_cluster.ts | 13 +++----------
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/src/core/server/elasticsearch/retry_call_cluster.test.ts b/src/core/server/elasticsearch/retry_call_cluster.test.ts
index b5a5185ab39d9..4f391f0aba34b 100644
--- a/src/core/server/elasticsearch/retry_call_cluster.test.ts
+++ b/src/core/server/elasticsearch/retry_call_cluster.test.ts
@@ -89,6 +89,19 @@ describe('migrationsRetryCallCluster', () => {
     });
   });
 
+  it('retries ES API calls that rejects with snapshot_in_progress_exception', () => {
+    expect.assertions(1);
+    const callEsApi = jest.fn();
+    let i = 0;
+    callEsApi.mockImplementation(() => {
+      return i++ <= 2
+        ? Promise.reject({ body: { error: { type: 'snapshot_in_progress_exception' } } })
+        : Promise.resolve('success');
+    });
+    const retried = migrationsRetryCallCluster(callEsApi, mockLogger.get('mock log'), 1);
+    return expect(retried('endpoint')).resolves.toMatchInlineSnapshot(`"success"`);
+  });
+
   it('rejects when ES API calls reject with other errors', async () => {
     expect.assertions(3);
     const callEsApi = jest.fn();
diff --git a/src/core/server/elasticsearch/retry_call_cluster.ts b/src/core/server/elasticsearch/retry_call_cluster.ts
index ea3cc0b90c077..901b801159cb6 100644
--- a/src/core/server/elasticsearch/retry_call_cluster.ts
+++ b/src/core/server/elasticsearch/retry_call_cluster.ts
@@ -64,7 +64,8 @@ export function migrationsRetryCallCluster(
                     error instanceof esErrors.AuthenticationException ||
                     error instanceof esErrors.AuthorizationException ||
                     // @ts-ignore
-                    error instanceof esErrors.Gone
+                    error instanceof esErrors.Gone ||
+                    error?.body?.error?.type === 'snapshot_in_progress_exception'
                   );
                 },
                 timer(delay),
@@ -85,15 +86,7 @@ export function migrationsRetryCallCluster(
  *
  * @param apiCaller
  */
-
-// TODO: Replace with APICaller from './scoped_cluster_client' once #46668 is merged
-export function retryCallCluster(
-  apiCaller: (
-    endpoint: string,
-    clientParams: Record<string, any>,
-    options?: CallAPIOptions
-  ) => Promise<any>
-) {
+export function retryCallCluster(apiCaller: APICaller) {
   return (endpoint: string, clientParams: Record<string, any> = {}, options?: CallAPIOptions) => {
     return defer(() => apiCaller(endpoint, clientParams, options))
       .pipe(