ruby-clock 2.0.0.beta2 → 2.0.0.beta4

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: 9fdfa3656f0ffbdf60b162a594809e29e9f0579cf3f5f52e98ffd857a811c348
4
- data.tar.gz: f63dd579f2cd258f89f17666338ec9d433a63e2b93d0a400975ee6c1e61886fa
3
+ metadata.gz: 8900519602f68a1eb7e0a5b49aa1752c5a42ffb65a16b409b8f12c003237c568
4
+ data.tar.gz: bb9d30d35bafa38b970f061faa0416bffb66197f5fddd5d46a691c05e04fe82b
5
5
  SHA512:
6
- metadata.gz: 938ec658ba3837be8a90c49fdd8d2d6a050b1b6a19486bc2b10479e81370ed3fe5c0e4501293b02a2c8efcfe82d67974e887c2069270986f3398b89762c04707
7
- data.tar.gz: c3376b79456a66c2b3c1eb5492b9a0429e69ece7b5207a73d2792c8830c33355c14dc622c2a37e8b6b8e2b9b27cdaaa4d0c83449e6e9c8aca3ae2538e2a90af0
6
+ metadata.gz: 50482fd2178c9098bd8e2eb1218f56c56596d5983d82571246d5516cd977227a344598f056019027f2b97222ffc8a628eed503ed2d10defea116bfe5d6b953f1
7
+ data.tar.gz: 5eb78d5f6dffb1d09d09e9d1ada59a0bae9646253f789affec38311237b74b937192b1f7a414b2a5ff3e8fc2b34a3beb6fe1e8fda8a6aeffedfac80941e8a5a5
data/CHANGELOG.md CHANGED
@@ -1,15 +1,34 @@
1
1
  ## 2.0.0 beta
2
2
 
