Skip to content
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

Add possibility to schedule jobs by interval in seconds #235

Merged
merged 2 commits into from Feb 7, 2023

Conversation

marcocitus
Copy link
Member

@marcocitus marcocitus commented Feb 4, 2023

By popular demand, fixes #6.

Extends the schedule syntax to allow defining jobs based on an interval in seconds that starts when pg_cron learns about the job, shortly after scheduling or server boot. The interval is measured from the start of the last run. If a run takes longer than the interval, the next run starts immediately after, which resets the interval timer.

We opted to define a job purely based on an interval because adding another part to the cron schedule would make the schedule hard to read, incompatible with typical crontab tools, and the level of control over when in the week the "per x second" job happens seems unnecessary. Moreover, we usually cannot guarantee when a job happens down to the second on busy servers, so we'll make no attempt to do so.

Syntax is as follows, inspired by interval syntax, but only positive whole seconds are supported.

SELECT cron.schedule('check-news', '5 seconds', 'SELECT check_news()');

src/job_metadata.c Outdated Show resolved Hide resolved
src/pg_cron.c Show resolved Hide resolved
sql/pg_cron-test.sql Show resolved Hide resolved
src/job_metadata.c Outdated Show resolved Hide resolved
@marcocitus
Copy link
Member Author

Thanks for the review!

expected/pg_cron-test.out Show resolved Hide resolved
Base automatically changed from marcocitus/fix-job-name to main February 5, 2023 14:01
@mulander
Copy link

mulander commented Feb 5, 2023

I like the options but having thoughts on the interface for setting the interval. Currently we re-implement parsing seconds supporting syntax like 5 seconds and suggesting to users that this is an interval. I think that is a nice idea to leverage how intervals work and peoples familiarity with it but taking it a step further could be better and actually simplify how it works and reduce cases where people get surprised (ie. '3s' and '3 sec' are both valid intervals). In PG you can overload functions, so add cron.schedule taking text (cron definition) and cron.schedule taking actual interval.

postgres=# \df
                       List of functions
 Schema | Name | Result data type | Argument data types | Type
--------+------+------------------+---------------------+------
 public | test | void             | p_schedule interval | func
 public | test | void             | p_schedule text     | func
(2 rows)
postgres=# select test('* * * *');
NOTICE:  Text with * * * *
 test
------
(1 row)
postgres=# select test('1 s'::interval);
NOTICE:  Interval with 00:00:01
 test
------
(1 row)

This way users can have the parsing be done by PostgreSQL, and you can simply discard out of range intervals.

Alternatively you could take it further and try to support casting INTERVAL to a cron schedule where possible. This way you could allow using the interval syntax to define jobs that happen every N days, hours, minutes and convert that to their cron counterparts.

So that '2 hours'::interval could become 0 */2 * * *. The only problem is that cron has no representation for something running in second intervals so it doesn't have a nice mapping.

@marcocitus marcocitus merged commit 71642fd into main Feb 7, 2023
@marcocitus marcocitus deleted the marcocitus/jobs-in-seconds branch February 7, 2023 08:52
Copy link

@webern webern left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool 🎉

@elahrvivaz
Copy link

elahrvivaz commented Feb 9, 2023

I think this change broke some valid cron syntax, such as 9,19,29,39,49,59 * * * *. This is now being interpreted as running every 9 seconds.

@marcocitus
Copy link
Member Author

Hmz, that's bad. I'll look into it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a way to run a job every x seconds
6 participants