scheddy 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f3ff142fb2059d543a17e05efa0e607e1a762419a1e14bd6c79c82eb4806872
4
- data.tar.gz: a3a1a9a1975148811f85bdc36a92df7d83bada860e2ca9ad7a1f06eabacac40e
3
+ metadata.gz: 86885e07595c5cc31d8a5963684a2618de1505986399fd93e0f54f6ff248bbac
4
+ data.tar.gz: 409a482e3d28dbdda1f2ec48e06ed7a52ff020e961ce89b89aef976698e9e400
5
5
  SHA512:
6
- metadata.gz: 95d9325b4fa7985dc777b0d722a0a4b5a81ac13a382e0d73e1547c16182442d6f5a073bd17f16d81332876f85c344e2a4180108546fee39f383fcd3dd8d3b03b
7
- data.tar.gz: 16cff8b03fc9d4c608f61d41db7d624e532e4e77d92d1e9bb6233c0603b627f38ad2964a5fee39dd4a136679f0b7f38bf1ba34708f1f70925f872ca5596fc54f
6
+ metadata.gz: fa861cb109163a3a86e8b327436441ed4f4f4dbee4b95d1ea605f67500b91110465aded2062b00934d1621211625665f735f07d5a9f8c14d0b8d0d9a9800f560
7
+ data.tar.gz: 33acabd55cc1ecce55ec9cd0a30e547dad4570d19414382839a02510e6d7543b2d12f5b136aa9951550dbf96a0b7bb7b3085ed974cd5b41e1f157380f642ded1
data/README.md CHANGED
@@ -6,7 +6,7 @@ Scheddy is a batteries-included task scheduler for Rails. It is intended as a re
6
6
  * Tiny intervals are great for scheduling workload specific jobs (database field `next_run_at`).
7
7
  * Catch up missed tasks. Designed for environments with frequent deploys. Also useful in dev where the scheduler isn't always running.
8
8
  * Job-queue agnostic. Works great with various ActiveJob adapters and non-ActiveJob queues too.
9
- * Minimal dependencies. Uses your existing database; doesn't require Redis.
9
+ * Minimal dependencies. Uses your existing database (or no database at all). Redis not required either.
10
10
  * Tasks and their schedules are versioned as part of your code.
11
11
 
12
12
 
@@ -72,7 +72,7 @@ Scheddy.config do
72
72
  # track_runs false # when run_every is >= 15.minutes, defaults to true; else to false
73
73
  perform do
74
74
  User.where(welcome_email_at: nil).find_each(batch_size: 100) do |user|
75
- WelcomeMailer.welcome_email.with(user: user).deliver_later
75
+ WelcomeMailer.with(user: user).welcome_email.deliver_later
76
76
  end
77
77
  end
78
78
  end
@@ -136,7 +136,7 @@ A given task will only ever be executed once at a time. Mostly relevant when usi
136
136
 
137
137
  Tasks may receive an optional context to check if they need to stop for pending shutdown or to know the deadline for completing work before the next cycle would begin.
138
138
 
139
- Deadlines (`finish_before`) are mostly useful if there is occasionally a large block of work combined with tiny intervals. The deadline is calculated with a near 2 second buffer. Only if that's inadequate do you need to adjust further. As already mentioned, Scheddy is smart enough to skip the next cycle if the prior cycle is still running, so handling deadlines is entirely optional.
139
+ Deadlines (`finish_before`) are mostly useful if there is occasionally a large block of work combined with tiny intervals. It may be necessary to calculate your own buffer when comparing against `finish_before` (1 second is shown below). As already mentioned, Scheddy is smart enough to skip the next cycle if the prior cycle is still running, so handling deadlines is entirely optional.
140
140
 
