Skip to content

Commit 8347504

Browse files
authored
fix: report worker activity to pg_stat_activity (#255)
* fix: report worker activity to pg_stat_activity Background workers must call pgstat_report_activity() themselves to update state/state_change in pg_stat_activity; regular user backends get this for free via tcop/postgres.c. Without it the pg_net worker shows up with a blank state column, making it impossible to tell from monitoring whether the worker is idle, processing a tick, or stuck in a transaction. Adds STATE_IDLE / STATE_RUNNING transitions around the inner work loop. cmd_str is NULL, matching what other background workers (e.g. logical replication apply worker) do; backend_type already identifies it as "pg_net <ver> worker" so a query-column label would be redundant. * test: verify worker state is reported in pg_stat_activity
1 parent 3736d0f commit 8347504

2 files changed

Lines changed: 59 additions & 0 deletions

File tree

src/worker.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ void pg_net_worker(__attribute__((unused)) Datum main_arg) {
265265

266266
publish_state(WS_RUNNING);
267267

268+
// Initial state: we go straight into the outer loop and wait for a wake.
269+
pgstat_report_activity(STATE_IDLE, NULL);
270+
268271
do {
269272

270273
uint32 expected = 1;
@@ -274,6 +277,8 @@ void pg_net_worker(__attribute__((unused)) Datum main_arg) {
274277
continue;
275278
}
276279

280+
pgstat_report_activity(STATE_RUNNING, NULL);
281+
277282
uint64 requests_consumed = 0;
278283
uint64 expired_responses = 0;
279284

@@ -397,6 +402,9 @@ void pg_net_worker(__attribute__((unused)) Datum main_arg) {
397402

398403
} while (!worker_should_restart && (requests_consumed > 0 || expired_responses > 0));
399404

405+
// Inner loop drained; back to waiting for the next wake.
406+
pgstat_report_activity(STATE_IDLE, NULL);
407+
400408
} while (!worker_should_restart);
401409

402410
publish_state(WS_EXITED);

test/test_worker_behavior.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,3 +588,54 @@ def test_worker_writes_trigger_autoanalyze_on_http_response(sess, autocommit_ses
588588
autocommit_sess.execute(text("alter system reset autovacuum_naptime;"))
589589
autocommit_sess.execute(text("select pg_reload_conf();"))
590590

591+
592+
def test_worker_reports_activity_in_pg_stat_activity(sess, autocommit_sess):
593+
"""the pg_net worker must call pgstat_report_activity() so its row in
594+
pg_stat_activity has a valid state column.
595+
"""
596+
597+
autocommit_sess.execute(text("select net.wait_until_running();"))
598+
599+
# Wait for the worker to drain any leftover work from previous tests
600+
# and settle into idle. Polling makes this robust regardless of what
601+
# ran before.
602+
deadline = time.time() + 5.0
603+
state = None
604+
while time.time() < deadline:
605+
(state,) = autocommit_sess.execute(text(
606+
"select state from pg_stat_activity where backend_type ilike '%pg_net%';"
607+
)).fetchone()
608+
if state == 'idle':
609+
break
610+
time.sleep(0.1)
611+
assert state == 'idle', (
612+
f"pg_net worker state expected 'idle' at rest, got {state!r}. "
613+
"Without pgstat_report_activity(STATE_IDLE, ...) the state column "
614+
"stays NULL."
615+
)
616+
617+
# Fire a slow request so the worker stays active long enough to observe.
618+
sess.execute(text("""
619+
select net.http_get('http://localhost:8080/pathological?status=200&delay=2');
620+
"""))
621+
sess.commit()
622+
623+
# Poll for 'active' for up to 5s. The slow request keeps the worker
624+
# busy for ~2s, so we have a wide observation window.
625+
deadline = time.time() + 5.0
626+
saw_active = False
627+
while time.time() < deadline:
628+
(state,) = autocommit_sess.execute(text(
629+
"select state from pg_stat_activity where backend_type ilike '%pg_net%';"
630+
)).fetchone()
631+
if state == 'active':
632+
saw_active = True
633+
break
634+
time.sleep(0.1)
635+
636+
assert saw_active, (
637+
"pg_net worker state was never observed as 'active' during a slow "
638+
"request. Without pgstat_report_activity(STATE_RUNNING, ...) the "
639+
"state column stays NULL."
640+
)
641+

0 commit comments

Comments
 (0)