Skip to content

Commit 6f08f68

Browse files
authored
feat: add cleanup function for cron job run details (#511)
# Add cleanup function for cron job run details This PR adds a new `cleanup_ensure_workers_logs` function to prevent the `cron.job_run_details` table from growing indefinitely. The function: - Deletes cron job run details older than a configurable retention period (default 24 hours) - Returns the count of deleted records - Is implemented as a security definer function with appropriate search path settings - Includes comprehensive documentation explaining its purpose and behavior The PR includes: - SQL schema definition for the function - TypeScript type definitions for the function's arguments and return values - Migration file for Supabase deployment - Two test files to verify the function works correctly: - Basic cleanup functionality with custom retention period - Proper handling when no records need deletion Note that HTTP response logs (`net._http_response`) are not cleaned by this function as they are automatically managed by pg_net with a 6-hour TTL.
1 parent 8ec9428 commit 6f08f68

File tree

6 files changed

+119
-1
lines changed

6 files changed

+119
-1
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-- Cleanup Ensure Workers Logs
2+
-- Cleans up old cron job run details to prevent the table from growing indefinitely.
3+
-- Note: net._http_response is automatically cleaned by pg_net (6 hour TTL), so we only clean cron logs.
4+
5+
drop function if exists pgflow.cleanup_ensure_workers_logs(integer);
6+
7+
create or replace function pgflow.cleanup_ensure_workers_logs(
8+
retention_hours integer default 24
9+
)
10+
returns table (cron_deleted bigint)
11+
language sql
12+
security definer
13+
set search_path = pgflow, cron, pg_temp
14+
as $$
15+
with deleted as (
16+
delete from cron.job_run_details
17+
where job_run_details.end_time < now() - (cleanup_ensure_workers_logs.retention_hours || ' hours')::interval
18+
returning 1
19+
)
20+
select count(*)::bigint as cron_deleted from deleted
21+
$$;
22+
23+
comment on function pgflow.cleanup_ensure_workers_logs(integer) is
24+
'Cleans up old cron job run details to prevent table growth.
25+
Default retention is 24 hours. HTTP response logs (net._http_response) are
26+
automatically cleaned by pg_net with a 6-hour TTL, so they are not cleaned here.
27+
This function follows the standard pg_cron maintenance pattern recommended by
28+
AWS RDS, Neon, and Supabase documentation.';

pkgs/core/src/database-types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,12 @@ export type Database = {
423423
Args: { run_id: string }
424424
Returns: number
425425
}
426+
cleanup_ensure_workers_logs: {
427+
Args: { retention_hours?: number }
428+
Returns: {
429+
cron_deleted: number
430+
}[]
431+
}
426432
complete_task: {
427433
Args: {
428434
output: Json
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-- Create "cleanup_ensure_workers_logs" function
2+
CREATE FUNCTION "pgflow"."cleanup_ensure_workers_logs" ("retention_hours" integer DEFAULT 24) RETURNS TABLE ("cron_deleted" bigint) LANGUAGE sql SECURITY DEFINER SET "search_path" = pgflow, cron, pg_temp AS $$
3+
with deleted as (
4+
delete from cron.job_run_details
5+
where job_run_details.end_time < now() - (cleanup_ensure_workers_logs.retention_hours || ' hours')::interval
6+
returning 1
7+
)
8+
select count(*)::bigint as cron_deleted from deleted
9+
$$;
10+
-- Set comment to function: "cleanup_ensure_workers_logs"
11+
COMMENT ON FUNCTION "pgflow"."cleanup_ensure_workers_logs" IS 'Cleans up old cron job run details to prevent table growth.
12+
Default retention is 24 hours. HTTP response logs (net._http_response) are
13+
automatically cleaned by pg_net with a 6-hour TTL, so they are not cleaned here.
14+
This function follows the standard pg_cron maintenance pattern recommended by
15+
AWS RDS, Neon, and Supabase documentation.';

pkgs/core/supabase/migrations/atlas.sum

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
h1:G7RvNGNjnwVtYZTuceBwoaHEXa9bd/xH6hC8x5MNxZk=
1+
h1:UPs/YAMNWH5FdnHa1GJRQZ4yiv6kOHpfBNfs6telwgI=
22
20250429164909_pgflow_initial.sql h1:I3n/tQIg5Q5nLg7RDoU3BzqHvFVjmumQxVNbXTPG15s=
33
20250517072017_pgflow_fix_poll_for_tasks_to_use_separate_statement_for_polling.sql h1:wTuXuwMxVniCr3ONCpodpVWJcHktoQZIbqMZ3sUHKMY=
44
20250609105135_pgflow_add_start_tasks_and_started_status.sql h1:ggGanW4Wyt8Kv6TWjnZ00/qVb3sm+/eFVDjGfT8qyPg=
@@ -19,3 +19,4 @@ h1:G7RvNGNjnwVtYZTuceBwoaHEXa9bd/xH6hC8x5MNxZk=
1919
20251204165231_pgflow_temp_mark_worker_stopped.sql h1:zI2FijK429oae4OpLbjU4eSaZtYhlsbvN3buWH9FKLw=
2020
20251205103442_pgflow_temp_add_extensions.sql h1:IBHG1vBdXu8wDEJzqpJUFmuPhVaX0mAmDUkngLgdaMg=
2121
20251205133446_pgflow_temp_ensure_workers.sql h1:EQzE75uaMSXeU1sdjO7MK1ipCwepxlWSVzlKegLpr48=
22+
20251205140756_pgflow_temp_cleanup_ensure_workers_logs.sql h1:wNsRFg6bZKwItg3qdNx/dP8zaK4Qe7ufOZwxO+yx/F8=
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
-- Test: cleanup_ensure_workers_logs() deletes old entries and returns correct count
2+
begin;
3+
select plan(3);
4+
select pgflow_tests.reset_db();
5+
6+
-- Clear existing cron job run details
7+
delete from cron.job_run_details;
8+
9+
-- Setup: Create job run details at different ages (testing 4h custom retention)
10+
insert into cron.job_run_details (runid, jobid, command, status, end_time)
11+
values
12+
(1, 1, 'select some_function()', 'succeeded', now() - interval '5 hours'), -- Should be deleted
13+
(2, 1, 'select some_function()', 'succeeded', now() - interval '6 hours'), -- Should be deleted
14+
(3, 1, 'select some_function()', 'succeeded', now() - interval '3 hours'), -- Should be kept
15+
(4, 1, 'select some_function()', 'succeeded', now() - interval '1 hour'); -- Should be kept
16+
17+
-- Execute cleanup with 4 hour retention
18+
with result as (
19+
select * from pgflow.cleanup_ensure_workers_logs(retention_hours => 4)
20+
)
21+
select is(
22+
(select cron_deleted from result),
23+
2::bigint,
24+
'Should return count of 2 deleted entries'
25+
);
26+
27+
-- Test: Old entries were deleted
28+
select is(
29+
(select count(*) from cron.job_run_details where runid in (1, 2)),
30+
0::bigint,
31+
'Entries older than retention should be deleted'
32+
);
33+
34+
-- Test: Recent entries were kept
35+
select is(
36+
(select count(*) from cron.job_run_details where runid in (3, 4)),
37+
2::bigint,
38+
'Entries newer than retention should be kept'
39+
);
40+
41+
select finish();
42+
rollback;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
-- Test: cleanup_ensure_workers_logs() returns 0 when no old entries exist
2+
begin;
3+
select plan(1);
4+
select pgflow_tests.reset_db();
5+
6+
-- Clear existing cron job run details
7+
delete from cron.job_run_details;
8+
9+
-- Setup: Only recent entries exist
10+
insert into cron.job_run_details (runid, jobid, command, status, end_time)
11+
values
12+
(1, 1, 'select some_function()', 'succeeded', now() - interval '1 hour'),
13+
(2, 1, 'select some_function()', 'succeeded', now() - interval '2 hours');
14+
15+
-- Execute cleanup - nothing should be deleted
16+
with result as (
17+
select * from pgflow.cleanup_ensure_workers_logs()
18+
)
19+
select is(
20+
(select cron_deleted from result),
21+
0::bigint,
22+
'Should return 0 when no entries exceed retention period'
23+
);
24+
25+
select finish();
26+
rollback;

0 commit comments

Comments
 (0)