Skip to content

Commit

Permalink
Set status for backend in background jobs
Browse files Browse the repository at this point in the history
The status of background workers is recorded using the function
`pgstat_record_activity` which allow the status of the background
worker to be inspected using the `status` field in `pg_stat_activity`.
This is used by the `timescaledb_information.job_stats` view to show if
a job is running, scheduled, or paused.

However, the activity was never recorded in the code and hence the
field was always NULL. Since this was the default for the `job_status`
field of `timescaledb_information.job_stats` it would always show as
`Scheduled`.

This commit fixes this by adding calls to `pgstat_record_activity` and
suitable locations

Fixes #2831
  • Loading branch information
mkindahl committed Jan 22, 2021
1 parent b1dc030 commit ca9b055
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 1 deletion.
3 changes: 2 additions & 1 deletion sql/views.sql
Expand Up @@ -61,7 +61,8 @@ SELECT ht.schema_name AS hypertable_schema,
'Failed'
END
END AS last_run_status,
CASE WHEN pgs.state = 'active' THEN
CASE
WHEN pgs.state = 'active' THEN
'Running'
WHEN j.scheduled = FALSE THEN
'Paused'
Expand Down
2 changes: 2 additions & 0 deletions src/bgw/job_stat.c
Expand Up @@ -429,6 +429,7 @@ ts_bgw_job_stat_mark_start(int32 bgw_job_id)
RowExclusiveLock))
bgw_job_stat_insert_relation(rel, bgw_job_id, true, DT_NOBEGIN);
table_close(rel, ShareRowExclusiveLock);
pgstat_report_activity(STATE_IDLE, NULL);
}
}

Expand All @@ -446,6 +447,7 @@ ts_bgw_job_stat_mark_end(BgwJob *job, JobResult result)
&res,
RowExclusiveLock))
elog(ERROR, "unable to find job statistics for job %d", job->fd.id);
pgstat_report_activity(STATE_IDLE, NULL);
}

bool
Expand Down
4 changes: 4 additions & 0 deletions src/bgw/scheduler.c
Expand Up @@ -734,6 +734,8 @@ ts_bgw_scheduler_process(int32 run_for_interval_ms,
TimestampTz start = ts_timer_get_current_timestamp();
TimestampTz quit_time = DT_NOEND;

pgstat_report_activity(STATE_RUNNING, NULL);

/* txn to read the list of jobs from the DB */
StartTransactionCommand();
scheduled_jobs = ts_update_scheduled_jobs_list(scheduled_jobs, scheduler_mctx);
Expand Down Expand Up @@ -763,7 +765,9 @@ ts_bgw_scheduler_process(int32 run_for_interval_ms,
next_wakeup = least_timestamp(next_wakeup, earliest_wakeup_to_start_next_job());
next_wakeup = least_timestamp(next_wakeup, earliest_job_timeout());

pgstat_report_activity(STATE_IDLE, NULL);
ts_timer_wait(next_wakeup);
pgstat_report_activity(STATE_RUNNING, NULL);

CHECK_FOR_INTERRUPTS();

Expand Down
14 changes: 14 additions & 0 deletions tsl/src/bgw_policy/job.c
Expand Up @@ -463,6 +463,7 @@ job_execute(BgwJob *job)
List *name;
FuncExpr *funcexpr;
MemoryContext parent_ctx = CurrentMemoryContext;
StringInfo query;

if (!IsTransactionOrTransactionBlock())
{
Expand Down Expand Up @@ -504,6 +505,19 @@ job_execute(BgwJob *job)
InvalidOid,
COERCE_EXPLICIT_CALL);

/* Here we create a query string from the function/procedure name that we
* are calling. We do not update the status after the execution has
* finished since this is wrapped inside the code that starts and stops
* any job, not just custom jobs. We just provide more detailed
* information here that we are actually calling a specific custom
* function. */
query = makeStringInfo();
appendStringInfo(query,
"CALL %s.%s()",
NameStr(job->fd.proc_schema),
NameStr(job->fd.proc_name));
pgstat_report_activity(STATE_RUNNING, query->data);

switch (prokind)
{
case PROKIND_FUNCTION:
Expand Down
29 changes: 29 additions & 0 deletions tsl/test/expected/bgw_db_scheduler.out
Expand Up @@ -212,6 +212,35 @@ SELECT application_name FROM pg_stat_activity WHERE application_name LIKE 'User-
User-Defined Action [1001]
(1 row)

\x on
SELECT * FROM timescaledb_information.job_stats;
-[ RECORD 1 ]----------+-------------------------------
hypertable_schema |
hypertable_name |
job_id | 1001
last_run_started_at | Fri Dec 31 16:00:00.1 1999 PST
last_successful_finish | -infinity
last_run_status |
job_status | Running
last_run_duration |
next_start | -infinity
total_runs | 1
total_successes | 0
total_failures | 0

-- Showing non-volatile information from pg_stat_activity for
-- debugging purposes. Information schema above reads from this view.
SELECT datname, usename, application_name, state, wait_event_type, wait_event
FROM pg_stat_activity WHERE application_name LIKE 'User-Defined Action%';
-[ RECORD 1 ]----+---------------------------
datname | db_bgw_db_scheduler
usename | default_perm_user
application_name | User-Defined Action [1001]
state | active
wait_event_type | Timeout
wait_event | PgSleep

\x off
-- have to suppress notices here as delete_job will print pid of the running background worker processes
SET client_min_messages TO WARNING;
SELECT delete_job(:job_id);
Expand Down
8 changes: 8 additions & 0 deletions tsl/test/sql/bgw_db_scheduler.sql
Expand Up @@ -150,6 +150,14 @@ SELECT ts_bgw_db_scheduler_test_run();
SELECT wait_for_logentry(:job_id);
SELECT application_name FROM pg_stat_activity WHERE application_name LIKE 'User-Defined Action%';

\x on
SELECT * FROM timescaledb_information.job_stats;
-- Showing non-volatile information from pg_stat_activity for
-- debugging purposes. Information schema above reads from this view.
SELECT datname, usename, application_name, state, wait_event_type, wait_event
FROM pg_stat_activity WHERE application_name LIKE 'User-Defined Action%';
\x off

-- have to suppress notices here as delete_job will print pid of the running background worker processes
SET client_min_messages TO WARNING;
SELECT delete_job(:job_id);
Expand Down

0 comments on commit ca9b055

Please sign in to comment.