hugoabonizio / schedule.cr

:clock3: Run periodic tasks in Crystal

Home Page:https://hugoabonizio.github.io/schedule.cr/Schedule.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

schedule tasks based on the clock like cron

coderhs opened this issue · comments

I would very much like to see these features in this project, as I am building a custom scheduler to replace cron bases scheduling in our rails application and I feel crystal with schedule.cr would be the best fit to build the tool.

In cron we can schedule task like run every hour, every 5 minutes. These task run at the start of the hours and every 5 minute based on clock, which makes the system more predictable. So If its set to run every hour, I know that it supposes to run at 1 PM (the start of next hour) and not 1 hour from now. So I propose we add a new method so that we can schedule task based on the clock.

run_every(1, :hour), run_every(5, :minute) - which runs based on the clock.

If this enhancement is fine, then I will add this feature to this library and send a PR.

Hi @coderhs!

This feature is similar to the one requested on #3 and I would appreciate very much a PR 😄

I want to discuss the API first. I liked the method suggested on the former issue (based on whenever gem), thus we could have the following:

every :hour do
  # something that is triggered at 06:00, 07:00, 08:00...
end

every :sunday, at: "14:40:00" do
  # something that is triggered on sundays at 14:40:00...
end

every :hour, at: ["05:00", "10:00", "15:00"] do
  # something that is triggered every hour at the given minutes
end

I'm thinking how to implement this and probably we need to start scheduling the task to the next event (sleep(next - Time.now)) and then rescheduling after each executed task. To calculate the events based on clock we can use Crystal's methods at_end_of_*. Did you think in a better way?

This is a relatively big enhacement, given the simplicity of this shard, and we can start with baby steps, maybe implementing a way to use every :hour for example.

Does this fits in your use case or did I understand wrong?

Yes, thats what I meant. I will create a PR for every(:hour) and we will start with baby steps. I feel like, I should overload the existing every method, to a new method and have our logic there.

Or we create a new interval method, which accepts all the arguments and then make a decision on when the next job is to be executed. In which case I feel we can support all the above types.

So I agree with your suggestion of baby step, I will send a PR soon for the every(:hour)

You can overload the method like below and write your logic there (make use of private methods as you wish).

def self.every(interval : Symbol, &block)

For the specs I suggest to take a look at timecop.cr shard, which can help with Time mocking, or use any other way you think is better.

Thanks @coderhs 😃

This seems to be a better timecop library. https://github.com/TobiasGSmollett/timecop.cr as it allows travel.