every second cron doesn't trigger `tick` but `time_until_next` returns 0
Closed this issue · 3 comments
libcron::Cron<> cron;
cron.add_schedule("Test 1", "* * * * * ?", [](auto&& a) {
if (a.get_delay() > std::chrono::seconds{1}) {
std::cout << "Late launch " << a.get_delay().count() << std::endl;
}
std::cout << "SECONDS" << std::endl;
return;
});
while (true) {
cron.tick();
std::cout << '.';
std::this_thread::sleep_for(cron.time_until_next());
}
With this code thread will sleep for 0 seconds around 100k+ times, then it triggers the task, then time_until_next
returns almost perfect 1s
.
I expected it to always return a valid time that can be used for sleep_for
function, but something is wrong and I suspect tick
, because time_until_next
is pretty straightforward.
The code above can be fixed by adding a check:
cron.tick();
auto&& sleep_for = cron.time_until_next();
if (sleep_for == std::chrono::seconds{0}) {
sleep_for = std::chrono::seconds{1};
}
std::this_thread::sleep_for(sleep_for);
But this prints that task is late (Example: Late launch 1001189130
). So adding delay of 1 second tells me I missed previous second.
What's interesting, calling time_until_next
then tick
fixes that problem. (but only for every second schedule)
Perhaps, next_schedule_time
method could solve this by returning task.next_schedule
value. It can be used in std::this_thread::sleep_until
cron.time_until_next()
will return 0 as long as a task is due for the current second, it was not designed to be used as you do. I can see why you'd want to use it like this though, but it is working as intended.
as long as a task is due for the current second
If it's due for the current second, why .tick() doesn't process it? Or it's arbitrary?
Tasks are only updated once at least a second has passed which is why things work the way they do.
https://github.com/PerMalmberg/libcron/blob/master/libcron%2Finclude%2Flibcron%2FCron.h#L196