Skip to content

Commit 6c33371

Browse files
committed
Allow custom names for User-Defined Actions
This commit allows custom names for Used-Defined Actions. add_job() and alter_job() accept an additional "job_name" argument to modify the name of User-Defined Action. If "job_name" is not specified, it is names as default.
1 parent bd4bb22 commit 6c33371

25 files changed

+361
-171
lines changed

.unreleased/pr_7958

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Implements: #7958 Allow custom names for User-Defined Actions

sql/job_api.sql

+5-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ CREATE OR REPLACE FUNCTION @[email protected]_job(
1010
scheduled BOOL DEFAULT true,
1111
check_config REGPROC DEFAULT NULL,
1212
fixed_schedule BOOL DEFAULT TRUE,
13-
timezone TEXT DEFAULT NULL
13+
timezone TEXT DEFAULT NULL,
14+
job_name TEXT DEFAULT NULL
1415
) RETURNS INTEGER AS '@MODULE_PATHNAME@', 'ts_job_add' LANGUAGE C VOLATILE;
1516

1617
CREATE OR REPLACE FUNCTION @[email protected]_job(job_id INTEGER) RETURNS VOID AS '@MODULE_PATHNAME@', 'ts_job_delete' LANGUAGE C VOLATILE STRICT;
@@ -30,10 +31,11 @@ CREATE OR REPLACE FUNCTION @[email protected]_job(
3031
check_config REGPROC = NULL,
3132
fixed_schedule BOOL = NULL,
3233
initial_start TIMESTAMPTZ = NULL,
33-
timezone TEXT DEFAULT NULL
34+
timezone TEXT DEFAULT NULL,
35+
job_name TEXT DEFAULT NULL
3436
)
3537
RETURNS TABLE (job_id INTEGER, schedule_interval INTERVAL, max_runtime INTERVAL, max_retries INTEGER, retry_period INTERVAL, scheduled BOOL, config JSONB,
36-
next_start TIMESTAMPTZ, check_config TEXT, fixed_schedule BOOL, initial_start TIMESTAMPTZ, timezone TEXT)
38+
next_start TIMESTAMPTZ, check_config TEXT, fixed_schedule BOOL, initial_start TIMESTAMPTZ, timezone TEXT, application_name name)
3739
AS '@MODULE_PATHNAME@', 'ts_job_alter'
3840
LANGUAGE C VOLATILE;
3941

sql/updates/latest-dev.sql

+62
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,65 @@ LANGUAGE C VOLATILE;
3434

3535
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';
3636

37+
DROP FUNCTION IF EXISTS @[email protected]_job(
38+
proc REGPROC,
39+
schedule_interval INTERVAL,
40+
config JSONB,
41+
initial_start TIMESTAMPTZ,
42+
scheduled BOOL,
43+
check_config REGPROC,
44+
fixed_schedule BOOL,
45+
timezone TEXT
46+
);
47+
48+
CREATE FUNCTION @[email protected]_job(
49+
proc REGPROC,
50+
schedule_interval INTERVAL,
51+
config JSONB DEFAULT NULL,
52+
initial_start TIMESTAMPTZ DEFAULT NULL,
53+
scheduled BOOL DEFAULT true,
54+
check_config REGPROC DEFAULT NULL,
55+
fixed_schedule BOOL DEFAULT TRUE,
56+
timezone TEXT DEFAULT NULL,
57+
job_name TEXT DEFAULT NULL
58+
)
59+
RETURNS INTEGER
60+
AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
61+
LANGUAGE C VOLATILE;
62+
63+
DROP FUNCTION IF EXISTS @[email protected]_job(
64+
job_id INTEGER,
65+
schedule_interval INTERVAL,
66+
max_runtime INTERVAL,
67+
max_retries INTEGER,
68+
retry_period INTERVAL,
69+
scheduled BOOL,
70+
config JSONB,
71+
next_start TIMESTAMPTZ,
72+
if_exists BOOL,
73+
check_config REGPROC,
74+
fixed_schedule BOOL,
75+
initial_start TIMESTAMPTZ,
76+
timezone TEXT
77+
);
78+
79+
CREATE FUNCTION @[email protected]_job(
80+
job_id INTEGER,
81+
schedule_interval INTERVAL = NULL,
82+
max_runtime INTERVAL = NULL,
83+
max_retries INTEGER = NULL,
84+
retry_period INTERVAL = NULL,
85+
scheduled BOOL = NULL,
86+
config JSONB = NULL,
87+
next_start TIMESTAMPTZ = NULL,
88+
if_exists BOOL = FALSE,
89+
check_config REGPROC = NULL,
90+
fixed_schedule BOOL = NULL,
91+
initial_start TIMESTAMPTZ = NULL,
92+
timezone TEXT DEFAULT NULL,
93+
job_name TEXT DEFAULT NULL
94+
)
95+
RETURNS TABLE (job_id INTEGER, schedule_interval INTERVAL, max_runtime INTERVAL, max_retries INTEGER, retry_period INTERVAL, scheduled BOOL, config JSONB,
96+
next_start TIMESTAMPTZ, check_config TEXT, fixed_schedule BOOL, initial_start TIMESTAMPTZ, timezone TEXT, application_name name)
97+
AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
98+
LANGUAGE C VOLATILE;

