zhong 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/CI.yml +34 -0
- data/CHANGELOG.md +21 -0
- data/LICENSE.txt +4 -21
- data/README.md +48 -7
- data/lib/zhong/every.rb +1 -1
- data/lib/zhong/job.rb +2 -1
- data/lib/zhong/version.rb +1 -1
- data/lib/zhong/web.rb +2 -0
- data/lib/zhong/web_helpers.rb +2 -0
- data/test/test_every.rb +12 -0
- data/web/views/index.erb +7 -6
- data/zhong.gemspec +5 -5
- metadata +15 -18
- data/.travis.yml +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 577d8f17b30c591def82d4f69b184e233ba9a3b66d690616880c6e311dd85e4c
|
4
|
+
data.tar.gz: a838490cfa7cf4b3dbd451009cd0278d9a7ab391934e6e39a8d897af4a81926a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30259b64b127a57c3ae44cfe5ad5a8339c7009512eeb26d08e69b417bf0c6d682de87d73f20ac23efc9fd2e2863aa9a62f2ca6c6b07eee89e77228c017f49007
|
7
|
+
data.tar.gz: 36e88630340b371f38c511d9b716456b7a2112c5c4555c197ec18d3c176cad22f52be34c43262c06cf670d2bddafcbfe9c2c60124780075987228c548df11d3e
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
pull_request:
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
build:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
strategy:
|
13
|
+
fail-fast: false
|
14
|
+
matrix:
|
15
|
+
ruby:
|
16
|
+
- '2.5'
|
17
|
+
- '2.6'
|
18
|
+
- '2.7'
|
19
|
+
- '3.0'
|
20
|
+
- ruby-head
|
21
|
+
continue-on-error: ${{ matrix.ruby == 'ruby-head' }}
|
22
|
+
services:
|
23
|
+
redis:
|
24
|
+
image: redis
|
25
|
+
ports:
|
26
|
+
- 6379:6379
|
27
|
+
steps:
|
28
|
+
- uses: actions/checkout@v2
|
29
|
+
- uses: ruby/setup-ruby@v1
|
30
|
+
with:
|
31
|
+
ruby-version: ${{ matrix.ruby }}
|
32
|
+
bundler-cache: true
|
33
|
+
- run: |
|
34
|
+
bundle exec rake
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
## 0.3.0
|
2
|
+
|
3
|
+
- Update version requirements, and switch to Github actions (thank you @mlarraz!)
|
4
|
+
|
5
|
+
## 0.2.4
|
6
|
+
|
7
|
+
- Compatibility with Sinatra/Tilt (thank you Brian Storti!)
|
8
|
+
|
9
|
+
## 0.2.3
|
10
|
+
|
11
|
+
- Much improved documentation, and executable file naming (thank you Antoine Augusti!)
|
12
|
+
- Fixes to the time parsing & to_s (thank you Antoine Augusti!)
|
13
|
+
|
14
|
+
## 0.2.2
|
15
|
+
|
16
|
+
- Re-licensed as LGPL, as I lifted Sidekiq-web code to power Zhong web (thanks Mike Perham for the great gem and the code!)
|
17
|
+
|
18
|
+
## 0.2.1
|
19
|
+
|
20
|
+
- Fix manually specifying a Redis connection (thanks, Richard Adams!)
|
21
|
+
|
1
22
|
## 0.2.0
|
2
23
|
|
3
24
|
- Configuring Redis and the heartbeat key now correctly updates even after Zhong is configured initially.
|
data/LICENSE.txt
CHANGED
@@ -1,22 +1,5 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) Nick Elser
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
a copy of this software and associated documentation files (the
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
11
|
-
the following conditions:
|
12
|
-
|
13
|
-
The above copyright notice and this permission notice shall be
|
14
|
-
included in all copies or substantial portions of the Software.
|
15
|
-
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
3
|
+
Zhong is an Open Source project licensed under the terms of
|
4
|
+
the LGPLv3 license. Please see <http://www.gnu.org/licenses/lgpl-3.0.html>
|
5
|
+
for license text.
|
data/README.md
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
# Zhong [![Build Status](https://
|
1
|
+
# Zhong [![Build Status](https://github.com/nickelser/zhong/workflows/CI/badge.svg)](https://github.com/nickelser/zhong/actions?query=workflow%3ACI) [![Code Climate](https://codeclimate.com/github/nickelser/zhong/badges/gpa.svg)](https://codeclimate.com/github/nickelser/zhong) [![Gem Version](https://badge.fury.io/rb/zhong.svg)](http://badge.fury.io/rb/zhong)
|
2
2
|
|
3
3
|
Useful, reliable distributed cron. Tired of your cron-like scheduler running key jobs twice? Would you like to be able to run your cron server on multiple machines and have it "just work"? Have we got the gem for you.
|
4
4
|
|
5
5
|
Zhong uses Redis to acquire exclusive locks on jobs, as well as recording when they last ran. This means that you can rest easy at night, knowing that your customers are getting their monthly Goat Fancy magazine subscriptions and you are rolling around in your piles of money without a care in the world.
|
6
6
|
|
7
|
+
:tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
|
7
8
|
# Installation
|
8
9
|
|
9
10
|
Add this line to your application’s Gemfile:
|
@@ -14,6 +15,9 @@ gem 'zhong'
|
|
14
15
|
|
15
16
|
## Usage
|
16
17
|
|
18
|
+
### Zhong schedule
|
19
|
+
Create a definition file, let's call it `zhong.rb`:
|
20
|
+
|
17
21
|
```ruby
|
18
22
|
Zhong.redis = Redis.new(url: ENV["ZHONG_REDIS_URL"])
|
19
23
|
|
@@ -23,9 +27,9 @@ Zhong.schedule do
|
|
23
27
|
puts "foo"
|
24
28
|
end
|
25
29
|
|
26
|
-
every(1.minute, "biz", at: ["**:26", "**:27"]) { puts "biz" }
|
27
|
-
every(1.week, "baz", at: ["mon 22:45", "wed 23:13"]) { puts "baz" }
|
28
|
-
every(10.seconds, "boom") { raise "fail" }
|
30
|
+
every(1.minute, "running biz at 26th and 27th minute", at: ["**:26", "**:27"]) { puts "biz" }
|
31
|
+
every(1.week, "running baz on mon and wed", at: ["mon 22:45", "wed 23:13"]) { puts "baz" }
|
32
|
+
every(10.seconds, "boom every 10 seconds") { raise "fail" }
|
29
33
|
end
|
30
34
|
|
31
35
|
category "clutter" do
|
@@ -75,18 +79,55 @@ Zhong.schedule do
|
|
75
79
|
end
|
76
80
|
```
|
77
81
|
|
82
|
+
This file only describes what should be the schedule. Nothing will be executed
|
83
|
+
until we actually run
|
84
|
+
```ruby
|
85
|
+
Zhong.start
|
86
|
+
```
|
87
|
+
after describing the Zhong schedule.
|
88
|
+
|
89
|
+
### Zhong cron process
|
90
|
+
|
91
|
+
You can run the cron process that will execute your code from the definitions
|
92
|
+
in the `zhong.rb` file by running:
|
93
|
+
```sh
|
94
|
+
zhong zhong.rb
|
95
|
+
```
|
96
|
+
|
78
97
|
## Web UI
|
79
98
|
|
80
99
|
Zhong comes with a web application that can display jobs, their last run and
|
81
100
|
enable/disable them.
|
82
101
|
|
83
|
-
|
102
|
+
This is a Sinatra application that requires at least `v2.0.0`. You can add to your Gemfile
|
103
|
+
```ruby
|
104
|
+
gem 'sinatra', "~>2.0"
|
105
|
+
```
|
106
|
+
|
107
|
+
It can be protected by HTTP basic authentication by
|
108
|
+
setting the following environment variables:
|
109
|
+
- `ZHONG_WEB_USERNAME`: the username
|
110
|
+
- `ZHONG_WEB_PASSWORD`: the password
|
84
111
|
|
85
|
-
|
112
|
+
You'll need to load the Zhong schedule to be able to see jobs in the web UI, typically
|
113
|
+
by requiring your `zhong.rb` definition file.
|
86
114
|
|
115
|
+
### Rails
|
116
|
+
Load the Zhong schedule by creating an initializer at `config/initializers/zhong.rb`,
|
117
|
+
with the following content:
|
118
|
+
```ruby
|
119
|
+
require "#{Rails.root}/zhong.rb"
|
120
|
+
```
|
121
|
+
|
122
|
+
Add the following to your `config/routes.rb`:
|
87
123
|
```ruby
|
88
124
|
require 'zhong/web'
|
89
|
-
|
125
|
+
|
126
|
+
Rails.application.routes.draw do
|
127
|
+
# Other routes here...
|
128
|
+
|
129
|
+
mount Zhong::Web, at: "/zhong"
|
130
|
+
end
|
90
131
|
```
|
91
132
|
|
92
133
|
## History
|
data/lib/zhong/every.rb
CHANGED
data/lib/zhong/job.rb
CHANGED
@@ -23,6 +23,7 @@ module Zhong
|
|
23
23
|
@long_running_timeout = config[:long_running_timeout]
|
24
24
|
@running = false
|
25
25
|
@first_run = true
|
26
|
+
@last_ran = nil
|
26
27
|
@id = Digest::SHA256.hexdigest(@name)
|
27
28
|
end
|
28
29
|
|
@@ -183,7 +184,7 @@ module Zhong
|
|
183
184
|
end
|
184
185
|
|
185
186
|
def redis_lock
|
186
|
-
@lock ||= Suo::Client::Redis.new(lock_key, client:
|
187
|
+
@lock ||= Suo::Client::Redis.new(lock_key, client: redis, stale_lock_expiration: @long_running_timeout)
|
187
188
|
end
|
188
189
|
end
|
189
190
|
end
|
data/lib/zhong/version.rb
CHANGED
data/lib/zhong/web.rb
CHANGED
@@ -6,6 +6,8 @@ require "zhong"
|
|
6
6
|
require "zhong/web_helpers"
|
7
7
|
|
8
8
|
module Zhong
|
9
|
+
# Most of the following helpers are copied from a previous version of the Sidekiq project
|
10
|
+
# available here: https://github.com/mperham/sidekiq/blob/2c9f7662fcdcb52d59b72ba0fe7dc5f963de4904/lib/sidekiq/web.rb
|
9
11
|
class Web < Sinatra::Base
|
10
12
|
enable :sessions
|
11
13
|
use ::Rack::Protection, use: :authenticity_token unless ENV["RACK_ENV"] == "test"
|
data/lib/zhong/web_helpers.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
require "uri"
|
3
3
|
|
4
4
|
module Zhong
|
5
|
+
# Most of the following helpers are copied from a previous version of the Sidekiq project
|
6
|
+
# available here: https://github.com/mperham/sidekiq/blob/2c9f7662fcdcb52d59b72ba0fe7dc5f963de4904/lib/sidekiq/web_helpers.rb
|
5
7
|
module WebHelpers
|
6
8
|
# Simple capture method for erb templates. The origin was
|
7
9
|
# capture method from sinatra-contrib library.
|
data/test/test_every.rb
CHANGED
@@ -77,6 +77,18 @@ class TestEvery < Minitest::Test
|
|
77
77
|
assert_equal time_in_day(0, 0, 7, 10), every.next_at(time_in_day(0, 0, 0, 10))
|
78
78
|
end
|
79
79
|
|
80
|
+
def test_to_s
|
81
|
+
assert_equal "3 minutes", Zhong::Every.parse(3.minute).to_s
|
82
|
+
assert_equal "3 hours", Zhong::Every.parse(3.hour).to_s
|
83
|
+
assert_equal "1 hour", Zhong::Every.parse(1.hour).to_s
|
84
|
+
assert_equal "3 days", Zhong::Every.parse(3.day).to_s
|
85
|
+
assert_equal "3 weeks", Zhong::Every.parse(3.week).to_s
|
86
|
+
assert_equal "3 months", Zhong::Every.parse(3.month).to_s
|
87
|
+
assert_equal "1 month", Zhong::Every.parse(1.month).to_s
|
88
|
+
assert_equal "3 years", Zhong::Every.parse(3.year).to_s
|
89
|
+
assert_equal "3 decades", Zhong::Every.parse(30.years).to_s
|
90
|
+
end
|
91
|
+
|
80
92
|
def test_invalid_string_foo
|
81
93
|
assert_raises Zhong::Every::FailedToParse do
|
82
94
|
Zhong::Every.parse("foo")
|
data/web/views/index.erb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
|
+
<!-- This view based on ankane/clockwork_web's interface https://github.com/ankane/clockwork_web/blob/master/app/views/clockwork_web/home/index.html.erb -->
|
2
3
|
<html>
|
3
4
|
<head>
|
4
5
|
<title><%= environment_title_prefix %>Zhong</title>
|
@@ -69,7 +70,7 @@
|
|
69
70
|
<tbody>
|
70
71
|
<% @jobs.each do |job| %>
|
71
72
|
<% enabled = !@disabled[job.to_s] %>
|
72
|
-
<% enabled_str = enabled ? 'disable' : 'enable'
|
73
|
+
<% enabled_str = enabled ? 'disable' : 'enable' %>
|
73
74
|
<% last_run = @last_runs[job.to_s] %>
|
74
75
|
<tr class="<%= enabled ? "" : "disabled" %>">
|
75
76
|
<td><%= h(job) %></td>
|
@@ -87,7 +88,7 @@
|
|
87
88
|
<form method="POST" style="margin-top: 20px; margin-bottom: 10px;">
|
88
89
|
<%= csrf_tag %>
|
89
90
|
<div>
|
90
|
-
<button type="submit" name="<%= enabled_str
|
91
|
+
<button type="submit" name="<%= enabled_str %>" value="<%= job.id %>" data-confirm="Are you sure you want to <%= enabled_str %> this job?"><%= enabled_str.capitalize %></button>
|
91
92
|
</div>
|
92
93
|
</form>
|
93
94
|
</td>
|
@@ -99,15 +100,15 @@
|
|
99
100
|
<div>
|
100
101
|
<h3>Hosts</h3>
|
101
102
|
<ul>
|
102
|
-
<% @hosts.each do |host|
|
103
|
+
<% @hosts.each do |host| %>
|
103
104
|
<li>
|
104
|
-
<strong><%= h(host[:host])
|
105
|
+
<strong><%= h(host[:host]) %></strong> <em>(PID <%= host[:pid] %>)</em>: last seen <%= relative_time(host[:last_seen]) %>.
|
105
106
|
</li>
|
106
|
-
<% end
|
107
|
+
<% end %>
|
107
108
|
</ul>
|
108
109
|
</div>
|
109
110
|
<div>
|
110
|
-
<small><%= product_version
|
111
|
+
<small><%= product_version %></small>
|
111
112
|
</div>
|
112
113
|
</body>
|
113
114
|
</html>
|
data/zhong.gemspec
CHANGED
@@ -16,20 +16,20 @@ Gem::Specification.new do |spec|
|
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0")
|
18
18
|
spec.bindir = "bin"
|
19
|
-
spec.executables =
|
19
|
+
spec.executables = ["zhong"]
|
20
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
-
spec.required_ruby_version = "
|
23
|
+
spec.required_ruby_version = ">= 2.5.0"
|
24
24
|
|
25
25
|
spec.add_dependency "suo"
|
26
26
|
spec.add_dependency "redis"
|
27
27
|
spec.add_dependency "tzinfo"
|
28
28
|
spec.add_dependency "activesupport"
|
29
29
|
|
30
|
-
spec.add_development_dependency "bundler", "~>
|
31
|
-
spec.add_development_dependency "rake", "~>
|
32
|
-
spec.add_development_dependency "rubocop", "~> 0.
|
30
|
+
spec.add_development_dependency "bundler", "~> 2.2"
|
31
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
32
|
+
spec.add_development_dependency "rubocop", "~> 0.49.0"
|
33
33
|
spec.add_development_dependency "minitest", "~> 5.5.0"
|
34
34
|
spec.add_development_dependency "codeclimate-test-reporter", "~> 0.4.7"
|
35
35
|
spec.add_development_dependency "sinatra", "~> 1.4", ">= 1.4.6"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zhong
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Elser
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: suo
|
@@ -72,42 +72,42 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '2.2'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '2.2'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rake
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '13.0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '13.0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rubocop
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 0.
|
103
|
+
version: 0.49.0
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 0.
|
110
|
+
version: 0.49.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: minitest
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -216,8 +216,6 @@ description: Reliable, distributed cron.
|
|
216
216
|
email:
|
217
217
|
- nick.elser@gmail.com
|
218
218
|
executables:
|
219
|
-
- console
|
220
|
-
- setup
|
221
219
|
- zhong
|
222
220
|
extensions: []
|
223
221
|
extra_rdoc_files: []
|
@@ -225,9 +223,9 @@ files:
|
|
225
223
|
- ".codeclimate.yml"
|
226
224
|
- ".eslintignore"
|
227
225
|
- ".eslintrc"
|
226
|
+
- ".github/workflows/CI.yml"
|
228
227
|
- ".gitignore"
|
229
228
|
- ".rubocop.yml"
|
230
|
-
- ".travis.yml"
|
231
229
|
- CHANGELOG.md
|
232
230
|
- Gemfile
|
233
231
|
- LICENSE.txt
|
@@ -260,24 +258,23 @@ homepage: https://www.github.com/nickelser/zhong
|
|
260
258
|
licenses:
|
261
259
|
- MIT
|
262
260
|
metadata: {}
|
263
|
-
post_install_message:
|
261
|
+
post_install_message:
|
264
262
|
rdoc_options: []
|
265
263
|
require_paths:
|
266
264
|
- lib
|
267
265
|
required_ruby_version: !ruby/object:Gem::Requirement
|
268
266
|
requirements:
|
269
|
-
- - "
|
267
|
+
- - ">="
|
270
268
|
- !ruby/object:Gem::Version
|
271
|
-
version:
|
269
|
+
version: 2.5.0
|
272
270
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
273
271
|
requirements:
|
274
272
|
- - ">="
|
275
273
|
- !ruby/object:Gem::Version
|
276
274
|
version: '0'
|
277
275
|
requirements: []
|
278
|
-
|
279
|
-
|
280
|
-
signing_key:
|
276
|
+
rubygems_version: 3.1.2
|
277
|
+
signing_key:
|
281
278
|
specification_version: 4
|
282
279
|
summary: Reliable, distributed cron.
|
283
280
|
test_files:
|