2024-09-05 09:40:03 -05:00
|
|
|
|
2022-08-08 19:01:24 -04:00
|
|
|
import signal
|
|
|
|
|
import time
|
2022-02-03 18:02:50 -08:00
|
|
|
|
2024-09-05 08:16:45 -05:00
|
|
|
import psycopg2
|
|
|
|
|
import utils
|
2022-08-08 19:01:24 -04:00
|
|
|
|
2024-09-05 08:16:45 -05:00
|
|
|
SHUTDOWN_TIMEOUT = 5
|
2022-08-08 19:01:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_shutdown_logic():
|
|
|
|
|
|
2022-08-25 06:40:56 -07:00
|
|
|
# - - - - - - - - - - - - - - - - - -
|
|
|
|
|
# NO ACTIVE QUERIES SIGINT HANDLING
|
|
|
|
|
|
2022-08-08 19:01:24 -04:00
|
|
|
# Start pgcat
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pgcat_start()
|
2022-08-08 19:01:24 -04:00
|
|
|
|
|
|
|
|
# Create client connection and send query (not in transaction)
|
2024-09-05 08:16:45 -05:00
|
|
|
conn, cur = utils.connect_db()
|
2022-08-08 19:01:24 -04:00
|
|
|
|
|
|
|
|
cur.execute("BEGIN;")
|
|
|
|
|
cur.execute("SELECT 1;")
|
|
|
|
|
cur.execute("COMMIT;")
|
|
|
|
|
|
|
|
|
|
# Send sigint to pgcat
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pg_cat_send_signal(signal.SIGINT)
|
2022-08-08 19:01:24 -04:00
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
# Check that any new queries fail after sigint since server should close with no active transactions
|
|
|
|
|
try:
|
|
|
|
|
cur.execute("SELECT 1;")
|
|
|
|
|
except psycopg2.OperationalError as e:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
# Fail if query execution succeeded
|
|
|
|
|
raise Exception("Server not closed after sigint")
|
2022-08-09 17:09:53 -04:00
|
|
|
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.cleanup_conn(conn, cur)
|
|
|
|
|
utils.pg_cat_send_signal(signal.SIGTERM)
|
2022-08-09 17:09:53 -04:00
|
|
|
|
2023-02-27 01:16:30 -05:00
|
|
|
# - - - - - - - - - - - - - - - - - -
|
|
|
|
|
# NO ACTIVE QUERIES ADMIN SHUTDOWN COMMAND
|
|
|
|
|
|
|
|
|
|
# Start pgcat
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pgcat_start()
|
2023-02-27 01:16:30 -05:00
|
|
|
|
|
|
|
|
# Create client connection and begin transaction
|
2024-09-05 08:16:45 -05:00
|
|
|
conn, cur = utils.connect_db()
|
|
|
|
|
admin_conn, admin_cur = utils.connect_db(admin=True)
|
2023-02-27 01:16:30 -05:00
|
|
|
|
|
|
|
|
cur.execute("BEGIN;")
|
|
|
|
|
cur.execute("SELECT 1;")
|
|
|
|
|
cur.execute("COMMIT;")
|
|
|
|
|
|
|
|
|
|
# Send SHUTDOWN command pgcat while not in transaction
|
|
|
|
|
admin_cur.execute("SHUTDOWN;")
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
# Check that any new queries fail after SHUTDOWN command since server should close with no active transactions
|
|
|
|
|
try:
|
|
|
|
|
cur.execute("SELECT 1;")
|
|
|
|
|
except psycopg2.OperationalError as e:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
# Fail if query execution succeeded
|
|
|
|
|
raise Exception("Server not closed after sigint")
|
|
|
|
|
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.cleanup_conn(conn, cur)
|
|
|
|
|
utils.cleanup_conn(admin_conn, admin_cur)
|
|
|
|
|
utils.pg_cat_send_signal(signal.SIGTERM)
|
2023-02-27 01:16:30 -05:00
|
|
|
|
2022-08-25 06:40:56 -07:00
|
|
|
# - - - - - - - - - - - - - - - - - -
|
|
|
|
|
# HANDLE TRANSACTION WITH SIGINT
|
2022-08-08 19:01:24 -04:00
|
|
|
|
|
|
|
|
# Start pgcat
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pgcat_start()
|
2022-08-08 19:01:24 -04:00
|
|
|
|
|
|
|
|
# Create client connection and begin transaction
|
2024-09-05 08:16:45 -05:00
|
|
|
conn, cur = utils.connect_db()
|
2022-08-08 19:01:24 -04:00
|
|
|
|
|
|
|
|
cur.execute("BEGIN;")
|
|
|
|
|
cur.execute("SELECT 1;")
|
|
|
|
|
|
|
|
|
|
# Send sigint to pgcat while still in transaction
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pg_cat_send_signal(signal.SIGINT)
|
2022-08-08 19:01:24 -04:00
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
# Check that any new queries succeed after sigint since server should still allow transaction to complete
|
|
|
|
|
try:
|
|
|
|
|
cur.execute("SELECT 1;")
|
|
|
|
|
except psycopg2.OperationalError as e:
|
|
|
|
|
# Fail if query fails since server closed
|
|
|
|
|
raise Exception("Server closed while in transaction", e.pgerror)
|
|
|
|
|
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.cleanup_conn(conn, cur)
|
|
|
|
|
utils.pg_cat_send_signal(signal.SIGTERM)
|
2022-08-09 17:09:53 -04:00
|
|
|
|
2023-02-27 01:16:30 -05:00
|
|
|
# - - - - - - - - - - - - - - - - - -
|
|
|
|
|
# HANDLE TRANSACTION WITH ADMIN SHUTDOWN COMMAND
|
|
|
|
|
|
|
|
|
|
# Start pgcat
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pgcat_start()
|
2023-02-27 01:16:30 -05:00
|
|
|
|
|
|
|
|
# Create client connection and begin transaction
|
2024-09-05 08:16:45 -05:00
|
|
|
conn, cur = utils.connect_db()
|
|
|
|
|
admin_conn, admin_cur = utils.connect_db(admin=True)
|
2023-02-27 01:16:30 -05:00
|
|
|
|
|
|
|
|
cur.execute("BEGIN;")
|
|
|
|
|
cur.execute("SELECT 1;")
|
|
|
|
|
|
|
|
|
|
# Send SHUTDOWN command pgcat while still in transaction
|
|
|
|
|
admin_cur.execute("SHUTDOWN;")
|
|
|
|
|
if admin_cur.fetchall()[0][0] != "t":
|
|
|
|
|
raise Exception("PgCat unable to send signal")
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
# Check that any new queries succeed after SHUTDOWN command since server should still allow transaction to complete
|
|
|
|
|
try:
|
|
|
|
|
cur.execute("SELECT 1;")
|
|
|
|
|
except psycopg2.OperationalError as e:
|
|
|
|
|
# Fail if query fails since server closed
|
|
|
|
|
raise Exception("Server closed while in transaction", e.pgerror)
|
|
|
|
|
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.cleanup_conn(conn, cur)
|
|
|
|
|
utils.cleanup_conn(admin_conn, admin_cur)
|
|
|
|
|
utils.pg_cat_send_signal(signal.SIGTERM)
|
2023-02-27 01:16:30 -05:00
|
|
|
|
2022-08-25 06:40:56 -07:00
|
|
|
# - - - - - - - - - - - - - - - - - -
|
|
|
|
|
# NO NEW NON-ADMIN CONNECTIONS DURING SHUTDOWN
|
|
|
|
|
# Start pgcat
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pgcat_start()
|
2022-08-25 06:40:56 -07:00
|
|
|
|
|
|
|
|
# Create client connection and begin transaction
|
2024-09-05 08:16:45 -05:00
|
|
|
transaction_conn, transaction_cur = utils.connect_db()
|
2022-08-25 06:40:56 -07:00
|
|
|
|
|
|
|
|
transaction_cur.execute("BEGIN;")
|
|
|
|
|
transaction_cur.execute("SELECT 1;")
|
|
|
|
|
|
|
|
|
|
# Send sigint to pgcat while still in transaction
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pg_cat_send_signal(signal.SIGINT)
|
2022-08-25 06:40:56 -07:00
|
|
|
time.sleep(1)
|
2022-08-08 19:01:24 -04:00
|
|
|
|
2022-08-25 06:40:56 -07:00
|
|
|
start = time.perf_counter()
|
|
|
|
|
try:
|
2024-09-05 08:16:45 -05:00
|
|
|
conn, cur = utils.connect_db()
|
2022-08-25 06:40:56 -07:00
|
|
|
cur.execute("SELECT 1;")
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.cleanup_conn(conn, cur)
|
2022-08-25 06:40:56 -07:00
|
|
|
except psycopg2.OperationalError as e:
|
|
|
|
|
time_taken = time.perf_counter() - start
|
|
|
|
|
if time_taken > 0.1:
|
|
|
|
|
raise Exception(
|
|
|
|
|
"Failed to reject connection within 0.1 seconds, got", time_taken, "seconds")
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
raise Exception("Able connect to database during shutdown")
|
|
|
|
|
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.cleanup_conn(transaction_conn, transaction_cur)
|
|
|
|
|
utils.pg_cat_send_signal(signal.SIGTERM)
|
2022-08-25 06:40:56 -07:00
|
|
|
|
|
|
|
|
# - - - - - - - - - - - - - - - - - -
|
|
|
|
|
# ALLOW NEW ADMIN CONNECTIONS DURING SHUTDOWN
|
2022-08-08 19:01:24 -04:00
|
|
|
# Start pgcat
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pgcat_start()
|
2022-08-08 19:01:24 -04:00
|
|
|
|
2022-08-25 06:40:56 -07:00
|
|
|
# Create client connection and begin transaction
|
2024-09-05 08:16:45 -05:00
|
|
|
transaction_conn, transaction_cur = utils.connect_db()
|
2022-08-25 06:40:56 -07:00
|
|
|
|
|
|
|
|
transaction_cur.execute("BEGIN;")
|
|
|
|
|
transaction_cur.execute("SELECT 1;")
|
|
|
|
|
|
|
|
|
|
# Send sigint to pgcat while still in transaction
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pg_cat_send_signal(signal.SIGINT)
|
2022-08-25 06:40:56 -07:00
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
try:
|
2024-09-05 08:16:45 -05:00
|
|
|
conn, cur = utils.connect_db(admin=True)
|
2022-08-25 06:40:56 -07:00
|
|
|
cur.execute("SHOW DATABASES;")
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.cleanup_conn(conn, cur)
|
2022-08-25 06:40:56 -07:00
|
|
|
except psycopg2.OperationalError as e:
|
|
|
|
|
raise Exception(e)
|
|
|
|
|
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.cleanup_conn(transaction_conn, transaction_cur)
|
|
|
|
|
utils.pg_cat_send_signal(signal.SIGTERM)
|
2022-08-25 06:40:56 -07:00
|
|
|
|
|
|
|
|
# - - - - - - - - - - - - - - - - - -
|
|
|
|
|
# ADMIN CONNECTIONS CONTINUING TO WORK AFTER SHUTDOWN
|
|
|
|
|
# Start pgcat
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pgcat_start()
|
2022-08-25 06:40:56 -07:00
|
|
|
|
|
|
|
|
# Create client connection and begin transaction
|
2024-09-05 08:16:45 -05:00
|
|
|
transaction_conn, transaction_cur = utils.connect_db()
|
2022-08-25 06:40:56 -07:00
|
|
|
transaction_cur.execute("BEGIN;")
|
|
|
|
|
transaction_cur.execute("SELECT 1;")
|
|
|
|
|
|
2024-09-05 08:16:45 -05:00
|
|
|
admin_conn, admin_cur = utils.connect_db(admin=True)
|
2022-08-25 06:40:56 -07:00
|
|
|
admin_cur.execute("SHOW DATABASES;")
|
|
|
|
|
|
|
|
|
|
# Send sigint to pgcat while still in transaction
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pg_cat_send_signal(signal.SIGINT)
|
2022-08-25 06:40:56 -07:00
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
admin_cur.execute("SHOW DATABASES;")
|
|
|
|
|
except psycopg2.OperationalError as e:
|
|
|
|
|
raise Exception("Could not execute admin command:", e)
|
|
|
|
|
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.cleanup_conn(transaction_conn, transaction_cur)
|
|
|
|
|
utils.cleanup_conn(admin_conn, admin_cur)
|
|
|
|
|
utils.pg_cat_send_signal(signal.SIGTERM)
|
2022-08-25 06:40:56 -07:00
|
|
|
|
|
|
|
|
# - - - - - - - - - - - - - - - - - -
|
|
|
|
|
# HANDLE SHUTDOWN TIMEOUT WITH SIGINT
|
|
|
|
|
|
|
|
|
|
# Start pgcat
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pgcat_start()
|
2022-08-08 19:01:24 -04:00
|
|
|
|
|
|
|
|
# Create client connection and begin transaction, which should prevent server shutdown unless shutdown timeout is reached
|
2024-09-05 08:16:45 -05:00
|
|
|
conn, cur = utils.connect_db()
|
2022-08-08 19:01:24 -04:00
|
|
|
|
|
|
|
|
cur.execute("BEGIN;")
|
|
|
|
|
cur.execute("SELECT 1;")
|
|
|
|
|
|
|
|
|
|
# Send sigint to pgcat while still in transaction
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.pg_cat_send_signal(signal.SIGINT)
|
2022-08-08 19:01:24 -04:00
|
|
|
|
|
|
|
|
# pgcat shutdown timeout is set to SHUTDOWN_TIMEOUT seconds, so we sleep for SHUTDOWN_TIMEOUT + 1 seconds
|
|
|
|
|
time.sleep(SHUTDOWN_TIMEOUT + 1)
|
|
|
|
|
|
|
|
|
|
# Check that any new queries succeed after sigint since server should still allow transaction to complete
|
|
|
|
|
try:
|
|
|
|
|
cur.execute("SELECT 1;")
|
|
|
|
|
except psycopg2.OperationalError as e:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
# Fail if query execution succeeded
|
|
|
|
|
raise Exception("Server not closed after sigint and expected timeout")
|
|
|
|
|
|
2024-09-05 08:16:45 -05:00
|
|
|
utils.cleanup_conn(conn, cur)
|
|
|
|
|
utils.pg_cat_send_signal(signal.SIGTERM)
|
2024-09-05 09:40:03 -05:00
|
|
|
|
|
|
|
|
# - - - - - - - - - - - - - - - - - -
|