sql/updates/reverse-dev.sql

+63
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,66 @@ CREATE FUNCTION @[email protected]_continuous_aggregate_policy(
3131
RETURNS INTEGER
3232
AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
3333
LANGUAGE C VOLATILE;
34+
35+
DROP FUNCTION IF EXISTS @[email protected]_job(
36+
proc REGPROC,
37+
schedule_interval INTERVAL,
38+
config JSONB,
39+
initial_start TIMESTAMPTZ,
40+
scheduled BOOL,
41+
check_config REGPROC,
42+
fixed_schedule BOOL,
43+
timezone TEXT,
44+
job_name TEXT
45+
);
46+
47+
CREATE FUNCTION @[email protected]_job(
48+
proc REGPROC,
49+
schedule_interval INTERVAL,
50+
config JSONB DEFAULT NULL,
51+
initial_start TIMESTAMPTZ DEFAULT NULL,
52+
scheduled BOOL DEFAULT true,
53+
check_config REGPROC DEFAULT NULL,
54+
fixed_schedule BOOL DEFAULT TRUE,
55+
timezone TEXT DEFAULT NULL
56+
)
57+
RETURNS INTEGER
58+
AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
59+
LANGUAGE C VOLATILE;
60+
61+
DROP FUNCTION IF EXISTS @[email protected]_job(
62+
job_id INTEGER,
63+
schedule_interval INTERVAL,
64+
max_runtime INTERVAL,
65+
max_retries INTEGER,
66+
retry_period INTERVAL,
67+
scheduled BOOL,
68+
config JSONB,
69+
next_start TIMESTAMPTZ,
70+
if_exists BOOL,
71+
check_config REGPROC,
72+
fixed_schedule BOOL,
73+
initial_start TIMESTAMPTZ,
74+
timezone TEXT,
75+
job_name TEXT
76+
);
77+
78+
CREATE FUNCTION @[email protected]_job(
79+
job_id INTEGER,
80+
schedule_interval INTERVAL = NULL,
81+
max_runtime INTERVAL = NULL,
82+
max_retries INTEGER = NULL,
83+
retry_period INTERVAL = NULL,
84+
scheduled BOOL = NULL,
85+
config JSONB = NULL,
86+
next_start TIMESTAMPTZ = NULL,
87+
if_exists BOOL = FALSE,
88+
check_config REGPROC = NULL,
89+
fixed_schedule BOOL = NULL,
90+
initial_start TIMESTAMPTZ = NULL,
91+
timezone TEXT DEFAULT NULL
92+
)
93+
RETURNS TABLE (job_id INTEGER, schedule_interval INTERVAL, max_runtime INTERVAL, max_retries INTEGER, retry_period INTERVAL, scheduled BOOL, config JSONB,
94+
next_start TIMESTAMPTZ, check_config TEXT, fixed_schedule BOOL, initial_start TIMESTAMPTZ, timezone TEXT)
95+
AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
96+
LANGUAGE C VOLATILE;

src/bgw/job.c

+4
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,10 @@ bgw_job_tuple_update_by_id(TupleInfo *ti, void *const data)
786786
bool isnull[Natts_bgw_job] = { 0 };
787787
bool doReplace[Natts_bgw_job] = { 0 };
788788

789+
values[AttrNumberGetAttrOffset(Anum_bgw_job_application_name)] =
790+
NameGetDatum(&updated_job->fd.application_name);
791+
doReplace[AttrNumberGetAttrOffset(Anum_bgw_job_application_name)] = true;
792+
789793
Datum old_schedule_interval =
790794
slot_getattr(ti->slot, Anum_bgw_job_schedule_interval, &isnull[0]);
791795
Assert(!isnull[0]);

tsl/src/bgw_policy/job_api.c

+36-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ validate_check_signature(Oid check)
7070
* 5 check_config REGPROC DEFAULT NULL
7171
* 6 fixed_schedule BOOL DEFAULT TRUE
7272
* 7 timezone TEXT DEFAULT NULL
73+
* 8 job_name TEXT DEFAULT NULL
7374
* ) RETURNS INTEGER
7475
*/
7576
Datum
@@ -99,6 +100,7 @@ job_add(PG_FUNCTION_ARGS)
99100
/* verify it's a valid timezone */
100101
if (timezone != NULL)
101102
valid_timezone = ts_bgw_job_validate_timezone(PG_GETARG_DATUM(7));
103+
char *job_name_str = PG_ARGISNULL(8) ? NULL : text_to_cstring(PG_GETARG_TEXT_PP(8));
102104

