ruby-clock 0.6.0 → 0.8.0.rc3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/Gemfile.lock +4 -4
- data/README.md +88 -3
- data/example-app/.gitattributes +1 -0
- data/example-app/Clockfile +11 -0
- data/example-app/Gemfile +7 -0
- data/example-app/Gemfile.lock +31 -0
- data/example-app/README.md +9 -0
- data/exe/clock +19 -4
- data/lib/ruby-clock/version.rb +1 -1
- data/lib/ruby-clock.rb +80 -3
- data/release.md +4 -0
- metadata +12 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e8d972bb2c2468f53d943f233e4e799df71a449b6f7b8c00a1ddbea33c54c92
|
4
|
+
data.tar.gz: fc97259d0575bd220f79dd25206128001eece56ec51eda06d95f28d718b65080
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6dcf79cbebb137a9f04e920b8d6ff0f910bd61536e3e666297217aef8d9942c656fca0d67d794c753ab42a9e035be364bcf3d3b6e465058ebfe7e8683fa94fea
|
7
|
+
data.tar.gz: a3ca20e788af53d77d5526aaacb3b7ff4b07e8852e7586fe181e1681985b32b5bce3a9f0a305507be335dfeee7399567a6cd31afe8262b6e0b84db9cd2d9a75a
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
## 0.8.0 RC3
|
2
|
+
|
3
|
+
* make terrapin and posix-spawn gems optional
|
4
|
+
|
5
|
+
## 0.8.0 RC2
|
6
|
+
|
7
|
+
* fix detection of Rails constant, for non-rails apps
|
8
|
+
|
9
|
+
## 0.8.0 RC1
|
10
|
+
|
11
|
+
* automatically wrap jobs with rails reloader
|
12
|
+
* ability to run rake tasks
|
13
|
+
* ability to run shell commands
|
14
|
+
* nicer shutdown logging, indicating when shutdown process begins and ends
|
15
|
+
* fix approach for error fallbacks when when calculating job identifier (probably never encountered)
|
16
|
+
|
17
|
+
## 0.7.0
|
18
|
+
|
19
|
+
* ability to specify the name of the file with job definitions, e.g. `bundle exec clock clocks/MyClockfile`
|
20
|
+
* ability to specify the amount of time ruby-clock will wait before forcing threads to shut down
|
21
|
+
|
22
|
+
## 0.6.0
|
23
|
+
|
24
|
+
* job identifiers
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ruby-clock (0.
|
4
|
+
ruby-clock (0.8.0.rc2)
|
5
5
|
method_source
|
6
6
|
rufus-scheduler (~> 3.8)
|
7
7
|
|
@@ -9,9 +9,9 @@ GEM
|
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
11
|
concurrent-ruby (1.1.9)
|
12
|
-
et-orbi (1.2.
|
12
|
+
et-orbi (1.2.5)
|
13
13
|
tzinfo
|
14
|
-
fugit (1.5.
|
14
|
+
fugit (1.5.2)
|
15
15
|
et-orbi (~> 1.1, >= 1.1.8)
|
16
16
|
raabro (~> 1.4)
|
17
17
|
method_source (1.0.0)
|
@@ -30,4 +30,4 @@ DEPENDENCIES
|
|
30
30
|
ruby-clock!
|
31
31
|
|
32
32
|
BUNDLED WITH
|
33
|
-
2.
|
33
|
+
2.2.23
|
data/README.md
CHANGED
@@ -16,6 +16,7 @@ The clock process will respond to signals INT (^c at the command line) and
|
|
16
16
|
TERM (signal sent by environments such as Heroku and other PaaS's when shutting down).
|
17
17
|
In both cases, the clock will stop running jobs and give existing jobs 29 seconds
|
18
18
|
to stop before killing them.
|
19
|
+
You can change this number with `RUBY_CLOCK_SHUTDOWN_WAIT_SECONDS` in the environment.
|
19
20
|
|
20
21
|
## Installation
|
21
22
|
|
@@ -55,6 +56,11 @@ To start your clock process:
|
|
55
56
|
|
56
57
|
bundle exec clock
|
57
58
|
|
59
|
+
To use a file other than Clockfile for job definitions, specify it.
|
60
|
+
This will ignore Clockfile and only read jobs from clocks/MyClockfile:
|
61
|
+
|
62
|
+
bundle exec clock clocks/MyClockfile
|
63
|
+
|
58
64
|
### Rails
|
59
65
|
|
60
66
|
Install the `clock` binstub and commit to your repo.
|
@@ -65,6 +71,12 @@ To run your clock process in your app's environment:
|
|
65
71
|
|
66
72
|
bundle exec rails runner bin/clock
|
67
73
|
|
74
|
+
To get smarter database connection management (such as in the case of a database restart or upgrade,
|
75
|
+
and maybe other benefits) and code reloading in dev (app code, not the code in Clockfile itself),
|
76
|
+
jobs are automatically wrapped in the
|
77
|
+
[rails app reloader](https://guides.rubyonrails.org/threading_and_code_execution.html).
|
78
|
+
|
79
|
+
|
68
80
|
### Non-Rails
|
69
81
|
|
70
82
|
Require your app's code at the top of Clockfile:
|
@@ -83,6 +95,28 @@ Add this line to your Procfile
|
|
83
95
|
clock: bundle exec rails runner bin/clock
|
84
96
|
```
|
85
97
|
|
98
|
+
You might have a main clock for general scheduled jobs, and then standalone ones
|
99
|
+
if your system has something where you want to monitor and adjust resources
|
100
|
+
for that work more precisely. Here, maybe the main clock needs a 2GB instance,
|
101
|
+
and the others each need 1GB all to themselves:
|
102
|
+
|
103
|
+
```
|
104
|
+
clock: bundle exec rails runner bin/clock
|
105
|
+
thing_checker: bundle exec rails runner bin/clock clocks/thing_checker.rb
|
106
|
+
thing_reporter: bundle exec rails runner bin/clock clocks/thing_reporter.rb
|
107
|
+
```
|
108
|
+
|
109
|
+
Because of this feature, do I regret using "Clockfile" instead of, say, "clock.rb"? Maybe.
|
110
|
+
|
111
|
+
#### Observing logs
|
112
|
+
|
113
|
+
Because STDOUT does not flush until a certain amount of data has gone into it,
|
114
|
+
you might not immediately see the ruby-clock startup message or job output if
|
115
|
+
viewing logs in a deployed environment such as Heroku where the logs are redirected
|
116
|
+
to another process or file. To change this behavior and have logs flush immediately,
|
117
|
+
add `$stdout.sync = true` to the top of your Clockfile.
|
118
|
+
|
119
|
+
|
86
120
|
## More Config and Capabilities
|
87
121
|
|
88
122
|
### Error Handling
|
@@ -102,6 +136,49 @@ You can define before, after, and around callbacks which will run for all jobs.
|
|
102
136
|
Read [the rufus-scheduler documentation](https://github.com/jmettraux/rufus-scheduler/#callbacks)
|
103
137
|
to learn how to do this. Where the documentation references `s`, you should use `schedule`.
|
104
138
|
|
139
|
+
### Shell commands
|
140
|
+
|
141
|
+
You can run shell commands in your jobs.
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
schedule.every '1 day' do
|
145
|
+
shell('sh scripts/process_stuff.sh')
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
By default they will be run with
|
150
|
+
[ruby backticks](https://livebook.manning.com/concept/ruby/backtick).
|
151
|
+
For better performance, install the [terrapin](https://github.com/thoughtbot/terrapin)
|
152
|
+
and [posix-spawn](https://github.com/rtomayko/posix-spawn) gems.
|
153
|
+
|
154
|
+
`shell` is a convenience method which just passes the string on.
|
155
|
+
If you want to use other terrapin features, you can skip the `shell` command
|
156
|
+
and use terrapin directly:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
schedule.every '1 day' do
|
160
|
+
line = Terrapin::CommandLine.new('optimize_png', ":file")
|
161
|
+
Organization.with_new_logos.find_each do |o|
|
162
|
+
line.run(file: o.logo_file_path)
|
163
|
+
o.update!(logo_optimized: true)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
```
|
167
|
+
|
168
|
+
### Rake tasks
|
169
|
+
|
170
|
+
You can run tasks from within the persistent runtime of ruby-clock, without
|
171
|
+
needing to shell out and start another process.
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
schedule.every '1 day' do
|
175
|
+
rake('reports:daily')
|
176
|
+
end
|
177
|
+
```
|
178
|
+
|
179
|
+
There is also `rake_execute` and `rake_async`. See [the code](https://github.com/jjb/ruby-clock/blob/main/lib/ruby-clock.rb)
|
180
|
+
and [this article](https://code.jjb.cc/running-rake-tasks-from-within-ruby-on-rails-code) for more info.
|
181
|
+
|
105
182
|
### Job Identifier
|
106
183
|
|
107
184
|
ruby-clock adds the `identifier` method to `Rufus::Scheduler::Job`. This method will return the job's
|
@@ -113,12 +190,12 @@ fallback is the line number of the job in Clockfile.
|
|
113
190
|
Some examples of jobs and their identifiers:
|
114
191
|
|
115
192
|
```ruby
|
116
|
-
schedule.every '1 second', name: 'my job' do
|
193
|
+
schedule.every '1 second', name: 'my job' do
|
117
194
|
Foo.bar
|
118
195
|
end
|
119
196
|
# => my job
|
120
197
|
|
121
|
-
schedule.every '1 day'
|
198
|
+
schedule.every '1 day' do
|
122
199
|
daily_things = Foo.setup_daily
|
123
200
|
daily_things.process
|
124
201
|
# TODO: figure out best time of day
|
@@ -126,7 +203,7 @@ end
|
|
126
203
|
# => daily_things.process
|
127
204
|
|
128
205
|
# n.b. ruby-clock isn't yet smart enough to remove trailing comments
|
129
|
-
schedule.every '1 week'
|
206
|
+
schedule.every '1 week' do
|
130
207
|
weekly_things = Foo.setup_weekly
|
131
208
|
weekly_things.process # does this work???!1~
|
132
209
|
end
|
@@ -168,6 +245,14 @@ so anything you can do on this instance, you can do in your Clockfile.
|
|
168
245
|
Perhaps in the future ruby-clock will add some easier specific configuration
|
169
246
|
capabilities for some things. Let me know if you have a request!
|
170
247
|
|
248
|
+
## Syntax highlighting for Clockfile
|
249
|
+
|
250
|
+
To tell github and maybe other systems to syntax highlight Clockfile, put this in a .gitattributes file:
|
251
|
+
|
252
|
+
```gitattributes
|
253
|
+
Clockfile linguist-language=Ruby
|
254
|
+
```
|
255
|
+
|
171
256
|
|
172
257
|
## License
|
173
258
|
|
@@ -0,0 +1 @@
|
|
1
|
+
Clockfile linguist-language=Ruby
|
data/example-app/Gemfile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
ruby-clock (0.8.0.rc2)
|
5
|
+
method_source
|
6
|
+
rufus-scheduler (~> 3.8)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
concurrent-ruby (1.1.9)
|
12
|
+
et-orbi (1.2.5)
|
13
|
+
tzinfo
|
14
|
+
fugit (1.5.2)
|
15
|
+
et-orbi (~> 1.1, >= 1.1.8)
|
16
|
+
raabro (~> 1.4)
|
17
|
+
method_source (1.0.0)
|
18
|
+
raabro (1.4.0)
|
19
|
+
rufus-scheduler (3.8.0)
|
20
|
+
fugit (~> 1.1, >= 1.1.6)
|
21
|
+
tzinfo (2.0.4)
|
22
|
+
concurrent-ruby (~> 1.0)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
arm64-darwin-20
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
ruby-clock!
|
29
|
+
|
30
|
+
BUNDLED WITH
|
31
|
+
2.2.28
|
data/exe/clock
CHANGED
@@ -8,9 +8,11 @@ class Rufus::Scheduler::Job
|
|
8
8
|
@identifier ||= begin
|
9
9
|
name || handler.source.split("\n").reject(&:empty?).grep_v(/#.*/)[-2].strip
|
10
10
|
rescue
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
begin
|
12
|
+
source_location.join('-')
|
13
|
+
rescue
|
14
|
+
'error-calculating-job-identifier'
|
15
|
+
end
|
14
16
|
end
|
15
17
|
end
|
16
18
|
end
|
@@ -18,7 +20,20 @@ end
|
|
18
20
|
include RubyClock
|
19
21
|
|
20
22
|
listen_to_signals
|
23
|
+
prepare_rake
|
24
|
+
schedule.pause
|
25
|
+
|
26
|
+
load ARGV[0] || 'Clockfile'
|
21
27
|
|
22
|
-
|
28
|
+
if defined?(::Rails)
|
29
|
+
schedule.instance_eval do
|
30
|
+
@old_around_trigger = method :around_trigger
|
31
|
+
def around_trigger(job)
|
32
|
+
::Rails.application.reloader.wrap do
|
33
|
+
@old_around_trigger.call(job){ yield }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
23
38
|
|
24
39
|
run_jobs
|
data/lib/ruby-clock/version.rb
CHANGED
data/lib/ruby-clock.rb
CHANGED
@@ -3,8 +3,10 @@ require 'rufus-scheduler'
|
|
3
3
|
|
4
4
|
module RubyClock
|
5
5
|
def shutdown
|
6
|
-
|
7
|
-
|
6
|
+
wait_seconds = ENV['RUBY_CLOCK_SHUTDOWN_WAIT_SECONDS']&.to_i || 29
|
7
|
+
puts "Shutting down ruby-clock. Waiting #{wait_seconds} seconds for jobs to finish..."
|
8
|
+
schedule.shutdown(wait: wait_seconds)
|
9
|
+
puts "...done 🐈️ 👋"
|
8
10
|
end
|
9
11
|
|
10
12
|
def listen_to_signals
|
@@ -27,6 +29,81 @@ module RubyClock
|
|
27
29
|
|
28
30
|
def run_jobs
|
29
31
|
puts "Starting ruby-clock with #{schedule.jobs.size} jobs"
|
30
|
-
|
32
|
+
schedule.resume
|
33
|
+
schedule.join
|
31
34
|
end
|
35
|
+
|
36
|
+
def prepare_rake
|
37
|
+
if defined?(::Rails) && Rails.application
|
38
|
+
Rails.application.load_tasks
|
39
|
+
Rake::Task.tasks.each{|t| t.prerequisites.delete 'environment' }
|
40
|
+
@rake_mutex = Mutex.new
|
41
|
+
else
|
42
|
+
puts <<~MESSAGE
|
43
|
+
Because this is not a rails application, we do not know how to load your
|
44
|
+
rake tasks. You can do this yourself at the top of your Clockfile if you want
|
45
|
+
to run rake tasks from ruby-cron.
|
46
|
+
MESSAGE
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# See https://code.jjb.cc/running-rake-tasks-from-within-ruby-on-rails-code
|
51
|
+
|
52
|
+
# for tasks that don't have dependencies
|
53
|
+
def rake_execute(task)
|
54
|
+
Rake::Task[task].execute
|
55
|
+
end
|
56
|
+
|
57
|
+
# If the task doesn't share dependencies with another task,
|
58
|
+
# or if it does and you know you'll never run tasks such that any overlap
|
59
|
+
def rake_async(task)
|
60
|
+
Rake::Task[task].invoke
|
61
|
+
ensure
|
62
|
+
Rake::Task[task].reenable
|
63
|
+
Rake::Task[task].all_prerequisite_tasks.each(&:reenable)
|
64
|
+
end
|
65
|
+
|
66
|
+
# If the task has shared dependencies and you might run more than one at the same time
|
67
|
+
# This is the safest option and hence the default.
|
68
|
+
def rake(task)
|
69
|
+
@rake_mutex.synchronize { rake_async(task) }
|
70
|
+
end
|
71
|
+
|
72
|
+
def shell_runner
|
73
|
+
@shell_runner ||= begin
|
74
|
+
require 'terrapin'
|
75
|
+
require 'posix-spawn'
|
76
|
+
|
77
|
+
unless Terrapin::CommandLine.runner.class == Terrapin::CommandLine::PosixRunner
|
78
|
+
puts <<~MESSAGE
|
79
|
+
|
80
|
+
🤷 terrapin and posix-spawn are installed, but for some reason terrapin is
|
81
|
+
not using posix-spawn as its runner.
|
82
|
+
|
83
|
+
MESSAGE
|
84
|
+
end
|
85
|
+
|
86
|
+
puts '🐆 Using terrapin for shell commands.'
|
87
|
+
:terrapin
|
88
|
+
rescue LoadError
|
89
|
+
puts <<~MESSAGE
|
90
|
+
|
91
|
+
🦥 Using ruby backticks for shell commands.
|
92
|
+
For better performance, install the terrapin and posix-spawn gems.
|
93
|
+
See README.md for more info.
|
94
|
+
|
95
|
+
MESSAGE
|
96
|
+
:backticks
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def shell(command)
|
101
|
+
case shell_runner
|
102
|
+
when :terrapin
|
103
|
+
Terrapin::CommandLine.new(command).run
|
104
|
+
when :backticks
|
105
|
+
`#{command}`
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
32
109
|
end
|
data/release.md
ADDED
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: 0.
|
4
|
+
version: 0.8.0.rc3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Bachir
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rufus-scheduler
|
@@ -47,6 +47,7 @@ extensions: []
|
|
47
47
|
extra_rdoc_files: []
|
48
48
|
files:
|
49
49
|
- ".gitignore"
|
50
|
+
- CHANGELOG.md
|
50
51
|
- Gemfile
|
51
52
|
- Gemfile.lock
|
52
53
|
- LICENSE.txt
|
@@ -54,9 +55,15 @@ files:
|
|
54
55
|
- Rakefile
|
55
56
|
- bin/console
|
56
57
|
- bin/setup
|
58
|
+
- example-app/.gitattributes
|
59
|
+
- example-app/Clockfile
|
60
|
+
- example-app/Gemfile
|
61
|
+
- example-app/Gemfile.lock
|
62
|
+
- example-app/README.md
|
57
63
|
- exe/clock
|
58
64
|
- lib/ruby-clock.rb
|
59
65
|
- lib/ruby-clock/version.rb
|
66
|
+
- release.md
|
60
67
|
- ruby-clock.gemspec
|
61
68
|
homepage: https://github.com/jjb/ruby-clock
|
62
69
|
licenses:
|
@@ -75,11 +82,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
82
|
version: 2.3.0
|
76
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
84
|
requirements:
|
78
|
-
- - "
|
85
|
+
- - ">"
|
79
86
|
- !ruby/object:Gem::Version
|
80
|
-
version:
|
87
|
+
version: 1.3.1
|
81
88
|
requirements: []
|
82
|
-
rubygems_version: 3.
|
89
|
+
rubygems_version: 3.2.22
|
83
90
|
signing_key:
|
84
91
|
specification_version: 4
|
85
92
|
summary: A "clock" process for invoking ruby code within a persistent runtime
|