From a1183d6e0116bac4ad6419b892a5736a5355dac6 Mon Sep 17 00:00:00 2001
From: Vladimir Davydov <vdavydov@tarantool.org>
Date: Wed, 18 May 2022 14:38:58 +0300
Subject: [PATCH] applier: make SSLError retryable

A certificate used for an encrypted replication connection may expire,
in which case the user will be forced to reconfigure the connection both
on the master and on the replica to use the new certificate. If the
replica completes the reconfiguration first, it will fail to connect to
the master and never retry, even though the master should complete its
reconfiguration in a moment.

To avoid that, we should make the applier retry to connect on SSLError,
just like it does on SocketError.

Needed for https://github.com/tarantool/tarantool-ee/issues/107

NO_DOC=ee
NO_TEST=ee
NO_CHANGELOG=ee
---
 src/box/applier.cc | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/box/applier.cc b/src/box/applier.cc
index a8b2f61ef0..f30d9f2f77 100644
--- a/src/box/applier.cc
+++ b/src/box/applier.cc
@@ -60,6 +60,7 @@
 #include "small/static.h"
 #include "tt_static.h"
 #include "memory.h"
+#include "ssl_error.h"
 
 STRS(applier_state, applier_STATE);
 
@@ -119,6 +120,7 @@ applier_log_error(struct applier *applier, struct error *e)
 	case ER_ACCESS_DENIED:
 	case ER_NO_SUCH_USER:
 	case ER_SYSTEM:
+	case ER_SSL:
 	case ER_UNKNOWN_REPLICA:
 	case ER_PASSWORD_MISMATCH:
 	case ER_XLOG_GAP:
@@ -2186,7 +2188,8 @@ applier_f(va_list ap)
 				applier_log_error(applier, e);
 				applier_disconnect(applier, APPLIER_LOADING);
 				goto reconnect;
-			} else if (e->errcode() == ER_SYSTEM) {
+			} else if (e->errcode() == ER_SYSTEM ||
+				   e->errcode() == ER_SSL) {
 				/* System error from master instance. */
 				applier_log_error(applier, e);
 				applier_disconnect(applier, APPLIER_DISCONNECTED);
@@ -2239,6 +2242,10 @@ applier_f(va_list ap)
 			applier_log_error(applier, e);
 			applier_disconnect(applier, APPLIER_DISCONNECTED);
 			goto reconnect;
+		} catch (SSLError *e) {
+			applier_log_error(applier, e);
+			applier_disconnect(applier, APPLIER_DISCONNECTED);
+			goto reconnect;
 		} catch (Exception *e) {
 			applier_log_error(applier, e);
 			applier_disconnect(applier, APPLIER_STOPPED);
-- 
GitLab