103105
TS_PREVENT_FUNC_IF_READ_ONLY();
104106

@@ -161,7 +163,20 @@ job_add(PG_FUNCTION_ARGS)
161163
ts_bgw_job_validate_job_owner(owner);
162164

163165
/* Next, insert a new job into jobs table */
164-
namestrcpy(&application_name, "User-Defined Action");
166+
if (job_name_str)
167+
{
168+
/* 7 bytes are reserved for job id which will be appended later. */
169+
if (strlen(job_name_str) >= NAMEDATALEN - 7)
170+
{
171+
ereport(ERROR,
172+
(errcode(ERRCODE_NAME_TOO_LONG),
173+
errmsg("application name \"%s\": too long.",
174+
job_name_str)));
175+
}
176+
namestrcpy(&application_name, job_name_str);
177+
}
178+
else
179+
namestrcpy(&application_name, "User-Defined Action");
165180
namestrcpy(&proc_schema, get_namespace_name(get_func_namespace(proc)));
166181
namestrcpy(&proc_name, func_name);
167182

@@ -283,6 +298,7 @@ job_run(PG_FUNCTION_ARGS)
283298
* 10 fixed_schedule BOOL = NULL,
284299
* 11 initial_start TIMESTAMPTZ = NULL
285300
* 12 timezone TEXT = NULL
301+
* 13 job_name TEXT = NULL
286302
* ) RETURNS TABLE (
287303
* job_id INTEGER,
288304
* schedule_interval INTERVAL,
@@ -296,6 +312,7 @@ job_run(PG_FUNCTION_ARGS)
296312
* fixed_schedule BOOL
297313
* initial_start TIMESTAMPTZ
298314
* timezone TEXT
315+
* job_name TEXT
299316
* )
300317
*/
301318
Datum
@@ -436,6 +453,22 @@ job_alter(PG_FUNCTION_ARGS)
436453
job->fd.initial_start = initial_start;
437454
}
438455

456+
if (!PG_ARGISNULL(13))
457+
{
458+
char app_name[NAMEDATALEN];
459+
int name_len;
460+
461+
name_len = snprintf(app_name, NAMEDATALEN, "%s [%d]", text_to_cstring(PG_GETARG_TEXT_PP(13)), job_id);
462+
if (name_len >= NAMEDATALEN)
463+
{
464+
ereport(ERROR,
465+
(errcode(ERRCODE_NAME_TOO_LONG),
466+
errmsg("application name \"%s [%d]\": too long.",
467+
text_to_cstring(PG_GETARG_TEXT_PP(13)), job_id)));
468+
}
469+
namestrcpy(&job->fd.application_name, app_name);
470+
}
471+
439472
if (valid_timezone != NULL)
440473
job->fd.timezone = cstring_to_text(valid_timezone);
441474
else
@@ -525,6 +558,8 @@ job_alter(PG_FUNCTION_ARGS)
525558
else
526559
nulls[11] = true;
527560

561+
values[12] = NameGetDatum(&job->fd.application_name);
562+
528563
tuple = heap_form_tuple(tupdesc, values, nulls);
529564
return HeapTupleGetDatum(tuple);
530565
}

tsl/test/expected/bgw_custom.out

