Skip to content

Allow custom names for User-Defined Actions #7958

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .unreleased/pr_7958
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implements: #7958 Allow custom names for User-Defined Actions
8 changes: 5 additions & 3 deletions sql/job_api.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ CREATE OR REPLACE FUNCTION @[email protected]_job(
scheduled BOOL DEFAULT true,
check_config REGPROC DEFAULT NULL,
fixed_schedule BOOL DEFAULT TRUE,
timezone TEXT DEFAULT NULL
timezone TEXT DEFAULT NULL,
job_name TEXT DEFAULT NULL
) RETURNS INTEGER AS '@MODULE_PATHNAME@', 'ts_job_add' LANGUAGE C VOLATILE;

CREATE OR REPLACE FUNCTION @[email protected]_job(job_id INTEGER) RETURNS VOID AS '@MODULE_PATHNAME@', 'ts_job_delete' LANGUAGE C VOLATILE STRICT;
Expand All @@ -30,10 +31,11 @@ CREATE OR REPLACE FUNCTION @[email protected]_job(
check_config REGPROC = NULL,
fixed_schedule BOOL = NULL,
initial_start TIMESTAMPTZ = NULL,
timezone TEXT DEFAULT NULL
timezone TEXT DEFAULT NULL,
job_name TEXT DEFAULT NULL
)
RETURNS TABLE (job_id INTEGER, schedule_interval INTERVAL, max_runtime INTERVAL, max_retries INTEGER, retry_period INTERVAL, scheduled BOOL, config JSONB,
next_start TIMESTAMPTZ, check_config TEXT, fixed_schedule BOOL, initial_start TIMESTAMPTZ, timezone TEXT)
next_start TIMESTAMPTZ, check_config TEXT, fixed_schedule BOOL, initial_start TIMESTAMPTZ, timezone TEXT, application_name name)
AS '@MODULE_PATHNAME@', 'ts_job_alter'
LANGUAGE C VOLATILE;

Expand Down
62 changes: 62 additions & 0 deletions sql/updates/latest-dev.sql
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,65 @@ LANGUAGE C VOLATILE;

UPDATE _timescaledb_catalog.hypertable SET chunk_sizing_func_schema = '_timescaledb_functions' WHERE chunk_sizing_func_schema = '_timescaledb_internal' AND chunk_sizing_func_name = 'calculate_chunk_interval';

DROP FUNCTION IF EXISTS @[email protected]_job(
proc REGPROC,
schedule_interval INTERVAL,
config JSONB,
initial_start TIMESTAMPTZ,
scheduled BOOL,
check_config REGPROC,
fixed_schedule BOOL,
timezone TEXT
);

CREATE FUNCTION @[email protected]_job(
proc REGPROC,
schedule_interval INTERVAL,
config JSONB DEFAULT NULL,
initial_start TIMESTAMPTZ DEFAULT NULL,
scheduled BOOL DEFAULT true,
check_config REGPROC DEFAULT NULL,
fixed_schedule BOOL DEFAULT TRUE,
timezone TEXT DEFAULT NULL,
job_name TEXT DEFAULT NULL
)
RETURNS INTEGER
AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
LANGUAGE C VOLATILE;

DROP FUNCTION IF EXISTS @[email protected]_job(
job_id INTEGER,
schedule_interval INTERVAL,
max_runtime INTERVAL,
max_retries INTEGER,
retry_period INTERVAL,
scheduled BOOL,
config JSONB,
next_start TIMESTAMPTZ,
if_exists BOOL,
check_config REGPROC,
fixed_schedule BOOL,
initial_start TIMESTAMPTZ,
timezone TEXT
);

