@@ -106,10 +106,12 @@ def setUp(self):
106106 self .maxDiff = None
107107 self .mock_logger = Mock (spec = ['log' , 'info' , 'debug' , 'error' , 'warn' , 'exception' ])
108108 self .apply_patches ([
109+ patch ('gpsegrecovery.ensure_replication_slot_exists' ),
109110 patch ('gpsegrecovery.start_segment' , return_value = Mock ()),
110111 patch ('gpsegrecovery.PgBaseBackup.__init__' , return_value = None ),
111112 patch ('gpsegrecovery.PgBaseBackup.run' )
112113 ])
114+ self .mock_ensure_slot = self .get_mock_from_apply_patch ('ensure_replication_slot_exists' )
113115 self .mock_pgbasebackup_run = self .get_mock_from_apply_patch ('run' )
114116 self .mock_pgbasebackup_init = self .get_mock_from_apply_patch ('__init__' )
115117
@@ -130,6 +132,7 @@ def tearDown(self):
130132 super (FullRecoveryTestCase , self ).tearDown ()
131133
132134 def _assert_basebackup_runs (self , expected_init_args ):
135+ self .mock_ensure_slot .assert_called_once_with ('sdw1' , 40000 , 'internal_wal_replication_slot' )
133136 self .assertEqual (1 , self .mock_pgbasebackup_init .call_count )
134137 self .assertEqual (expected_init_args , self .mock_pgbasebackup_init .call_args )
135138 self .assertEqual (1 , self .mock_pgbasebackup_run .call_count )
@@ -172,66 +175,51 @@ def test_basebackup_run_no_forceoverwrite_passes(self):
172175 self ._assert_basebackup_runs (expected_init_args1 )
173176 self ._assert_cmd_passed ()
174177
175- def test_basebackup_run_one_exception (self ):
176- self .mock_pgbasebackup_run .side_effect = [Exception ('backup failed once' ), Mock ( )]
178+ def test_basebackup_slot_check_exception (self ):
179+ self .mock_ensure_slot .side_effect = [Exception ('slot check failed' )]
177180
178181 self .full_recovery_cmd .run ()
179182
180- expected_init_args1 = call ("/data/mirror0" , "sdw1" , '40000' , create_slot = False ,
181- replication_slot_name = 'internal_wal_replication_slot' ,
182- forceoverwrite = True , target_gp_dbid = 2 , progress_file = '/tmp/test_progress_file' )
183- expected_init_args2 = call ("/data/mirror0" , "sdw1" , '40000' , create_slot = True ,
184- replication_slot_name = 'internal_wal_replication_slot' ,
185- forceoverwrite = True , target_gp_dbid = 2 , progress_file = '/tmp/test_progress_file' )
186- self .assertEqual (2 , self .mock_pgbasebackup_init .call_count )
187- self .assertEqual ([expected_init_args1 , expected_init_args2 ] , self .mock_pgbasebackup_init .call_args_list )
188- self .assertEqual (2 , self .mock_pgbasebackup_run .call_count )
189- self .assertEqual ([call (validateAfter = True ),call (validateAfter = True )], self .mock_pgbasebackup_run .call_args_list )
190- gpsegrecovery .start_segment .assert_called_once_with (self .seg_recovery_info , self .mock_logger , self .era )
191- self ._assert_cmd_passed ()
183+ self .assertEqual (0 , self .mock_pgbasebackup_init .call_count )
184+ self .assertEqual (0 , self .mock_pgbasebackup_run .call_count )
185+ self .assertEqual (0 , gpsegrecovery .start_segment .call_count )
186+ self ._assert_cmd_failed ('{"error_type": "full", "error_msg": "slot check failed", "dbid": 2, '
187+ '"datadir": "/data/mirror0", "port": 50000, '
188+ '"progress_file": "/tmp/test_progress_file"}' )
192189
193- def test_basebackup_run_two_exceptions (self ):
194- self .mock_pgbasebackup_run .side_effect = [Exception ('backup failed once' ),
195- Exception ('backup failed twice' )]
190+ def test_basebackup_run_exception (self ):
191+ self .mock_pgbasebackup_run .side_effect = [Exception ('backup failed once' )]
196192
197193 self .full_recovery_cmd .run ()
198194
199195 expected_init_args1 = call ("/data/mirror0" , "sdw1" , '40000' , create_slot = False ,
200196 replication_slot_name = 'internal_wal_replication_slot' ,
201197 forceoverwrite = True , target_gp_dbid = 2 , progress_file = '/tmp/test_progress_file' )
202- expected_init_args2 = call ("/data/mirror0" , "sdw1" , '40000' , create_slot = True ,
203- replication_slot_name = 'internal_wal_replication_slot' ,
204- forceoverwrite = True , target_gp_dbid = 2 , progress_file = '/tmp/test_progress_file' )
205- self .assertEqual (2 , self .mock_pgbasebackup_init .call_count )
206- self .assertEqual ([expected_init_args1 , expected_init_args2 ], self .mock_pgbasebackup_init .call_args_list )
207- self .assertEqual (2 , self .mock_pgbasebackup_run .call_count )
208- self .assertEqual ([call (validateAfter = True ),call (validateAfter = True )], self .mock_pgbasebackup_run .call_args_list )
209- self .mock_logger .info .any_call ('Running pg_basebackup failed: backup failed once' )
210- self .mock_logger .info .assert_called_with ("Re-running pg_basebackup, creating the slot this time" )
198+ self .mock_ensure_slot .assert_called_once_with ('sdw1' , 40000 , 'internal_wal_replication_slot' )
199+ self .assertEqual (1 , self .mock_pgbasebackup_init .call_count )
200+ self .assertEqual ([expected_init_args1 ], self .mock_pgbasebackup_init .call_args_list )
201+ self .assertEqual (1 , self .mock_pgbasebackup_run .call_count )
202+ self .assertEqual ([call (validateAfter = True )], self .mock_pgbasebackup_run .call_args_list )
211203 self .assertEqual (0 , gpsegrecovery .start_segment .call_count )
212- self ._assert_cmd_failed ('{"error_type": "full", "error_msg": "backup failed twice ", "dbid": 2, ' \
204+ self ._assert_cmd_failed ('{"error_type": "full", "error_msg": "backup failed once ", "dbid": 2, ' \
213205 '"datadir": "/data/mirror0", "port": 50000, "progress_file": "/tmp/test_progress_file"}' )
214206
215- def test_basebackup_run_no_forceoverwrite_two_exceptions (self ):
216- self .mock_pgbasebackup_run .side_effect = [Exception ('backup failed once' ),
217- Exception ('backup failed twice' )]
207+ def test_basebackup_run_no_forceoverwrite_exception (self ):
208+ self .mock_pgbasebackup_run .side_effect = [Exception ('backup failed once' )]
218209 self .full_recovery_cmd .forceoverwrite = False
219210
220211 self .full_recovery_cmd .run ()
221212
222213 expected_init_args1 = call ("/data/mirror0" , "sdw1" , '40000' , create_slot = False ,
223214 replication_slot_name = 'internal_wal_replication_slot' ,
224215 forceoverwrite = False , target_gp_dbid = 2 , progress_file = '/tmp/test_progress_file' )
225- # regardless of the passed in value, second call to pg_basebackup will always have forceoverwrite=True
226- expected_init_args2 = call ("/data/mirror0" , "sdw1" , '40000' , create_slot = True ,
227- replication_slot_name = 'internal_wal_replication_slot' ,
228- forceoverwrite = True , target_gp_dbid = 2 , progress_file = '/tmp/test_progress_file' )
229- self .assertEqual (2 , self .mock_pgbasebackup_init .call_count )
230- self .assertEqual ([expected_init_args1 , expected_init_args2 ], self .mock_pgbasebackup_init .call_args_list )
231- self .assertEqual (2 , self .mock_pgbasebackup_run .call_count )
232- self .assertEqual ([call (validateAfter = True ),call (validateAfter = True )], self .mock_pgbasebackup_run .call_args_list )
216+ self .mock_ensure_slot .assert_called_once_with ('sdw1' , 40000 , 'internal_wal_replication_slot' )
217+ self .assertEqual (1 , self .mock_pgbasebackup_init .call_count )
218+ self .assertEqual ([expected_init_args1 ], self .mock_pgbasebackup_init .call_args_list )
219+ self .assertEqual (1 , self .mock_pgbasebackup_run .call_count )
220+ self .assertEqual ([call (validateAfter = True )], self .mock_pgbasebackup_run .call_args_list )
233221 self .assertEqual (0 , gpsegrecovery .start_segment .call_count )
234- self ._assert_cmd_failed ('{"error_type": "full", "error_msg": "backup failed twice ", "dbid": 2, ' \
222+ self ._assert_cmd_failed ('{"error_type": "full", "error_msg": "backup failed once ", "dbid": 2, ' \
235223 '"datadir": "/data/mirror0", "port": 50000, "progress_file": "/tmp/test_progress_file"}' )
236224
237225 def test_basebackup_init_exception (self ):
@@ -287,7 +275,10 @@ def tearDown(self):
287275 @patch ('gppylib.commands.pg.PgRewind.run' )
288276 @patch ('gpsegrecovery.PgBaseBackup.__init__' , return_value = None )
289277 @patch ('gpsegrecovery.PgBaseBackup.run' )
290- def test_complete_workflow (self , mock_pgbasebackup_run , mock_pgbasebackup_init , mock_pgrewind_run , mock_pgrewind_init ):
278+ @patch ('gpsegrecovery.ensure_replication_slot_exists' )
279+ def test_complete_workflow (self , mock_ensure_slot , mock_pgbasebackup_run ,
280+ mock_pgbasebackup_init , mock_pgrewind_run ,
281+ mock_pgrewind_init ):
291282 mix_confinfo = gppylib .recoveryinfo .serialize_list ([
292283 self .full_r1 , self .incr_r2 ])
293284 sys .argv = ['gpsegrecovery' , '-l' , '/tmp/logdir' , '--era' , '{}' .format (self .era ), '-c {}' .format (mix_confinfo )]
@@ -301,17 +292,21 @@ def test_complete_workflow(self, mock_pgbasebackup_run, mock_pgbasebackup_init,
301292 self .assertEqual (1 , mock_pgrewind_init .call_count )
302293 self .assertEqual (1 , mock_pgbasebackup_run .call_count )
303294 self .assertEqual (1 , mock_pgbasebackup_init .call_count )
295+ mock_ensure_slot .assert_called_once_with ('source_hostname1' , 6001 , 'internal_wal_replication_slot' )
304296 self .assertRegex (gplog .get_logfile (), '/gpsegrecovery.py_\d+\.log' )
305297
306298 @patch ('gppylib.commands.pg.PgRewind.__init__' , return_value = None )
307299 @patch ('gppylib.commands.pg.PgRewind.run' )
308300 @patch ('gpsegrecovery.PgBaseBackup.__init__' , return_value = None )
309301 @patch ('gpsegrecovery.PgBaseBackup.run' )
310- def test_complete_workflow_exception (self , mock_pgbasebackup_run , mock_pgbasebackup_init , mock_pgrewind_run ,
302+ @patch ('gpsegrecovery.ensure_replication_slot_exists' )
303+ def test_complete_workflow_exception (self , mock_ensure_slot ,
304+ mock_pgbasebackup_run ,
305+ mock_pgbasebackup_init ,
306+ mock_pgrewind_run ,
311307 mock_pgrewind_init ):
312308 mock_pgrewind_run .side_effect = [Exception ('pg_rewind failed' )]
313- mock_pgbasebackup_run .side_effect = [Exception ('pg_basebackup failed once' ),
314- Exception ('pg_basebackup failed twice' )]
309+ mock_pgbasebackup_run .side_effect = [Exception ('pg_basebackup failed once' )]
315310 mix_confinfo = gppylib .recoveryinfo .serialize_list ([
316311 self .full_r1 , self .incr_r2 ])
317312 sys .argv = ['gpsegrecovery' , '-l' , '/tmp/logdir' , '--era={}' .format (self .era ), '-c {}' .format (mix_confinfo )]
@@ -322,14 +317,15 @@ def test_complete_workflow_exception(self, mock_pgbasebackup_run, mock_pgbasebac
322317
323318 self .assertCountEqual ('[{"error_type": "incremental", "error_msg": "pg_rewind failed", "dbid": 4, "datadir": "target_data_dir4", '
324319 '"port": 5004, "progress_file": "/tmp/progress_file4"} , '
325- '{"error_type": "full", "error_msg": "pg_basebackup failed twice ", "dbid": 1,'
320+ '{"error_type": "full", "error_msg": "pg_basebackup failed once ", "dbid": 1,'
326321 '"datadir": "target_data_dir1", "port": 5001, "progress_file": "/tmp/progress_file1"}]' ,
327322 buf .getvalue ().strip ())
328323 self .assertEqual (1 , ex .exception .code )
329324 self .assertEqual (1 , mock_pgrewind_run .call_count )
330325 self .assertEqual (1 , mock_pgrewind_init .call_count )
331- self .assertEqual (2 , mock_pgbasebackup_run .call_count )
332- self .assertEqual (2 , mock_pgbasebackup_init .call_count )
326+ self .assertEqual (1 , mock_pgbasebackup_run .call_count )
327+ self .assertEqual (1 , mock_pgbasebackup_init .call_count )
328+ mock_ensure_slot .assert_called_once_with ('source_hostname1' , 6001 , 'internal_wal_replication_slot' )
333329 self .assertRegex (gplog .get_logfile (), '/gpsegrecovery.py_\d+\.log' )
334330
335331 @patch ('recovery_base.gplog.setup_tool_logging' )
0 commit comments