+22-5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ SELECT add_job('custom_func', NULL);
4242
ERROR: schedule interval cannot be NULL
4343
SELECT add_job('custom_func', 'invalid interval');
4444
ERROR: invalid input syntax for type interval: "invalid interval" at character 31
45+
SELECT add_job('custom_func', '1h', job_name := 'this_is_a_really_really_really_long_application_name_to_overflow');
46+
ERROR: application name "this_is_a_really_really_really_long_application_name_to_overflow": too long.
4547
\set ON_ERROR_STOP 1
4648
select '2000-01-01 00:00:00+00' as time_zero \gset
4749
SELECT add_job('custom_func','1h', config:='{"type":"function"}'::jsonb, initial_start => :'time_zero'::TIMESTAMPTZ);
@@ -68,7 +70,7 @@ SELECT add_job('custom_func', '1h', config:='{"type":"function"}'::jsonb, initia
6870
1003
6971
(1 row)
7072

71-
SELECT add_job('custom_func_definer', '1h', config:='{"type":"function"}'::jsonb, initial_start => :'time_zero'::TIMESTAMPTZ);
73+
SELECT add_job('custom_func_definer', '1h', config:='{"type":"function"}'::jsonb, initial_start => :'time_zero'::TIMESTAMPTZ, job_name := 'custom_job_name');
7274
add_job
7375
---------
7476
1004
@@ -82,7 +84,7 @@ SELECT * FROM timescaledb_information.jobs WHERE job_id >= 1000 ORDER BY 1;
8284
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 | | | |
8385
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 | | | |
8486
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 | | | |
85-
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 | | | |
87+
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 | | | |
8688
(5 rows)
8789

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

237+
-- test updating the job name
238+
SELECT job_id, application_name FROM alter_job(1000,job_name:='custom_name_2');
239+
job_id | application_name
240+
--------+----------------------
241+
1000 | custom_name_2 [1000]
242+
(1 row)
243+
244+
SELECT application_name FROM timescaledb_information.jobs WHERE job_id = 1000;
245+
application_name
246+
----------------------
247+
custom_name_2 [1000]
248+
(1 row)
249+
233250
-- Done with job 1000 now, so remove it.
234251
SELECT delete_job(1000);
235252
delete_job
@@ -906,9 +923,9 @@ update _timescaledb_catalog.chunk set status=3 where table_name = :'new_uncompre
906923
SELECT add_compression_policy('sensor_data', INTERVAL '1' minute) AS compressjob_id \gset
907924
-- set recompress to true
908925
SELECT alter_job(id,config:=jsonb_set(config,'{recompress}', 'true')) FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id;
909-
alter_job
910-
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
911-
(1014,"@ 12 hours","@ 0",-1,"@ 1 hour",t,"{""recompress"": true, ""hypertable_id"": 4, ""compress_after"": ""@ 1 min""}",-infinity,_timescaledb_functions.policy_compression_check,f,,)
926+
alter_job
927+
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
928+
(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]")
912929
(1 row)
913930

914931
-- verify that there are other uncompressed new chunks that need to be compressed

tsl/test/expected/bgw_db_scheduler.out

+6-6
Original file line numberDiff line numberDiff line change
@@ -1425,9 +1425,9 @@ SELECT wait_for_timer_to_run(0);
14251425
SELECT insert_job('another', 'bgw_test_job_1', INTERVAL '100ms', INTERVAL '100s', INTERVAL '1s') AS job_id \gset
14261426
-- call alter_job to trigger cache invalidation
14271427
SELECT alter_job(:job_id,scheduled:=true);
1428-
alter_job
1429-
---------------------------------------------------------------------
1430-
(1024,"@ 0.1 secs","@ 1 min 40 secs",5,"@ 1 sec",t,,-infinity,,f,,)
1428+
alter_job
1429+
-----------------------------------------------------------------------------
1430+
(1024,"@ 0.1 secs","@ 1 min 40 secs",5,"@ 1 sec",t,,-infinity,,f,,,another)
14311431
(1 row)
14321432

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

15491549
SELECT ts_bgw_params_reset_time(450000, true);

tsl/test/expected/bgw_db_scheduler_fixed.out

+9-9
Original file line numberDiff line numberDiff line change
@@ -1424,9 +1424,9 @@ SELECT wait_for_timer_to_run(0);
14241424
SELECT insert_job('another', 'bgw_test_job_1', INTERVAL '100ms', INTERVAL '100s', INTERVAL '1s') AS job_id \gset
14251425
-- call alter_job to trigger cache invalidation
14261426
SELECT alter_job(:job_id,scheduled:=true);
1427-
alter_job
1428-
---------------------------------------------------------------------------------------------------
1429-
(1024,"@ 0.1 secs","@ 1 min 40 secs",5,"@ 1 sec",t,,-infinity,,t,"Fri Dec 31 16:00:00 1999 PST",)
1427+
alter_job
1428+
-----------------------------------------------------------------------------------------------------------
1429+
(1024,"@ 0.1 secs","@ 1 min 40 secs",5,"@ 1 sec",t,,-infinity,,t,"Fri Dec 31 16:00:00 1999 PST",,another)
14301430
(1 row)
14311431

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

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

19081908
-- next start is now updated
19091909
SELECT alter_job(:jobid_fixed_2, fixed_schedule => false);
1910-
alter_job
1911-
-------------------------------------------------------------------------------------------------------------
1912-
(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",)
1910+
alter_job
1911+
------------------------------------------------------------------------------------------------------------------------------------------
1912+
(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]")
19131913
(1 row)
19141914

0 commit comments

Comments
 (0)