CREATE FUNCTION @[email protected]_job(
job_id INTEGER,
schedule_interval INTERVAL = NULL,
max_runtime INTERVAL = NULL,
max_retries INTEGER = NULL,
retry_period INTERVAL = NULL,
scheduled BOOL = NULL,
config JSONB = NULL,
next_start TIMESTAMPTZ = NULL,
if_exists BOOL = FALSE,
check_config REGPROC = NULL,
fixed_schedule BOOL = NULL,
initial_start TIMESTAMPTZ = NULL,
timezone TEXT DEFAULT NULL,
job_name TEXT DEFAULT NULL
)
RETURNS TABLE (job_id INTEGER, schedule_interval INTERVAL, max_runtime INTERVAL, max_retries INTEGER, retry_period INTERVAL, scheduled BOOL, config JSONB,
next_start TIMESTAMPTZ, check_config TEXT, fixed_schedule BOOL, initial_start TIMESTAMPTZ, timezone TEXT, application_name name)
AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
LANGUAGE C VOLATILE;
63 changes: 63 additions & 0 deletions sql/updates/reverse-dev.sql
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,66 @@ CREATE FUNCTION @[email protected]_continuous_aggregate_policy(
RETURNS INTEGER
AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
LANGUAGE C VOLATILE;

DROP FUNCTION IF EXISTS @[email protected]_job(
proc REGPROC,
schedule_interval INTERVAL,
config JSONB,
initial_start TIMESTAMPTZ,
scheduled BOOL,
check_config REGPROC,
fixed_schedule BOOL,
timezone TEXT,
job_name TEXT
);

CREATE FUNCTION @[email protected]_job(
proc REGPROC,
schedule_interval INTERVAL,
config JSONB DEFAULT NULL,
initial_start TIMESTAMPTZ DEFAULT NULL,
scheduled BOOL DEFAULT true,
check_config REGPROC DEFAULT NULL,
fixed_schedule BOOL DEFAULT TRUE,
timezone TEXT DEFAULT NULL
)
RETURNS INTEGER
AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
LANGUAGE C VOLATILE;

DROP FUNCTION IF EXISTS @[email protected]_job(
job_id INTEGER,
schedule_interval INTERVAL,
max_runtime INTERVAL,
max_retries INTEGER,
retry_period INTERVAL,
scheduled BOOL,
config JSONB,
next_start TIMESTAMPTZ,
if_exists BOOL,
check_config REGPROC,
fixed_schedule BOOL,
initial_start TIMESTAMPTZ,
timezone TEXT,
job_name TEXT
);

CREATE FUNCTION @[email protected]_job(
job_id INTEGER,
schedule_interval INTERVAL = NULL,
max_runtime INTERVAL = NULL,
max_retries INTEGER = NULL,
retry_period INTERVAL = NULL,
scheduled BOOL = NULL,
config JSONB = NULL,
next_start TIMESTAMPTZ = NULL,
if_exists BOOL = FALSE,
check_config REGPROC = NULL,
fixed_schedule BOOL = NULL,
initial_start TIMESTAMPTZ = NULL,
timezone TEXT DEFAULT NULL
)
RETURNS TABLE (job_id INTEGER, schedule_interval INTERVAL, max_runtime INTERVAL, max_retries INTEGER, retry_period INTERVAL, scheduled BOOL, config JSONB,
next_start TIMESTAMPTZ, check_config TEXT, fixed_schedule BOOL, initial_start TIMESTAMPTZ, timezone TEXT)
AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
LANGUAGE C VOLATILE;
4 changes: 4 additions & 0 deletions src/bgw/job.c
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,10 @@ bgw_job_tuple_update_by_id(TupleInfo *ti, void *const data)
bool isnull[Natts_bgw_job] = { 0 };
bool doReplace[Natts_bgw_job] = { 0 };

values[AttrNumberGetAttrOffset(Anum_bgw_job_application_name)] =
NameGetDatum(&updated_job->fd.application_name);
doReplace[AttrNumberGetAttrOffset(Anum_bgw_job_application_name)] = true;

Datum old_schedule_interval =
slot_getattr(ti->slot, Anum_bgw_job_schedule_interval, &isnull[0]);
Assert(!isnull[0]);
Expand Down
43 changes: 42 additions & 1 deletion tsl/src/bgw_policy/job_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ validate_check_signature(Oid check)
* 5 check_config REGPROC DEFAULT NULL
* 6 fixed_schedule BOOL DEFAULT TRUE
* 7 timezone TEXT DEFAULT NULL
* 8 job_name TEXT DEFAULT NULL
* ) RETURNS INTEGER
*/
Datum
Expand Down Expand Up @@ -99,6 +100,7 @@ job_add(PG_FUNCTION_ARGS)
/* verify it's a valid timezone */
if (timezone != NULL)
valid_timezone = ts_bgw_job_validate_timezone(PG_GETARG_DATUM(7));
char *job_name_str = PG_ARGISNULL(8) ? NULL : text_to_cstring(PG_GETARG_TEXT_PP(8));