141
141
  ```ruby
142
142
  task 'iterating task' do
@@ -145,7 +145,7 @@ task 'iterating task' do
145
145
  Model.where(...).find_each do |model|
146
146
  SomeJob.perform_later model.id if model.run_job?
147
147
  break if context.stop? # the scheduler has requested to shutdown
148
- break if context.finish_before < Time.now # the next cycle is imminent
148
+ break if context.finish_before < 1.second.from_now # the next cycle is imminent
149
149
  end
150
150
  end
151
151
  end
@@ -1,5 +1,10 @@
1
1
  module Scheddy
2
- class ApplicationRecord < ActiveRecord::Base
3
- self.abstract_class = true
2
+ if defined?(ActiveRecord::Base)
3
+ class ApplicationRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+ end
6
+ else
7
+ class ApplicationRecord
8
+ end
4
9
  end
5
10
  end
data/lib/scheddy/cli.rb CHANGED
@@ -38,6 +38,12 @@ module Scheddy
38
38
  end
39
39
 
40
40
 
41
+ desc :version, 'Show version'
42
+ def version
43
+ puts "Scheddy v#{Scheddy::VERSION}"
44
+ end
45
+
46
+
41
47
  no_commands do
42
48
 
43
49
  def load_app!
@@ -1,9 +1,9 @@
1
1
  module Scheddy
2
2
  class Context
3
3
 
4
- def initialize(scheduler, finish_before)
4
+ def initialize(scheduler, task)
5
5
  @scheduler = scheduler
6
- @finish_before = finish_before
6
+ @finish_before = task.finish_before
7
7
  end
8
8
 
9
9
  delegate :stop?, to: :@scheduler
@@ -19,7 +19,7 @@ module Scheddy
19
19
  running = tasks.select(&:running?).count
20
20
  if running > 0
21
21
  puts "[Scheddy] Waiting for #{running} tasks to complete"
22
- wait_until(45.seconds.from_now) do
22
+ wait_until(45.seconds.from_now, skip_stop: true) do
23
23
  tasks.none?(&:running?)
24
24
  end
25
25
  tasks.select(&:running?).each do |task|
@@ -73,9 +73,9 @@ module Scheddy
73
73
  end
74
74
 
75
75
  # &block - optional block - return truthy to end prematurely
76
- def wait_until(time)
76
+ def wait_until(time, skip_stop: false)
77
77
  while (now = Time.current) < time
78
- return if stop?
78
+ return if stop? && !skip_stop
79
79
  return if block_given? && yield
80
80
  sleep [time-now, 1].min
81
81
  end
data/lib/scheddy/task.rb CHANGED
@@ -12,12 +12,16 @@ module Scheddy
12
12
  logger.error "Scheddy task '#{name}' already running; skipping this cycle"
13
13
  return next_cycle!
14
14
  end
15
- context = Context.new(scheduler, finish_before)
15
+ context = Context.new(scheduler, self)
16
16
  self.thread =
17
17
  Thread.new do
18
18
  logger.tagged tag do
19
19
  Rails.application.reloader.wrap do
20
- task.call(*[context].take(task.arity.abs))
20
+ if context.finish_before < Time.current
21
+ logger.info "Rails dev-mode reloader locked for entire task interval; skipping this run"
22
+ else
23
+ task.call(*[context].take(task.arity.abs))
24
+ end
21
25
  rescue Exception => e
22
26
  if h = Scheddy.error_handler
23
27
  h.call(*[e, self].take(h.arity.abs))
@@ -28,6 +32,12 @@ module Scheddy
28
32
  self.thread = nil
29
33
  end
30
34
  next_cycle!
35
+ rescue Exception => e
36
+ logger.error "Scheddy: error scheduling task '#{name}'; retrying in 5 seconds"
37
+ if h = Scheddy.error_handler
38
+ h.call(*[e, self].take(h.arity.abs))
39
+ end
40
+ return self.next_cycle = 5.seconds.from_now
31
41
  end
32
42
 
33
43
  def kill
@@ -55,7 +65,7 @@ module Scheddy
55
65
  }
56
66
  case type
57
67
  when :interval
58
- attrs[:initial_delay] = ActiveSupport::Duration.build(delay) unless track_runs
68
+ attrs[:initial_delay] = ActiveSupport::Duration.build(delay) unless track_runs && last_run
59
69
  attrs[:interval] = ActiveSupport::Duration.build(interval)
60
70
  when :cron
61
71
  attrs[:cron] = cron.original
@@ -129,14 +139,15 @@ module Scheddy
129
139
  end
130
140
  end
131
141
 
132
- def finish_before
142
+ def finish_before(grace: 0.1.seconds)
133
143
  case type
134
144
  when :interval
135
- Time.current + interval - 2.seconds
145
+ Time.current + interval - grace
136
146
  when :cron
137
- cron.next_time.to_utc_time - 2.seconds
147
+ cron.next_time.to_utc_time - grace
138
148
  end
139
149
  end
150
+ public :finish_before
140
151
 
141
152
 
142
153
  def last_run
@@ -1,3 +1,3 @@
1
1
  module Scheddy
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scheddy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - thomas morgan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-08 00:00:00.000000000 Z
11
+ date: 2023-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fugit
@@ -85,6 +85,7 @@ licenses:
85
85
  metadata:
86
86
  homepage_uri: https://github.com/zarqman/scheddy
87
87
  source_code_uri: https://github.com/zarqman/scheddy
88
+ changelog_uri: https://github.com/zarqman/scheddy/blob/master/CHANGELOG.md
88
89
  post_install_message:
89
90
  rdoc_options: []
90
91
  require_paths: