@@ -10,238 +10,8 @@ tags: [user-defined actions, background jobs, scheduled jobs]
1010User-defined actions allow you to run functions and procedures implemented in a
1111language of your choice on a schedule within TimescaleDB. This allows
1212automatic periodic tasks that are not covered by existing policies, or the
13- ability to enhance existing policies with additional functionality .
13+ ability to enhance existing policies with additional features .
1414
15- User-defined actions have allow free-form configuration through a JSONB object
16- which allows endless flexibility and reusability.
15+ To learn more about user-defined actions, see the [ how-to guide] [ how-to ] .
1716
18- ## Examples
19-
20- The following section provides a number of examples of user-defined actions
21- that you can specify and subsequently schedule as part of TimescaleDB's
22- automation framework.
23-
24- ### Generic retention
25-
26- Create a generic data retention policy that applies to ALL hypertables, as opposed
27- to just a single one as required by ` add_retention_policy ` .
28- The policy could be further refined with additional filters, by adding a WHERE
29- clause to the PERFORM query in the procedure definition.
30-
31- ``` sql
32- CREATE OR REPLACE PROCEDURE generic_retention (job_id int , config jsonb)
33- LANGUAGE PLPGSQL
34- AS $$
35- DECLARE
36- drop_after interval;
37- BEGIN
38- SELECT jsonb_object_field_text (config, ' drop_after' )::interval INTO STRICT drop_after;
39-
40- IF drop_after IS NULL THEN
41- RAISE EXCEPTION ' Config must have drop_after' ;
42- END IF;
43-
44- PERFORM drop_chunks(format(' %I.%I' , table_schema, table_name), older_than => drop_after)
45- FROM timescaledb_information .hypertables ;
46- END
47- $$;
48- ```
49-
50- Register job to run daily dropping chunks on all hypertables that are older
51- than 12 months.
52-
53- ``` sql
54- SELECT add_job(' generic_retention' ,' 1d' , config => ' {"drop_after":"12 month"}' );
55- ```
56-
57- ### Tiered storage
58-
59- Action that moves chunks older than a certain time to a different tablespace.
60-
61- ``` sql
62- CREATE OR REPLACE PROCEDURE move_chunks (job_id int , config jsonb)
63- LANGUAGE PLPGSQL
64- AS $$
65- DECLARE
66- ht REGCLASS;
67- lag interval;
68- destination name;
69- chunk REGCLASS;
70- tmp_name name;
71- BEGIN
72- SELECT jsonb_object_field_text (config, ' hypertable' )::regclass INTO STRICT ht;
73- SELECT jsonb_object_field_text (config, ' lag' )::interval INTO STRICT lag;
74- SELECT jsonb_object_field_text (config, ' tablespace' ) INTO STRICT destination;
75-
76- IF ht IS NULL OR lag IS NULL OR destination IS NULL THEN
77- RAISE EXCEPTION ' Config must have hypertable, lag and destination' ;
78- END IF;
79-
80- FOR chunk IN
81- SELECT show .oid
82- FROM show_chunks(ht, older_than => lag)
83- SHOW (oid )
84- INNER JOIN pg_class pgc ON pgc .oid = show .oid
85- INNER JOIN pg_tablespace pgts ON pgts .oid = pgc .reltablespace
86- WHERE pgts .spcname != destination
87- LOOP
88- RAISE NOTICE ' Moving chunk: %' , chunk::text ;
89- EXECUTE format(' ALTER TABLE %s SET TABLESPACE %I;' , chunk, destination);
90- END LOOP;
91- END
92- $$;
93- ```
94-
95- Register job to run daily moving chunks older than 12 months on hypertable
96- metrics to tablespace old_chunks.
97-
98- ``` sql
99- SELECT add_job(' move_chunks' ,' 1d' , config => ' {"hypertable":"metrics","lag":"12 month","tablespace":"old_chunks"}' );
100- ```
101-
102- The above action uses the simpler ` ALTER TABLE ... SET TABLESPACE ` for moving
103- a chunk, but it could alternatively be written in terms of TimescaleDB's
104- [ ` move_chunk ` ] [ api-move_chunk ] . The ` move_chunk ` function also requires an
105- index as input, but performs data re-ordering as part of the move (for faster
106- subsequent queries) and requires lower lock levels, so the chunk remains available
107- for reads during the move.
108-
109- ### Downsample and compress
110-
111- Action that downsamples and compresses chunks on hypertable ` metrics `
112- older than a certain age. The example query computes a simple ` avg ` over
113- hourly data for downsampling, but this query can be arbitrarily complex.
114-
115- ``` sql
116- CREATE OR REPLACE PROCEDURE downsample_compress (job_id int , config jsonb)
117- LANGUAGE PLPGSQL
118- AS $$
119- DECLARE
120- lag interval;
121- chunk REGCLASS;
122- tmp_name name;
123- BEGIN
124- SELECT jsonb_object_field_text (config, ' lag' )::interval INTO STRICT lag;
125-
126- IF lag IS NULL THEN
127- RAISE EXCEPTION ' Config must have lag' ;
128- END IF;
129-
130- FOR chunk IN
131- SELECT show .oid
132- FROM show_chunks(' metrics' , older_than => lag) SHOW (oid )
133- INNER JOIN pg_class pgc ON pgc .oid = show .oid
134- INNER JOIN pg_namespace pgns ON pgc .relnamespace = pgns .oid
135- INNER JOIN timescaledb_information .chunks chunk ON chunk .chunk_name = pgc .relname
136- AND chunk .chunk_schema = pgns .nspname
137- WHERE chunk .is_compressed ::bool = FALSE
138- LOOP
139- RAISE NOTICE ' Processing chunk: %' , chunk::text ;
140-
141- -- build name for temp table
142- SELECT ' _tmp' || relname
143- FROM pg_class
144- WHERE oid = chunk INTO STRICT tmp_name;
145-
146- -- copy downsampled chunk data into temp table
147- EXECUTE format($sql$ CREATE UNLOGGED TABLE %I AS
148- SELECT time_bucket(' 1h' , time ), device_id, avg (value) FROM %s GROUP BY 1 , 2 ;
149- $sql$, tmp_name, chunk);
150-
151- -- clear original chunk
152- EXECUTE format(' TRUNCATE %s;' , chunk);
153-
154- -- copy downsampled data back into chunk
155- EXECUTE format(' INSERT INTO %s(time, device_id, value) SELECT * FROM %I;' , chunk, tmp_name);
156-
157- -- drop temp table
158- EXECUTE format(' DROP TABLE %I;' , tmp_name);
159-
160- PERFORM compress_chunk (chunk);
161-
162- COMMIT ;
163- END LOOP;
164- END
165- $$;
166- ```
167-
168- Register job to run daily downsampling and compressing chunks older than
169- 12 months.
170-
171- ``` sql
172- SELECT add_job(' downsample_compress' ,' 1d' , config => ' {"lag":"12 month"}' );
173- ```
174-
175- ### Set up a table and procedure
176-
177- Set up a simple table and procedure:
178- ``` sql
179- CREATE TABLE IF NOT EXISTS times (time timestamptz );
180-
181- CREATE OR REPLACE PROCEDURE add_time(job_id int , config jsonb)
182- LANGUAGE PLPGSQL
183- AS $$
184- BEGIN
185- INSERT INTO times VALUES (now());
186- END
187- $$;
188-
189- CALL add_time(null , ' {}' );
190-
191- SELECT * from times ;
192- ```
193-
194- Returns:
195- ``` sql
196- |time |
197- |-- ---------------------------|
198- |2021 - 12 - 27 10 :50 :28 .449 - 0600 |
199- ```
200-
201- Register a job to run every 5 seconds and return a ` job_id ` :
202- ``` sql
203- SELECT add_job(' add_time' , ' 5 secs' );
204- ```
205-
206- Returns:
207- ``` sql
208- |add_job|
209- |-- -----|
210- |1000 |
211- ```
212-
213- Wait for some jobs to run, then view the results:
214- ``` sql
215- SELECT * from times ;
216- ```
217-
218- Returns:
219- ``` sql
220- |time |
221- |-- ---------------------------|
222- |2021 - 12 - 27 10 :50 :28 .449 - 0600 |
223- |2021 - 12 - 27 10 :50 :38 .825 - 0600 |
224- |2021 - 12 - 27 10 :50 :44 .164 - 0600 |
225- |2021 - 12 - 27 10 :50 :49 .207 - 0600 |
226- |...|
227- ```
228-
229- See running jobs:
230- ``` sql
231- SELECT job_id, total_runs, total_failures, total_successes
232- FROM timescaledb_information .job_stats ;
233- ```
234-
235- Returns:
236- ``` sql
237- |job_id|total_runs|total_failures|total_successes|
238- |-- ----|----------|--------------|---------------|
239- |1000 |9 |0 |9 |
240- ```
241-
242- Stop or delete the job:
243- ``` sql
244- SELECT delete_job(1000 );
245- ```
246-
247- [ api-move_chunk ] : /api/:currentVersion:/hypertable/move_chunk
17+ [ how-to ] : /timescaledb/:currentVersion:/how-to-guides/user-defined-actions/
0 commit comments