TS_PREVENT_FUNC_IF_READ_ONLY();

Expand Down Expand Up @@ -161,7 +163,20 @@ job_add(PG_FUNCTION_ARGS)
ts_bgw_job_validate_job_owner(owner);

/* Next, insert a new job into jobs table */
namestrcpy(&application_name, "User-Defined Action");
if (job_name_str)
{
/* 7 bytes are reserved for job id which will be appended later. */
if (strlen(job_name_str) >= NAMEDATALEN - 7)
{
ereport(ERROR,
(errcode(ERRCODE_NAME_TOO_LONG),
errmsg("application name \"%s\": too long.",
job_name_str)));
}
namestrcpy(&application_name, job_name_str);
}
else
namestrcpy(&application_name, "User-Defined Action");
namestrcpy(&proc_schema, get_namespace_name(get_func_namespace(proc)));
namestrcpy(&proc_name, func_name);

Expand Down Expand Up @@ -283,6 +298,7 @@ job_run(PG_FUNCTION_ARGS)
* 10 fixed_schedule BOOL = NULL,
* 11 initial_start TIMESTAMPTZ = NULL
* 12 timezone TEXT = NULL
* 13 job_name TEXT = NULL
* ) RETURNS TABLE (
* job_id INTEGER,
* schedule_interval INTERVAL,
Expand All @@ -296,6 +312,7 @@ job_run(PG_FUNCTION_ARGS)
* fixed_schedule BOOL
* initial_start TIMESTAMPTZ
* timezone TEXT
* job_name TEXT
* )
*/
Datum
Expand Down Expand Up @@ -436,6 +453,28 @@ job_alter(PG_FUNCTION_ARGS)
job->fd.initial_start = initial_start;
}

if (!PG_ARGISNULL(13))
{
char app_name[NAMEDATALEN];
int name_len;

name_len = snprintf(app_name,
NAMEDATALEN,
"%s [%d]",
text_to_cstring(PG_GETARG_TEXT_PP(13)),
job_id);

if (name_len >= NAMEDATALEN)
{
ereport(ERROR,
(errcode(ERRCODE_NAME_TOO_LONG),
errmsg("application name \"%s [%d]\": too long.",
text_to_cstring(PG_GETARG_TEXT_PP(13)),
job_id)));
}
namestrcpy(&job->fd.application_name, app_name);
}

if (valid_timezone != NULL)
job->fd.timezone = cstring_to_text(valid_timezone);
else
Expand Down Expand Up @@ -525,6 +564,8 @@ job_alter(PG_FUNCTION_ARGS)
else
nulls[11] = true;

values[12] = NameGetDatum(&job->fd.application_name);

