ruby-clock 2.0.0.beta8 → 2.0.0.beta10

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: 315bcc30c6fc32c1676e452750d76e839b0123f19fe7512bbe6662ae72ee0ecc
4
- data.tar.gz: a5831b721e9d99af3082cb31dd472f4e282d5665616f40694ba41def7250b907
3
+ metadata.gz: 0f773f1b873c6048b24cb6c78769c809fd3008c0316463071633086aa572f853
4
+ data.tar.gz: 28de0953617822f2473cecebdac1ab308420231670073db0d4458d89d527e3ee
5
5
  SHA512:
6
- metadata.gz: '0983e40393e4d273feddbcb53d67c0a8b2ccbb194439a16df9ddb1edaeedcf89f36338bffc80d8ffb44809500b3553cbc601c55275fcd4dba86d18b67ad57bf5'
7
- data.tar.gz: 563039f0ea34927b4d6e1abd64db0f2ae086c44f37d03852d8ca510223e1ce0f57ebe275ce7059d704de3e29a1e7f33d1412b92ad4b7a5a7e4e6d5ec661e9605
6
+ metadata.gz: e4d94f375285033a0ca49ed535b29f0768adac1efa83f4c63a67090f866aa2a1f72b4a0159c746d99bf765c8c5b7f308daff090be0e2b671518d8fe67cf3b63e
7
+ data.tar.gz: 693519be98311aff6e24aae1c61cf908f710049a6854886264f100dc844f8436b3ba58f0ab1bd9b6d6a5bf3f5916383d744ce9390dbb582bdd70f4c6dab03936
data/CHANGELOG.md CHANGED
@@ -5,30 +5,33 @@
5
5
  is implemented is now compatible with both rails 6 and 7
6
6
  * RUBY_CLOCK_SHUTDOWN_WAIT_SECONDS value is logged when starting
7
7
  * DSL methods are now at the top-level namespace (`schedule.every` → `every`, `schedule.cron` → `cron`)
8
- * Error handler definition is now at the top-level namespace (`def schedule.on_error` → `on_error do`)
9
8
  * Around callbacks now have a top-level namespace method. `def schedule.around_trigger` → `around_action do`
10
9
  * Multiple around callbacks can be consecutively assigned - no need to put all behavior into one method
10
+ * Error handler definition is now at the top-level namespace (`def schedule.on_error` → `on_error do`)
11
11
  * Errors encountered when loading Clockfile (such as incorrect cron syntax)
12
12
  will be reported to the error handler
13
13
  * The automatic identifier generator will now ignore `}` and `end` lines
