Skip to content

Commit

Permalink
Add from: parameter to Mel::Job::On#run_on methods
Browse files Browse the repository at this point in the history
This is used to specify the time relative to which the first run
occurs.
  • Loading branch information
akadusei committed Dec 6, 2023
1 parent 65f907f commit 2214d23
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Changed
- Add `from:` parameter to `Mel::Job::Every#run_every` methods
- Add `from:` parameter to `Mel::Job::On#run_on` methods

## [0.17.2] - 2023-12-04

Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,14 @@ This makes *Redis* the *source of truth* for schedules, allowing to easily scale
DoSomeWork.run_on("0 */2 * * *", for: 6.hours, arg_1: 5, arg_2: "value")
```

This will do the first run relative to now. For instance, if the time now is 03:00, the first run would be at 04:00, the next run at 06:00, and so on. If you would like to do the first run relative to some other time, specify that in a `from:` argument:

```crystal
# ->>> src/app/some_file.cr
DoSomeWork.run_on("0 */2 * * *", from: 3.days.from_now, for: 6.hours, arg_1: 5, arg_2: "value")
```

Instead of `for:`, you may use `till:` and specify a `Time`. Leave those out to run forever.

The `DoSomeWork.run_*` methods accept the following additional arguments:
Expand Down
27 changes: 26 additions & 1 deletion spec/mel/job/on_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ describe Mel::Job::On do
address = "user@domain.tld"
id = "1001"
schedule = "0 */2 * * *"

cron = CronParser.new(schedule)

SendEmailOnJob.run_on(schedule, id: id, address: address)
Expand Down Expand Up @@ -43,6 +42,32 @@ describe Mel::Job::On do
Mel::CronTask.find(id).should be_a(Mel::CronTask)
end

it "starts at specified time" do
address = "user@domain.tld"
id = "1001"
schedule = "0 */2 * * *"
cron = CronParser.new(schedule)

SendEmailOnJob.run_on(
schedule,
id: id,
from: 10.days.from_now,
address: address
)

Time::Location.local = Time::Location.load("Europe/Berlin")

Timecop.travel(cron.next(6.days.from_now)) do
task = Mel::CronTask.find(id)
task.try(&.due?).should be_false
end

Timecop.travel(cron.next(10.days.from_now)) do
task = Mel::CronTask.find(id)
task.try(&.due?).should be_true
end
end

it "deletes task after given time" do
address = "user@domain.tld"
id = "1001"
Expand Down
6 changes: 4 additions & 2 deletions src/mel/job/on.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,29 @@ module Mel::Job::On
def self.run_on(
schedule : String,
for : Time::Span,
from : Time = Time.local,
id = UUID.random.hexstring,
retries = nil,
redis = nil,
force = false,
**job_args
)
till = for.from_now
run_on(schedule, till, id, retries, redis, force, **job_args)
run_on(schedule, till, from, id, retries, redis, force, **job_args)
end

def self.run_on(
schedule : String,
till : Time? = nil,
from : Time = Time.local,
id = UUID.random.hexstring,
retries = nil,
redis = nil,
force = false,
**job_args
) : String?
time = CronParser.new(schedule).next(from)
job = new(**job_args)
time = CronParser.new(schedule).next
task = Mel::CronTask.new(id.to_s, job, time, retries, till, schedule)

task.id if task.enqueue(redis, force: force)
Expand Down

0 comments on commit 2214d23

Please sign in to comment.