Skip to content

Commit 4604c09

Browse files
committed
test(io): add test_so_reuseport_zero_downtime_handover
1 parent 2fb5020 commit 4604c09

2 files changed

Lines changed: 57 additions & 1 deletion

File tree

test/io/postgrest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ def run(
8585
stdin=None,
8686
env=None,
8787
port=None,
88+
admin_port=None,
8889
host=None,
8990
wait_for_readiness=True,
9091
wait_max_seconds=1,
@@ -113,7 +114,7 @@ def run(
113114
env["PGRST_SERVER_UNIX_SOCKET"] = str(socketfile)
114115
baseurl = "http+unix://" + urllib.parse.quote_plus(str(socketfile))
115116

116-
adminport = freeport(used_ports=[port])
117+
adminport = freeport(used_ports=[port]) if admin_port is None else admin_port
117118
env["PGRST_ADMIN_SERVER_PORT"] = str(adminport)
118119
adminhost = f"[{host}]" if host and is_ipv6(host) else localhost
119120
adminurl = f"http://{adminhost}:{adminport}"

test/io/test_io.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,61 @@ def test_random_port_bound(defaultenv):
133133
assert True # liveness check is done by run(), so we just need to check that it doesn't fail
134134

135135

136+
@pytest.mark.xfail(reason="SO_REUSEPORT handover is currently failing")
137+
def test_so_reuseport_zero_downtime_handover(defaultenv):
138+
"A second PostgREST instance should take over on the same main/admin ports without request failures."
139+
140+
port = freeport()
141+
admin_port = freeport(used_ports=[port])
142+
failures = []
143+
keep_running = {"value": True}
144+
145+
with run(
146+
env={**defaultenv},
147+
port=port,
148+
admin_port=admin_port,
149+
wait_max_seconds=3,
150+
) as first:
151+
152+
def continuously_request():
153+
while keep_running["value"]:
154+
try:
155+
response = first.session.get("/projects", timeout=1)
156+
assert response.status_code == 200
157+
except Exception as exc:
158+
failures.append(exc)
159+
break
160+
time.sleep(0.05)
161+
162+
requester = Thread(target=continuously_request)
163+
requester.start()
164+
165+
try:
166+
time.sleep(1)
167+
with run(
168+
env={**defaultenv},
169+
port=port,
170+
admin_port=admin_port,
171+
wait_max_seconds=3,
172+
):
173+
response = first.admin.get("/live")
174+
assert response.status_code == 200
175+
176+
time.sleep(1)
177+
first.process.terminate()
178+
wait_until_exit(first)
179+
180+
response = first.admin.get("/live")
181+
assert response.status_code == 200
182+
183+
time.sleep(1)
184+
finally:
185+
keep_running["value"] = False
186+
requester.join()
187+
188+
assert failures == []
189+
190+
136191
def test_app_settings_reload(tmp_path, defaultenv):
137192
"App settings should be reloaded from file when PostgREST is sent SIGUSR2."
138193
config = (CONFIGSDIR / "sigusr2-settings.config").read_text()

0 commit comments

Comments
 (0)