tuple = heap_form_tuple(tupdesc, values, nulls);
return HeapTupleGetDatum(tuple);
}
Expand Down
27 changes: 22 additions & 5 deletions tsl/test/expected/bgw_custom.out
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ SELECT add_job('custom_func', NULL);
ERROR: schedule interval cannot be NULL
SELECT add_job('custom_func', 'invalid interval');
ERROR: invalid input syntax for type interval: "invalid interval" at character 31
SELECT add_job('custom_func', '1h', job_name := 'this_is_a_really_really_really_long_application_name_to_overflow');
ERROR: application name "this_is_a_really_really_really_long_application_name_to_overflow": too long.
\set ON_ERROR_STOP 1
select '2000-01-01 00:00:00+00' as time_zero \gset
SELECT add_job('custom_func','1h', config:='{"type":"function"}'::jsonb, initial_start => :'time_zero'::TIMESTAMPTZ);
Expand All @@ -68,7 +70,7 @@ SELECT add_job('custom_func', '1h', config:='{"type":"function"}'::jsonb, initia
1003
(1 row)

SELECT add_job('custom_func_definer', '1h', config:='{"type":"function"}'::jsonb, initial_start => :'time_zero'::TIMESTAMPTZ);
SELECT add_job('custom_func_definer', '1h', config:='{"type":"function"}'::jsonb, initial_start => :'time_zero'::TIMESTAMPTZ, job_name := 'custom_job_name');
add_job
---------
1004
Expand All @@ -82,7 +84,7 @@ SELECT * FROM timescaledb_information.jobs WHERE job_id >= 1000 ORDER BY 1;
1001 | User-Defined Action [1001] | @ 1 hour | @ 0 | -1 | @ 5 mins | public | custom_proc | default_perm_user | t | t | {"type": "procedure"} | Fri Dec 31 16:00:00 1999 PST | Fri Dec 31 16:00:00 1999 PST | | | |
1002 | User-Defined Action [1002] | @ 1 hour | @ 0 | -1 | @ 5 mins | public | custom_proc2 | default_perm_user | t | t | {"type": "procedure"} | Fri Dec 31 16:00:00 1999 PST | Fri Dec 31 16:00:00 1999 PST | | | |
1003 | User-Defined Action [1003] | @ 1 hour | @ 0 | -1 | @ 5 mins | public | custom_func | default_perm_user | t | t | {"type": "function"} | Fri Dec 31 16:00:00 1999 PST | Fri Dec 31 16:00:00 1999 PST | | | |
1004 | User-Defined Action [1004] | @ 1 hour | @ 0 | -1 | @ 5 mins | public | custom_func_definer | default_perm_user | t | t | {"type": "function"} | Fri Dec 31 16:00:00 1999 PST | Fri Dec 31 16:00:00 1999 PST | | | |
1004 | custom_job_name [1004] | @ 1 hour | @ 0 | -1 | @ 5 mins | public | custom_func_definer | default_perm_user | t | t | {"type": "function"} | Fri Dec 31 16:00:00 1999 PST | Fri Dec 31 16:00:00 1999 PST | | | |
(5 rows)

SELECT count(*) FROM _timescaledb_config.bgw_job WHERE config->>'type' IN ('procedure', 'function');
Expand Down Expand Up @@ -164,6 +166,8 @@ SELECT alter_job(NULL, if_exists => false);
ERROR: job ID cannot be NULL
SELECT alter_job(-1, if_exists => false);
ERROR: job -1 not found
SELECT alter_job(1000, job_name => 'this_is_a_really_really_really_long_application_name_to_overflow');
ERROR: application name "this_is_a_really_really_really_long_application_name_to_overflow [1000]": too long.
\set ON_ERROR_STOP 1
-- test bad input but don't fail
SELECT alter_job(NULL, if_exists => true);
Expand Down Expand Up @@ -230,6 +234,19 @@ SELECT scheduled, config FROM timescaledb_information.jobs WHERE job_id = 1000;
f | {"test": "test"}
(1 row)

-- test updating the job name
SELECT job_id, application_name FROM alter_job(1000,job_name:='custom_name_2');
job_id | application_name
--------+----------------------
1000 | custom_name_2 [1000]
(1 row)

SELECT application_name FROM timescaledb_information.jobs WHERE job_id = 1000;
application_name
----------------------
custom_name_2 [1000]
(1 row)

-- Done with job 1000 now, so remove it.
SELECT delete_job(1000);
delete_job
Expand Down Expand Up @@ -906,9 +923,9 @@ update _timescaledb_catalog.chunk set status=3 where table_name = :'new_uncompre
SELECT add_compression_policy('sensor_data', INTERVAL '1' minute) AS compressjob_id \gset
-- set recompress to true
SELECT alter_job(id,config:=jsonb_set(config,'{recompress}', 'true')) FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id;
alter_job
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(1014,"@ 12 hours","@ 0",-1,"@ 1 hour",t,"{""recompress"": true, ""hypertable_id"": 4, ""compress_after"": ""@ 1 min""}",-infinity,_timescaledb_functions.policy_compression_check,f,,)
alter_job
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(1014,"@ 12 hours","@ 0",-1,"@ 1 hour",t,"{""recompress"": true, ""hypertable_id"": 4, ""compress_after"": ""@ 1 min""}",-infinity,_timescaledb_functions.policy_compression_check,f,,,"Compression Policy [1014]")
(1 row)

-- verify that there are other uncompressed new chunks that need to be compressed
Expand Down
12 changes: 6 additions & 6 deletions tsl/test/expected/bgw_db_scheduler.out
Original file line number Diff line number Diff line change
Expand Up @@ -1425,9 +1425,9 @@ SELECT wait_for_timer_to_run(0);
SELECT insert_job('another', 'bgw_test_job_1', INTERVAL '100ms', INTERVAL '100s', INTERVAL '1s') AS job_id \gset
-- call alter_job to trigger cache invalidation
SELECT alter_job(:job_id,scheduled:=true);
alter_job
---------------------------------------------------------------------
(1024,"@ 0.1 secs","@ 1 min 40 secs",5,"@ 1 sec",t,,-infinity,,f,,)
alter_job
-----------------------------------------------------------------------------
(1024,"@ 0.1 secs","@ 1 min 40 secs",5,"@ 1 sec",t,,-infinity,,f,,,another)
(1 row)

SELECT ts_bgw_params_reset_time(50000, true);
Expand Down Expand Up @@ -1541,9 +1541,9 @@ SELECT wait_for_timer_to_run(400000);
SELECT insert_job('new_job', 'bgw_test_job_1', INTERVAL '10ms', INTERVAL '100s', INTERVAL '1s') AS job_id \gset
-- call alter_job to trigger cache invalidation
SELECT alter_job(:job_id,scheduled:=true);
alter_job
----------------------------------------------------------------------
(1025,"@ 0.01 secs","@ 1 min 40 secs",5,"@ 1 sec",t,,-infinity,,f,,)
alter_job
------------------------------------------------------------------------------
(1025,"@ 0.01 secs","@ 1 min 40 secs",5,"@ 1 sec",t,,-infinity,,f,,,new_job)
(1 row)

SELECT ts_bgw_params_reset_time(450000, true);
Expand Down
18 changes: 9 additions & 9 deletions tsl/test/expected/bgw_db_scheduler_fixed.out
Original file line number Diff line number Diff line change
Expand Up @@ -1424,9 +1424,9 @@ SELECT wait_for_timer_to_run(0);
SELECT insert_job('another', 'bgw_test_job_1', INTERVAL '100ms', INTERVAL '100s', INTERVAL '1s') AS job_id \gset
-- call alter_job to trigger cache invalidation
SELECT alter_job(:job_id,scheduled:=true);
alter_job
---------------------------------------------------------------------------------------------------
(1024,"@ 0.1 secs","@ 1 min 40 secs",5,"@ 1 sec",t,,-infinity,,t,"Fri Dec 31 16:00:00 1999 PST",)
alter_job
-----------------------------------------------------------------------------------------------------------
(1024,"@ 0.1 secs","@ 1 min 40 secs",5,"@ 1 sec",t,,-infinity,,t,"Fri Dec 31 16:00:00 1999 PST",,another)
(1 row)

SELECT ts_bgw_params_reset_time(50000, true);
Expand Down Expand Up @@ -1526,9 +1526,9 @@ SELECT wait_for_timer_to_run(400000);
SELECT insert_job('new_job', 'bgw_test_job_1', INTERVAL '10ms', INTERVAL '100s', INTERVAL '1s') AS job_id \gset
-- call alter_job to trigger cache invalidation
SELECT alter_job(:job_id,scheduled:=true);
alter_job
----------------------------------------------------------------------------------------------------
(1025,"@ 0.01 secs","@ 1 min 40 secs",5,"@ 1 sec",t,,-infinity,,t,"Fri Dec 31 16:00:00 1999 PST",)
alter_job
------------------------------------------------------------------------------------------------------------
(1025,"@ 0.01 secs","@ 1 min 40 secs",5,"@ 1 sec",t,,-infinity,,t,"Fri Dec 31 16:00:00 1999 PST",,new_job)
(1 row)

SELECT ts_bgw_params_reset_time(450000, true);
Expand Down Expand Up @@ -1907,8 +1907,8 @@ SELECT * FROM _timescaledb_internal.bgw_job_stat WHERE job_id = :jobid_fixed_2;

-- next start is now updated
SELECT alter_job(:jobid_fixed_2, fixed_schedule => false);
alter_job
-------------------------------------------------------------------------------------------------------------
(1035,"@ 30 secs","@ 0",-1,"@ 5 mins",t,,"Sat Jan 01 00:01:03 2000 PST",,f,"Sat Jan 01 00:00:23 2000 PST",)
alter_job
------------------------------------------------------------------------------------------------------------------------------------------
(1035,"@ 30 secs","@ 0",-1,"@ 5 mins",t,,"Sat Jan 01 00:01:03 2000 PST",,f,"Sat Jan 01 00:00:23 2000 PST",,"User-Defined Action [1035]")
(1 row)

Loading
Loading