14
- * posix-spawn is no longer used. In ruby 3, native `Process.spawn` is more performant. See
14
+ * posix-spawn is no longer used. In ruby ~3~ 2.2, native `Process.spawn` is more performant. See
15
15
  [posix-spawn#90](https://github.com/rtomayko/posix-spawn/issues/90)
16
16
  and
17
17
  [terrapin#19](https://github.com/thoughtbot/terrapin/pull/19)
18
18
  for more info.
19
- * `--environment-and-syntax-check` capability
19
+ * ability to load multiple clockfiles with one invocation
20
+ * job slugs based on job identifier, e.g. "Widget Co. Weekly Reports" -> "widget-co-weekly-reports"
21
+ * `--check-slug-uniqueness`
22
+ * `--environment-and-syntax-check`
23
+ * `--generate-dummy-crontab` to facilitate visualization with cronv
20
24
 
21
25
  ### Anti-Features
22
26
  * ruby 3.0 is now the minimum version
23
27
 
24
28
  ### Code Improvements
25
29
  * The code which implements the rails reloader/executor is now less complicated
26
- * Code reorganization so there are no unnecessary methods in top-level Kernel namespace
30
+ * Code reorganization so there are no unnecessary methods in top-level `Kernel` namespace
27
31
  * top-level DSL methods are now implemented with refinements, so they don't polute other code
28
32
 
29
33
 
30
34
  ### Migrating from ruby-clock version 1 to version 2
31
-
32
35
  * The minimum ruby version is 3.0
33
36
  * The top of every Clockfile must begin with `using RubyClock::DSL`
34
37
  * If you have an existing `def schedule.around_trigger`, you will need to change it to use the new
@@ -37,6 +40,7 @@
37
40
  `every`, `cron`, and `on_error` at the top-level, without referencing `schedule`.
38
41
  * You now have the option of catching and reporting errors encountered when parsing the Clockfile.
39
42
  * There is no longer a need to have a binstub in rails. You can delete bin/clock from your app.
43
+ * remove the `posix-spawn` gem from your project
40
44
  * The invocations (in Procfile, or wherever else you start ruby-clock) should change from
41
45
 
42
46
  bundle exec rails runner bin/clock
data/README.md CHANGED
@@ -33,7 +33,7 @@ ruby >= 3.0 is required.
33
33
  Add these lines to your application's Gemfile:
34
34
 
35
35
  ```ruby
36
- gem 'ruby-clock'
36
+ gem 'ruby-clock', '2.0.0.beta10'
37
37
  ```
38
38
 
39
39
  And then execute:
@@ -71,6 +71,11 @@ This will ignore Clockfile and only read jobs from clocks/MyClockfile:
71
71
 
72
72
  bundle exec clock clocks/MyClockfile
73
73
 
74
+ You can also load multiple files with one invocation
75
+ (although a better approach might be to load your subfiles within a top-level Clockfile):
76
+
77
+ bundle exec clock clocks/daily.rb clocks/weekly.rb
78
+
74
79
  ### Rails
75
80
 
76
81
  To run your clock process in your app's environment:
@@ -150,6 +155,28 @@ is valid during dev, or in automate tests.
150
155
  assert(system("bundle exec --environment-and-syntax-check clock/my_clockfile.rb"))
151
156
  ```
152
157
 
158
+ You can use `--check-slug-uniqueness` to check if all the auto-generated slugs are unique. If you have
159
+ multiple files with jobs, you need to pass them all in with one invocation in order to check global uniqueness.
160
+
161
+ ```ruby
162
+ # system returns true/false depending on 0/1 exit status of process
163
+ assert(system("bundle exec --check-slug-uniqueness")) # loads Clockfile
164
+ assert(system("bundle exec --check-slug-uniqueness clock/weekly.rb clock/daily.rb")) # load specific files
165
+ ```
166
+
167
+ #### Visualization with cronv
168
+
169
+ Using the `--generate-dummy-crontab` flag you can visualize your schedule with [cronv](https://github.com/takumakanari/cronv).
170
+ For your jobs with cron-style schedules, it will generate a dummy crontab file that can be ingested by cronv.
171
+ For your jobs with "Every X seconds" schedules, a comment will be made in the file and they will not be vizualized.
172
+
173
+ ```console
174
+ bundle exec clock --generate-dummy-crontab Clockfile ../clock/daily.rb ../clock/weekly.rb > dummycron.txt
175
+ ## IMPORTANT: open dummycron.txt in an editor and remove the boot startup message cruft from the top
176
+ cat dummycron.txt | /Users/your-username/go/bin/cronv -d 1d -o ./my_cron_schedule.html
177
+ open dummycron
178
+ ```
179
+
153
180
  ## More Config and Capabilities
154
181
 
155
182
  ### Error Handling
@@ -297,7 +324,7 @@ There are also `rake_execute` and `rake_async`.
297
324
  See [the code](https://github.com/jjb/ruby-clock/blob/main/lib/ruby-clock/rake.rb)
298
325
  and [this article](https://code.jjb.cc/running-rake-tasks-from-within-ruby-on-rails-code) for more info.
299
326
 
300
- ### Job Identifier
327
+ ### Job Identifier & Slug
301
328
 
302
329
  ruby-clock adds the `identifier` method to `Rufus::Scheduler::Job`. This method will return the job's
303
330
  [name](https://github.com/jmettraux/rufus-scheduler/#name--string) if one was given.
@@ -305,30 +332,35 @@ If a name is not given, the last non-comment code line in the job's block
305
332
  will be used instead. If for some reason an error is encountered while calculating this, the next
306
333
  fallback is the line number of the job in Clockfile.
307
334
 
308
- Some examples of jobs and their identifiers:
335
+ There is also the `slug` method, which produces a slug using
336
+ [ActiveSupport parameterize](https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-parameterize),
337
+ and with underscores changed to hyphens.
338
+ If the `activesupport` gem is not in your Gemfile and you attempt to use `slug`, it will fail.
339
+
340
+ Some examples of identifiers and slugs:
309
341
 
310
342
  ```ruby
311
343
  every '1 second', name: 'my job' do
312
344
  Foo.bar
313
345
  end
314
- # => my job
346
+ # my job, my-job
315
347
 
316
348
  every '1 day' do
317
349
  daily_things = Foo.setup_daily
318
350
  daily_things.process
319
351
  # TODO: figure out best time of day
320
352
  end
321
- # => daily_things.process
353
+ # daily_things.process, daily-things-process
322
354
 
323
355
  # n.b. ruby-clock isn't yet smart enough to remove trailing comments
324
356
  every '1 week' do
325
357
  weekly_things = Foo.setup_weekly
326
358
  weekly_things.process # does this work???!1~
327
359
  end
328
- # => weekly_things.process # does this work???!1~
360
+ # weekly_things.process # does this work???!1~, weekly-things-process-does-this-work-1
329
361
  ```
330
362
 
331
- This can be used for keeping track of job behavior in logs or a
363
+ The identifier can be used for keeping track of job behavior in logs or a
332
364
  stats tracker. For example:
333
365
 
334
366
  ```ruby
@@ -356,6 +388,18 @@ every '10 seconds', name: 'thread stats' do
356
388
  end
357
389
  ```
358
390
 
391
+ The slug can be used for similar purposes where a slug-style string is needed. Here you can report
392
+ your job to a scheduled job monitor:
393
+
394
+ ```ruby
395
+ # TODO proper example for healthcheks
396
+ around_action do |job_proc, job_info|
397
+ Net::HTTP.get("https://mymonitor.example.com/APIKEY/start/#{job_info.slug}")
398
+ job_proc.call
399
+ Net::HTTP.get("https://mymonitor.example.com/APIKEY/stop/#{job_info.slug}")
400
+ end
401
+ ```
402
+
359
403
  ### Other rufus-scheduler Options
360
404
 
361
405
  All [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler/) options are set to defaults.
@@ -14,7 +14,7 @@ end
14
14
  # end
15
15
 
16
16
  around_action do |job_proc, job_info|
17
- puts "before1 #{job_info.class} #{job_info.identifier}"
17
+ puts "before1 #{job_info.class} #{job_info.identifier} #{job_info.slug}"
18
18
  job_proc.call
19
19
  puts "after1"
20
20
  end
data/example-app/Gemfile CHANGED
@@ -5,4 +5,5 @@ source "https://rubygems.org"
5
5
  ruby '>= 3.0'
6
6
 
7
7
  gem 'ruby-clock', path: '../'
8
+ gem 'activesupport'
8
9
  # gem 'terrapin'
data/exe/clock CHANGED
@@ -9,27 +9,43 @@ RubyClock.instance.prepare_rake
9
9
  RubyClock.instance.schedule.pause
10
10
  RubyClock.instance.add_rails_executor_to_around_actions
11
11
 
12
- clockfile = 'Clockfile'
13
12
  check_syntax = false
14
- case ARGV[0]
15
- when '--environment-and-syntax-check'
16
- check_syntax = true
17
- case ARGV[1]
18
- when String
19
- clockfile = ARGV[1]
13
+ check_slug_uniqueness = false
14
+ generate_dummy_crontab = false
15
+ if '--' == ARGV[0][0..1]
16
+ case ARGV[0]
17
+ when '--environment-and-syntax-check'
18
+ check_syntax = true
19
+ when '--check-slug-uniqueness'
20
+ check_slug_uniqueness = true
21
+ when '--generate-dummy-crontab'
22
+ generate_dummy_crontab = true
23
+ else
24
+ raise 'unknown option'
25
+ end
26
+ if ARGV[1]
27
+ clockfiles = ARGV[1..]
28
+ else
29
+ clockfiles = ['Clockfile']
30
+ end
31
+ else
32
+ if ARGV[0]
33
+ clockfiles = ARGV[0..]
34
+ else
35
+ clockfiles = ['Clockfile']
20
36
  end
21
- when String
22
- clockfile = ARGV[0]
23
37
  end
24
38
 
25
- begin
26
- load clockfile
27
- rescue => clockfile_error
28
- if RubyClock.instance.on_error
29
- RubyClock.instance.on_error.call("An error has occured while parsing the clockfile", clockfile_error)
30
- end
39
+ clockfiles.each do |clockfile|
40
+ begin
41
+ load clockfile
42
+ rescue => clockfile_error
43
+ if RubyClock.instance.on_error
44
+ RubyClock.instance.on_error.call("An error has occured while parsing the clockfile #{clockfile}", clockfile_error)
45
+ end
31
46
 
32
- raise
47
+ raise
48
+ end
33
49
  end
34
50
 
35
51
  RubyClock.instance.ensure_around_trigger_has_not_been_redefined
@@ -37,6 +53,33 @@ RubyClock.instance.freeze_around_actions
37
53
 
38
54
  if check_syntax
39
55
  puts "✨ Environment & Syntax OK ✨"
56
+ elsif check_slug_uniqueness
57
+ slugs = {}
58
+ RubyClock.instance.schedule.jobs.each do |j|
59
+ if slugs[j.slug]
60
+ slugs[j.slug] +=1
61
+ else
62
+ slugs[j.slug] = 1
63
+ end
64
+ end
65
+ slugs_with_duplicates = []
66
+ slugs.each{|s,count| slugs_with_duplicates << s if count > 1 }
67
+ if slugs_with_duplicates.any?
68
+ puts "The following slugs have duplicates: #{slugs_with_duplicates}"
69
+ exit(false)
70
+ else
71
+ puts "✨ All Slugs Are Unique ✨"
72
+ end
73
+ elsif generate_dummy_crontab
74
+ text = ''
75
+ RubyClock.instance.schedule.jobs.each do |j|
76
+ if j.respond_to?(:cron_line)
77
+ text << "#{j.cron_line.original} #{j.slug}\n"
78
+ else
79
+ text << "# every-#{j.frequency}-seconds #{j.slug}\n"
80
+ end
81
+ end
82
+ puts text
40
83
  else
41
84
  RubyClock.instance.run_jobs
42
85
  end
@@ -1,3 +1,3 @@
1
1
  class RubyClock
2
- VERSION = "2.0.0.beta8"
2
+ VERSION = "2.0.0.beta10"
3
3
  end
@@ -1,6 +1,8 @@
1
1
  require 'method_source'
2
+
2
3
  class Rufus::Scheduler::Job
3
4
  UNDESIRED_ELEMENTS = ['', '}', 'end']
5
+
4
6
  def identifier
5
7
  @identifier ||= begin
6
8
  return name if name
@@ -18,4 +20,9 @@ class Rufus::Scheduler::Job
18
20
  end
19
21
  end
20
22
  end
23
+
24
+ def slug
25
+ require 'active_support/inflector'
26
+ identifier.gsub('_', '-').parameterize
27
+ end
21
28
  end
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.beta8
4
+ version: 2.0.0.beta10
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Bachir
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-06 00:00:00.000000000 Z
11
+ date: 2023-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rufus-scheduler