@@ -37,10 +37,12 @@ def log_step(step_number, description, status):
3737
3838# Function to execute SQL commands on a specific DSN
3939def execute_sql (sql , conn_info ):
40- conn_command = f"psql '{ conn_info } ' -c \" { sql } \" "
40+ # Quote the heredoc delimiter to prevent shell expansion
41+ conn_command = f"psql '{ conn_info } ' -v ON_ERROR_STOP=1 <<'EOF'\n { sql } \n EOF"
4142 result = subprocess .run (conn_command , shell = True , capture_output = True , text = True )
4243 return result .returncode , result .stdout , result .stderr
4344
45+
4446# Function to generate SQL for `node_create`
4547def node_create (node_name , dsn , location , country ):
4648 sql = f"""
@@ -158,6 +160,38 @@ def add_node_workflow(verbose):
158160 "sql" : rf"CALL spock.wait_for_sync_event(true, '{ NODE1_NAME } ', $10::pg_lsn, { SYNC_EVENT_TIMEOUT } );" ,
159161 "conn_info" : NODE3_DSN ,
160162 "ignore_error" : True
163+ },
164+ {
165+ "description" : "Check the replication lags between nodes" ,
166+ "sql" : """
167+ DO $$
168+ DECLARE
169+ lag_n1_n3 interval;
170+ lag_n2_n3 interval;
171+ BEGIN
172+ LOOP
173+ SELECT now() - commit_timestamp INTO lag_n1_n3
174+ FROM spock.lag_tracker
175+ WHERE origin_name = 'n1' AND receiver_name = 'n3';
176+
177+ SELECT now() - commit_timestamp INTO lag_n2_n3
178+ FROM spock.lag_tracker
179+ WHERE origin_name = 'n2' AND receiver_name = 'n3';
180+
181+ RAISE NOTICE 'n1 → n3 lag: %, n2 → n3 lag: %',
182+ COALESCE(lag_n1_n3::text, 'NULL'),
183+ COALESCE(lag_n2_n3::text, 'NULL');
184+
185+ EXIT WHEN lag_n1_n3 IS NOT NULL AND lag_n2_n3 IS NOT NULL
186+ AND extract(epoch FROM lag_n1_n3) < 59
187+ AND extract(epoch FROM lag_n2_n3) < 59;
188+
189+ PERFORM pg_sleep(1);
190+ END LOOP;
191+ END
192+ $$;
193+ """ .strip (),
194+ "conn_info" : NODE3_DSN
161195 }
162196 ]
163197
0 commit comments