3
+ ### Features
3
4
  * The way the [rails app reloader](https://guides.rubyonrails.org/threading_and_code_execution.html)
4
5
  is implemented is now compatible with both rails 6 and 7
5
- * The setup for rails is now less complicated
6
6
  * RUBY_CLOCK_SHUTDOWN_WAIT_SECONDS value is logged when starting
7
- * Code reorganization so there are no unnecessary methods in top-level Kernel namespace
8
7
  * DSL methods are now at the top-level namespace (`schedule.every` → `every`, `schedule.cron` → `cron`)
9
- * error handler definition is now at the top-level namespace (`def schedule.on_error` → `on_error do`)
8
+ * Error handler definition is now at the top-level namespace (`def schedule.on_error` → `on_error do`)
9
+ * Around callbacks now have a top-level namespace method. `def schedule.around_trigger` → `around_action` - see readme
10
+ * Multiple around callbacks can be consecutively assigned - no need to put all behavior into one action
11
+ * Errors encountered when loading Clockfile (such as incorrect cron syntaxt)
12
+ will be reported to the error handler
13
+
14
+ ### Anti-Features
15
+ * rake and shell runners are no longer top-level (`shell` → `RubyClock::Runners.shell`, `rake` → `RubyClock::Runners.rake`)
16
+
17
+ ### Code Improvements
18
+ * The code which implements the rails reloader/executor is now less complicated
19
+ * Code reorganization so there are no unnecessary methods in top-level Kernel namespace
20
+
10
21
 
11
22
  ### Migrating from ruby-clock version 1 to version 2
12
23
 
24
+ * The top of every Clockfile must begin with `using RubyClock::DSL`
25
+ * rake and shell runners must be invoked like so: `RubyClock::Runners.rake`, `RubyClock::Runners.shell`, etc.
26
+ * If you have an existing `def schedule.around_trigger`, you will need to change it to use the new
27
+ `around_action` method. Failure to change this will silently appear to keep working,
28
+ but will break the rails reloader/executor implementation.
29
+ * Your existing Clockfile will still work, but you now have the option to use
30
+ `every`, `cron`, and `on_error` at the top-level, without referencing `schedule`.
31
+ See the readme for examples.
13
32
  * There is no longer a need to have a binstub in rails. You can delete bin/clock from your app.
14
33
  * The invocations (in Procfile, or wherever else you start ruby-clock) should change from
15
34
 
@@ -17,9 +36,6 @@
17
36
  to
18
37
 
19
38
  bundle exec clock
20
- * Your existing Clockfile will still work, but you now have the option to use
21
- `every`, `cron`, and `on_error` at the top-level, without referencing `schedule`.
22
- See the readme for examples.
23
39
 
24
40
  ## 1.0.0
25
41
 
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- THESE ARE THE DOCS FOR VERSION 2.0.0.beta2
1
+ THESE ARE THE DOCS FOR VERSION 2.0.0.beta
2
2
 
3
3
  See version 1 docs here: https://github.com/jjb/ruby-clock/tree/v1.0.0
4
4
 
@@ -50,6 +50,8 @@ Create a file named Clockfile. This will hold your job definitions.
50
50
  Define jobs like this:
51
51
 
52
52
  ```ruby
53
+ using RubyClock::DSL
54
+
53
55
  every('5 minutes') do
54
56
  UserDataReports.generate
55
57
  end
@@ -90,9 +92,9 @@ You may wish to
90
92
  for your jobs. You can do so with the around trigger:
91
93
 
92
94
  ```ruby
93
- def schedule.around_trigger(job)
95
+ around_action(job_proc)
94
96
  ActiveRecord::Base.uncached do
95
- yield
97
+ job_proc.call
96
98
  end
97
99
  end
98
100
  ```
@@ -142,17 +144,59 @@ add `$stdout.sync = true` to the top of your Clockfile.
142
144
  ### Error Handling
143
145
 
144
146
  You can catch and report errors raised in your jobs by defining an error catcher at
145
- the top of your Clockfile like this:
147
+ the top of your Clockfile like this. You should handle these two cases so that you can get
148
+ error reports about problems while loading the Clockfile:
146
149
 
147
150
  ```ruby
148
151
  on_error do |job, error|
149
- ErrorReporter.track_exception(error)
152
+ case job
153
+ when String # this means there was a problem parsing the Clockfile while starting
154
+ ErrorReporter.track_exception(error, tag: 'clock', severity: 'high')
155
+ else
156
+ ErrorReporter.track_exception(error, tag: 'clock', custom_attribute: {job_name: job.identifier})
157
+ end
150
158
  end
151
159
  ```
152
160
 
153
161
  ### Callbacks
154
162
 
155
- You can define before, after, and around callbacks which will run for all jobs.
163
+ You can define around callbacks which will run for all jobs, like shown below.
164
+ This somewhat awkward syntax is necessary in order to enable the ability to define multiple callbacks.
165
+ (perhaps in different files, shared by multiple Clockfiles, etc.).
166
+
167
+ ```ruby
168
+ around_action do |job_proc, job_info|
169
+ puts "before1 #{job_info.class}"
170
+ job_proc.call
171
+ puts "after1"
172
+ end
173
+
174
+ around_action do |job_proc|
175
+ puts "before2"
176
+ job_proc.call
177
+ puts "after2"
178
+ end
179
+
180
+ every('2 seconds') do
181
+ puts "hello from a ruby-clock job"
182
+ end
183
+ ```
184
+
185
+
186
+ ```
187
+ before1 Rufus::Scheduler::EveryJob
188
+ before2
189
+ hello from a ruby-clock job
190
+ after2
191
+ after1
192
+ ```
193
+
194
+ The around callbacks code will be run in the individual job thread.
195
+
196
+ rufus-scheduler also provides before and after hooks. ruby-clock does not provide convenience methods for these
197
+ but you can easily use them via the `schedule` object. These will run in the outer scheduling thread and not in
198
+ the job thread, so they may have slightly different behavior in some cases. There is likely no reason to use them
199
+ instead of `around_action`.
156
200
  Read [the rufus-scheduler documentation](https://github.com/jmettraux/rufus-scheduler/#callbacks)
157
201
  to learn how to do this. Where the documentation references `s`, you should use `schedule`.
158
202
 
@@ -162,7 +206,7 @@ You can run shell commands in your jobs.
162
206
 
163
207
  ```ruby
164
208
  every '1 day' do
165
- shell('sh scripts/process_stuff.sh')
209
+ RubyClock::Runners.shell('sh scripts/process_stuff.sh')
166
210
  end
167
211
  ```
168
212
 
@@ -208,11 +252,12 @@ needing to shell out and start another process.
208
252
 
209
253
  ```ruby
210
254
  every '1 day' do
211
- rake('reports:daily')
255
+ RubyClock::Runners.rake('reports:daily')
212
256
  end
213
257
  ```
214
258
 
215
- There is also `rake_execute` and `rake_async`. See [the code](https://github.com/jjb/ruby-clock/blob/main/lib/ruby-clock.rb)
259
+ There is also `RubyClock::Runners.rake_execute` and `RubyClock::Runners.rake_async`.
260
+ See [the code](https://github.com/jjb/ruby-clock/blob/main/lib/rake.rb)
216
261
  and [this article](https://code.jjb.cc/running-rake-tasks-from-within-ruby-on-rails-code) for more info.
217
262
 
218
263
  ### Job Identifier
@@ -250,10 +295,12 @@ This can be used for keeping track of job behavior in logs or a
250
295
  stats tracker. For example:
251
296
 
252
297
  ```ruby
253
- def schedule.on_post_trigger(job, trigger_time)
298
+ around_action(job_proc, job_info)
299
+ trigger_time = Time.now
300
+ job_proc.call
254
301
  duration = Time.now-trigger_time.to_t
255
302
  StatsTracker.value('Clock: Job Execution Time', duration.round(2))
256
- StatsTracker.value("Clock: Job #{job.identifier} Execution Time", duration.round(2))
303
+ StatsTracker.value("Clock: Job #{job_info.identifier} Execution Time", duration.round(2))
257
304
  StatsTracker.increment('Clock: Job Executions')
258
305
  end
259
306
 
@@ -1,5 +1,28 @@
1
+ using RubyClock::DSL
2
+
1
3
  on_error do |job, error|
2
- raise error
4
+ case job
5
+ when String
6
+ puts "#{job}: #{error.class}: #{error.message}"
7
+ else
8
+ puts "An error has occurred with job #{job.identifier}: #{error.class}: #{error.message}"
9
+ end
10
+ end
11
+
12
+ # on_error do |job, error|
13
+ # raise error
14
+ # end
15
+
16
+ around_action do |job_proc, job_info|
17
+ puts "before1 #{job_info.class}"
18
+ job_proc.call
19
+ puts "after1"
20
+ end
21
+
22
+ around_action do |job_proc|
23
+ puts "before2"
24
+ job_proc.call
25
+ puts "after2"
3
26
  end
4
27
 
5
28
  every('2 seconds') do
@@ -7,9 +30,25 @@ every('2 seconds') do
7
30
  end
8
31
 
9
32
  every('2 seconds') do
10
- shell 'say hello'
33
+ RubyClock::Runners.shell 'say hello'
34
+ end
35
+
36
+ every('2 seconds') do
37
+ raise "🐈️ this error is expected, to test the error catcher"
11
38
  end
12
39
 
13
40
  cron('*/10 * * * * *') do
14
41
  puts "cron running on every 10th second #{Time.now}"
15
42
  end
43
+
44
+ every('2 seconds') do
45
+ if defined?(schedule)
46
+ raise "💥 we do not expect the ruby-clock DSL to be available inside a job, but it is"
47
+ end
48
+ end
49
+
50
+ every('2 seconds') do
51
+ if defined?(shell) || defined?(rake)
52
+ puts "💥 we do not expect runners to be available inside a job, but it is"
53
+ end
54
+ end
@@ -1,31 +1,32 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- ruby-clock (0.8.0.rc3)
4
+ ruby-clock (2.0.0.beta4)
5
5
  method_source
6
6
  rufus-scheduler (~> 3.8)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- concurrent-ruby (1.1.9)
12
- et-orbi (1.2.5)
11
+ concurrent-ruby (1.1.10)
12
+ et-orbi (1.2.7)
13
13
  tzinfo
14
- fugit (1.5.2)
15
- et-orbi (~> 1.1, >= 1.1.8)
14
+ fugit (1.7.1)
15
+ et-orbi (~> 1, >= 1.2.7)
16
16
  raabro (~> 1.4)
17
17
  method_source (1.0.0)
18
18
  raabro (1.4.0)
19
- rufus-scheduler (3.8.0)
19
+ rufus-scheduler (3.8.2)
20
20
  fugit (~> 1.1, >= 1.1.6)
21
- tzinfo (2.0.4)
21
+ tzinfo (2.0.5)
22
22
  concurrent-ruby (~> 1.0)
23
23
 
24
24
  PLATFORMS
25
25
  arm64-darwin-20
26
+ arm64-darwin-21
26
27
 
27
28
  DEPENDENCIES
28
29
  ruby-clock!
29
30
 
30
31
  BUNDLED WITH
31
- 2.2.28
32
+ 2.3.8
@@ -1,23 +1,19 @@
1
- on_error do |job, error|
2
- puts "An error has occurred: #{error.class}: #{error.message}"
3
- end
1
+ using RubyClock::DSL
4
2
 
5
- every('2 seconds') do
6
- puts "hello from a ruby-clock job"
7
- end
3
+ load '../example-app/Clockfile'
8
4
 
9
5
  every('2 seconds') do
10
- shell 'say hello'
6
+ puts Example.count
11
7
  end
12
8
 
13
9
  every('2 seconds') do
14
- puts Example.count
10
+ puts Example.check_for_global_method
15
11
  end
16
12
 
17
13
  every('2 seconds') do
18
- raise "An error."
14
+ puts Example.check_for_runner
19
15
  end
20
16
 
21
- cron('*/10 * * * * *') do
22
- puts "cron running on every 10th second #{Time.now}"
17
+ every('2 seconds') do
18
+ RubyClock::Runners.rake 'about'
23
19
  end
@@ -1,2 +1,18 @@
1
1
  class Example < ApplicationRecord
2
+ def self.check_for_global_method
3
+ if defined?(schedule)
4
+ raise "💥 Oh no, the ruby-clock DSL is in the global environment! 💥"
5
+ else
6
+ "🦝"
7
+ end
8
+ end
9
+
10
+ def self.check_for_runner
11
+ if defined?(shell) || defined?(rake)
12
+ raise "💥 Oh no, the runners got included in the global environment! 💥"
13
+ else
14
+ "🐅"
15
+ end
16
+ end
17
+
2
18
  end
data/exe/clock CHANGED
@@ -1,71 +1,22 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- begin
4
- require './config/environment.rb'
5
- puts "Detected rails app has been loaded."
6
- rescue LoadError
7
- end
8
-
9
3
  require 'ruby-clock'
10
- require 'method_source'
11
-
12
- class Rufus::Scheduler::Job
13
- def identifier
14
- @identifier ||= begin
15
- name || handler.source.split("\n").reject(&:empty?).grep_v(/#.*/)[-2].strip
16
- rescue
17
- begin
18
- source_location.join('-')
19
- rescue
20
- 'error-calculating-job-identifier'
21
- end
22
- end
23
- end
24
- end
25
-
4
+ RubyClock.detect_and_load_rails_app
5
+ require 'rufus_monkeypatch'
26
6
  RubyClock.instance.listen_to_signals
27
7
  RubyClock.instance.prepare_rake
28
8
  RubyClock.instance.schedule.pause
9
+ RubyClock.instance.add_rails_executor_to_around_actions
29
10
 
30
-
31
-
32
- ## Add methods to top-level namespace
33
- def schedule
34
- RubyClock.instance.schedule
35
- end
36
-
37
- def on_error(&on_error_block)
38
- RubyClock.instance.on_error = on_error_block
39
- def schedule.on_error(job, error)
40
- RubyClock.instance.on_error.call(job, error)
11
+ begin
12
+ load ARGV[0] || 'Clockfile'
13
+ rescue => clockfile_error
14
+ if RubyClock.instance.on_error
15
+ RubyClock.instance.on_error.call("An error has occured while parsing the clockfile", clockfile_error)
41
16
  end
42
- end
43
-
44
- def cron(...)
45
- RubyClock.instance.schedule.cron(...)
46
- end
47
-
48
- def every(...)
49
- RubyClock.instance.schedule.every(...)
50
- end
51
17
 
52
- def shell(string)
53
- RubyClock.instance.shell(string)
54
- end
55
- #####################################
56
-
57
-
58
- load ARGV[0] || 'Clockfile'
59
-
60
- if defined?(::Rails)
61
- schedule.instance_eval do
62
- @old_around_trigger = method :around_trigger
63
- def around_trigger(job)
64
- ::Rails.application.reloader.wrap do
65
- @old_around_trigger.call(job){ yield }
66
- end
67
- end
68
- end
18
+ raise
69
19
  end
70
20
 
21
+ RubyClock.instance.freeze_around_actions
71
22
  RubyClock.instance.run_jobs
@@ -0,0 +1,33 @@
1
+ module RubyClock::AroundActions
2
+
3
+ attr_accessor :around_actions
4
+
5
+ def freeze_around_actions
6
+ @around_actions.freeze
7
+ end
8
+
9
+ def set_up_around_actions
10
+ @around_actions = []
11
+ def schedule.around_trigger(job_info, &job_proc)
12
+ RubyClock.instance.call_with_around_action_stack(
13
+ RubyClock.instance.around_actions.reverse,
14
+ job_proc,
15
+ job_info
16
+ )
17
+ end
18
+ end
19
+
20
+ def call_with_around_action_stack(wrappers, job_proc, job_info)
21
+ case wrappers.count
22
+ when 0
23
+ job_proc.call(job_info)
24
+ else
25
+ call_with_around_action_stack(
26
+ wrappers[1..],
27
+ Proc.new{ wrappers.first.call(job_proc, job_info) },
28
+ job_info
29
+ )
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,26 @@
1
+ module RubyClock::DSL
2
+ refine ::Kernel do
3
+ def schedule
4
+ RubyClock.instance.schedule
5
+ end
6
+
7
+ def on_error(&on_error_block)
8
+ RubyClock.instance.on_error = on_error_block
9
+ def schedule.on_error(job, error)
10
+ RubyClock.instance.on_error.call(job, error)
11
+ end
12
+ end
13
+
14
+ def around_action(&b)
15
+ RubyClock.instance.around_actions << b
16
+ end
17
+
18
+ def cron(...)
19
+ RubyClock.instance.schedule.cron(...)
20
+ end
21
+
22
+ def every(...)
23
+ RubyClock.instance.schedule.every(...)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ # There is also rails-relevant code in rake.rb
2
+ module RubyClock::Rails
3
+ module ClassMethods
4
+ def detect_and_load_rails_app
5
+ begin
6
+ require './config/environment.rb'
7
+ puts "Detected rails app has been loaded."
8
+ rescue LoadError
9
+ end
10
+ end
11
+ end
12
+
13
+ module InstanceMethods
14
+ def add_rails_executor_to_around_actions
15
+ if defined?(::Rails)
16
+ RubyClock.instance.around_actions << Proc.new do |job_proc|
17
+ ::Rails.application.executor.wrap do
18
+ job_proc.call
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,37 @@
1
+ # See https://code.jjb.cc/running-rake-tasks-from-within-ruby-on-rails-code
2
+ module RubyClock::Rake
3
+ def prepare_rake
4
+ if defined?(::Rails) && Rails.application
5
+ Rails.application.load_tasks
6
+ Rake::Task.tasks.each{|t| t.prerequisites.delete 'environment' }
7
+ @rake_mutex = Mutex.new
8
+ else
9
+ puts <<~MESSAGE
10
+ Because this is not a rails application, we do not know how to load your
11
+ rake tasks. You can do this yourself at the top of your Clockfile if you want
12
+ to run rake tasks from ruby-clock.
13
+ MESSAGE
14
+ end
15
+ end
16
+
17
+ # for tasks that don't have dependencies
18
+ def rake_execute(task)
19
+ Rake::Task[task].execute
20
+ end
21
+
22
+ # If the task doesn't share dependencies with another task,
23
+ # or if it does and you know you'll never run tasks such that any overlap
24
+ def rake_async(task)
25
+ Rake::Task[task].invoke
26
+ ensure
27
+ Rake::Task[task].reenable
28
+ Rake::Task[task].all_prerequisite_tasks.each(&:reenable)
29
+ end
30
+
31
+ # If the task has shared dependencies and you might run more than one at the same time
32
+ # This is the safest option and hence the default.
33
+ def rake(task)
34
+ @rake_mutex.synchronize { rake_async(task) }
35
+ end
36
+
37
+ end
@@ -0,0 +1,23 @@
1
+ # if we ever want to make these available at the top-level using refinements,
2
+ # like we do with the DSL, it doesn't work in Rails because Rails prepends Kernel after
3
+ # we use the refinment. Initial tests show that prepending ActiveSupport::ForkTracker::CoreExtPrivate
4
+ # works, but maybe that's not reliable or has unknown side effects
5
+ # https://stackoverflow.com/questions/74119178/
6
+
7
+ module RubyClock::Runners
8
+ def self.shell(string)
9
+ RubyClock.instance.shell(string)
10
+ end
11
+
12
+ def self.rake(string)
13
+ RubyClock.instance.rake(string)
14
+ end
15
+
16
+ def self.rake_execute(string)
17
+ RubyClock.instance.rake_execute(string)
18
+ end
19
+
20
+ def self.rake_async(string)
21
+ RubyClock.instance.rake_async(string)
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ module RubyClock::Shell
2
+ def shell_runner
3
+ @shell_runner ||= begin
4
+ require 'terrapin'
5
+ require 'posix-spawn'
6
+
7
+ unless Terrapin::CommandLine.runner.class == Terrapin::CommandLine::PosixRunner
8
+ puts <<~MESSAGE
9
+
10
+ 🤷 terrapin and posix-spawn are installed, but for some reason terrapin is
11
+ not using posix-spawn as its runner.
12
+
13
+ MESSAGE
14
+ end
15
+
16
+ puts '🐆 Using terrapin for shell commands.'
17
+ :terrapin
18
+ rescue LoadError
19
+ puts <<~MESSAGE
20
+
21
+ 🦥 Using ruby backticks for shell commands.
22
+ For better performance, install the terrapin and posix-spawn gems.
23
+ See README.md for more info.
24
+
25
+ MESSAGE
26
+ :backticks
27
+ end
28
+ end
29
+
30
+ def shell(command)
31
+ case shell_runner
32
+ when :terrapin
33
+ Terrapin::CommandLine.new(command).run
34
+ when :backticks
35
+ `#{command}`
36
+ end
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  class RubyClock
2
- VERSION = "2.0.0.beta2"
2
+ VERSION = "2.0.0.beta4"
3
3
  end
data/lib/ruby-clock.rb CHANGED
@@ -1,13 +1,28 @@
1
+ require "ruby-clock/dsl"
1
2
  require "ruby-clock/version"
3
+ require "ruby-clock/rake"
4
+ require "ruby-clock/shell"
5
+ require "ruby-clock/around_actions"
6
+ require "ruby-clock/dsl"
7
+ require "ruby-clock/runners"
8
+ require "ruby-clock/rails"
2
9
  require 'rufus-scheduler'
3
10
  require 'singleton'
4
11
 
5
12
  class RubyClock
6
-
7
13
  include Singleton
14
+ include RubyClock::Rails::InstanceMethods
15
+ extend RubyClock::Rails::ClassMethods
16
+ include RubyClock::Rake
17
+ include RubyClock::Shell
18
+ include RubyClock::AroundActions
8
19
 
9
20
  attr_accessor :on_error
10
21
 
22
+ def initialize
23
+ set_up_around_actions
24
+ end
25
+
11
26
  def wait_seconds
12
27
  ENV['RUBY_CLOCK_SHUTDOWN_WAIT_SECONDS']&.to_i || 29
13
28
  end
@@ -42,78 +57,4 @@ class RubyClock
42
57
  schedule.resume
43
58
  schedule.join
44
59
  end
45
-
46
- def prepare_rake
47
- if defined?(::Rails) && Rails.application
48
- Rails.application.load_tasks
49
- Rake::Task.tasks.each{|t| t.prerequisites.delete 'environment' }
50
- @rake_mutex = Mutex.new
51
- else
52
- puts <<~MESSAGE
53
- Because this is not a rails application, we do not know how to load your
54
- rake tasks. You can do this yourself at the top of your Clockfile if you want
55
- to run rake tasks from ruby-clock.
56
- MESSAGE
57
- end
58
- end
59
-
60
- # See https://code.jjb.cc/running-rake-tasks-from-within-ruby-on-rails-code
61
-
62
- # for tasks that don't have dependencies
63
- def rake_execute(task)
64
- Rake::Task[task].execute
65
- end
66
-
67
- # If the task doesn't share dependencies with another task,
68
- # or if it does and you know you'll never run tasks such that any overlap
69
- def rake_async(task)
70
- Rake::Task[task].invoke
71
- ensure
72
- Rake::Task[task].reenable
73
- Rake::Task[task].all_prerequisite_tasks.each(&:reenable)
74
- end
75
-
76
- # If the task has shared dependencies and you might run more than one at the same time
77
- # This is the safest option and hence the default.
78
- def rake(task)
79
- @rake_mutex.synchronize { rake_async(task) }
80
- end
81
-
82
- def shell_runner
83
- @shell_runner ||= begin
84
- require 'terrapin'
85
- require 'posix-spawn'
86
-
87
- unless Terrapin::CommandLine.runner.class == Terrapin::CommandLine::PosixRunner
88
- puts <<~MESSAGE
89
-
90
- 🤷 terrapin and posix-spawn are installed, but for some reason terrapin is
91
- not using posix-spawn as its runner.
92
-
93
- MESSAGE
94
- end
95
-
96
- puts '🐆 Using terrapin for shell commands.'
97
- :terrapin
98
- rescue LoadError
99
- puts <<~MESSAGE
100
-
101
- 🦥 Using ruby backticks for shell commands.
102
- For better performance, install the terrapin and posix-spawn gems.
103
- See README.md for more info.
104
-
105
- MESSAGE
106
- :backticks
107
- end
108
- end
109
-
110
- def shell(command)
111
- case shell_runner
112
- when :terrapin
113
- Terrapin::CommandLine.new(command).run
114
- when :backticks
115
- `#{command}`
116
- end
117
- end
118
-
119
60
  end
@@ -0,0 +1,14 @@
1
+ require 'method_source'
2
+ class Rufus::Scheduler::Job
3
+ def identifier
4
+ @identifier ||= begin
5
+ name || handler.source.split("\n").reject(&:empty?).grep_v(/#.*/)[-2].strip
6
+ rescue
7
+ begin
8
+ source_location.join('-')
9
+ rescue
10
+ 'error-calculating-job-identifier'
11
+ end
12
+ end
13
+ end
14
+ end
data/ruby-clock.gemspec CHANGED
@@ -6,8 +6,17 @@ Gem::Specification.new do |spec|
6
6
  spec.authors = ["John Bachir"]
7
7
  spec.email = ["j@jjb.cc"]
8
8
 
9
- spec.summary = 'A "clock" process for invoking ruby code within a persistent runtime'
9
+ spec.summary = 'A job scheduler which runs jobs each in their own thread in a persistent process.'
10
10
  # spec.description = %q{TODO: Write a longer description or delete this line.}
11
+ spec.post_install_message = <<~MESSAGE
12
+
13
+ If you are updating ruby-clock from 1→2, there are a few things you need to change in your Clockfile.
14
+
15
+ It's quick, easy, and fun! See instructions here:
16
+ https://github.com/jjb/ruby-clock/blob/main/CHANGELOG.md#migrating-from-ruby-clock-version-1-to-version-2
17
+
18
+ MESSAGE
19
+
11
20
  spec.homepage = "https://github.com/jjb/ruby-clock"
12
21
  spec.license = "MIT"
13
22
  spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-clock
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta2
4
+ version: 2.0.0.beta4
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Bachir
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-15 00:00:00.000000000 Z
11
+ date: 2022-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rufus-scheduler
@@ -142,7 +142,14 @@ files:
142
142
  - example-rails-app/vendor/javascript/.keep
143
143
  - exe/clock
144
144
  - lib/ruby-clock.rb
145
+ - lib/ruby-clock/around_actions.rb
146
+ - lib/ruby-clock/dsl.rb
147
+ - lib/ruby-clock/rails.rb
148
+ - lib/ruby-clock/rake.rb
149
+ - lib/ruby-clock/runners.rb
150
+ - lib/ruby-clock/shell.rb
145
151
  - lib/ruby-clock/version.rb
152
+ - lib/rufus_monkeypatch.rb
146
153
  - release.md
147
154
  - ruby-clock.gemspec
148
155
  homepage: https://github.com/jjb/ruby-clock
@@ -151,7 +158,13 @@ licenses:
151
158
  metadata:
152
159
  homepage_uri: https://github.com/jjb/ruby-clock
153
160
  source_code_uri: https://github.com/jjb/ruby-clock
154
- post_install_message:
161
+ post_install_message: |2+
162
+
163
+ If you are updating ruby-clock from 1→2, there are a few things you need to change in your Clockfile.
164
+
165
+ It's quick, easy, and fun! See instructions here:
166
+ https://github.com/jjb/ruby-clock/blob/main/CHANGELOG.md#migrating-from-ruby-clock-version-1-to-version-2
167
+
155
168
  rdoc_options: []
156
169
  require_paths:
157
170
  - lib
@@ -169,5 +182,7 @@ requirements: []
169
182
  rubygems_version: 3.1.6
170
183
  signing_key:
171
184
  specification_version: 4
172
- summary: A "clock" process for invoking ruby code within a persistent runtime
185
+ summary: A job scheduler which runs jobs each in their own thread in a persistent
186
+ process.
173
187
  test_files: []
188
+ ...