|
1 | | -# Clockwork Web |
| 1 | +# Clockwork Web Plus |
2 | 2 |
|
3 | | -A web interface for [Clockwork](https://github.com/Rykian/clockwork) |
| 3 | +A fully compatible drop-in enhancement to [ankane/clockwork_web](https://github.com/ankane/clockwork_web), providing a modern web interface for [Clockwork](https://github.com/Rykian/clockwork) with fuzzy search, manual job run, overdue visibility, and hourly health checks. |
4 | 4 |
|
5 | | -[View the demo](https://clockwork.dokkuapp.com/) |
| 5 | +[](https://github.com/chaadow/clockwork_web_plus/actions/workflows/build.yml) |
| 6 | + |
| 7 | +## Preview |
| 8 | + |
| 9 | +<video src="https://github.com/user-attachments/assets/d145a4d5-834d-4c0d-9f11-397272b2d013" controls muted playsinline loop> |
| 10 | + Sorry, your browser doesn't support embedded videos. Here’s a <a href="https://github.com/user-attachments/assets/d145a4d5-834d-4c0d-9f11-397272b2d013">direct link</a>. |
| 11 | +</video> |
| 12 | + |
| 13 | +## Features |
| 14 | + |
| 15 | +### Core (from `clockwork_web`) |
6 | 16 |
|
7 | 17 | - see list of jobs |
8 | | -- monitor jobs |
9 | | -- disable jobs |
| 18 | +- monitor jobs ( when they were last run at) |
| 19 | +- Temporarily disable jobs |
10 | 20 |
|
11 | | -:tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource) |
| 21 | +### New compared to clockwork_web |
12 | 22 |
|
13 | | -[](https://github.com/ankane/clockwork_web/actions) |
| 23 | +- fuzzy find search across jobs |
| 24 | +- run any job immediately through the `Run now` button |
| 25 | +- view the Ruby implementation of each job |
| 26 | +- highlight overdue jobs at a glance |
| 27 | +- optional hourly health check callback with custom alerting |
14 | 28 |
|
15 | 29 | ## Installation |
16 | 30 |
|
17 | 31 | Add this line to your application’s Gemfile: |
18 | 32 |
|
19 | 33 | ```ruby |
20 | | -gem "clockwork_web" |
| 34 | +gem "clockwork_web_plus" |
21 | 35 | ``` |
22 | 36 |
|
| 37 | +> [!TIP] |
| 38 | +> Already using `clockwork_web`? Keep your existing `ClockworkWeb::Engine` mount and initializers—no renaming needed. `ClockworkWebPlus` aliases `ClockworkWeb`, so it works out of the box. |
| 39 | +
|
23 | 40 | And add it to your `config/routes.rb`. |
24 | 41 |
|
25 | 42 | ```ruby |
26 | | -mount ClockworkWeb::Engine, at: "clockwork" |
| 43 | +mount ClockworkWebPlus::Engine, at: "clockwork" |
27 | 44 | ``` |
28 | 45 |
|
29 | | -Be sure to secure the dashboard in production. |
| 46 | +> [!IMPORTANT] |
| 47 | +> Secure the dashboard in production. Protect access with Basic Auth, Devise, or your app’s auth layer to avoid exposing job controls and status. |
30 | 48 |
|
31 | 49 | To monitor and disable jobs, hook up Redis in an initializer. |
32 | 50 |
|
33 | 51 | ```ruby |
34 | | -ClockworkWeb.redis = Redis.new |
| 52 | +ClockworkWebPlus.redis = Redis.new |
35 | 53 | ``` |
36 | 54 |
|
37 | 55 | #### Basic Authentication |
38 | 56 |
|
39 | 57 | Set the following variables in your environment or an initializer. |
40 | 58 |
|
41 | 59 | ```ruby |
42 | | -ENV["CLOCKWORK_USERNAME"] = "andrew" |
| 60 | +ENV["CLOCKWORK_USERNAME"] = "chaadow" |
43 | 61 | ENV["CLOCKWORK_PASSWORD"] = "secret" |
44 | 62 | ``` |
45 | 63 |
|
| 64 | +> [!NOTE] |
| 65 | +> These are example credentials. Use environment-specific secrets and rotate them regularly. |
| 66 | +
|
46 | 67 | #### Devise |
47 | 68 |
|
48 | 69 | ```ruby |
49 | 70 | authenticate :user, ->(user) { user.admin? } do |
50 | | - mount ClockworkWeb::Engine, at: "clockwork" |
| 71 | + mount ClockworkWebPlus::Engine, at: "clockwork" |
51 | 72 | end |
52 | 73 | ``` |
53 | 74 |
|
| 75 | +> [!TIP] |
| 76 | +> Any authentication framework works—wrap the mount with whatever guard your app already uses for admin/ops access. |
| 77 | +
|
54 | 78 | ## Monitoring |
55 | 79 |
|
56 | 80 | ```ruby |
57 | | -ClockworkWeb.running? |
58 | | -ClockworkWeb.multiple? |
| 81 | +ClockworkWebPlus.running? |
| 82 | +ClockworkWebPlus.multiple? |
59 | 83 | ``` |
60 | 84 |
|
| 85 | +> [!NOTE] |
| 86 | +> `running?` reflects recent heartbeats. `multiple?` indicates multiple active Clockwork processes (based on heartbeat contention). |
| 87 | +
|
61 | 88 | ## Customize |
62 | 89 |
|
63 | 90 | Change clock path |
64 | 91 |
|
65 | 92 | ```ruby |
66 | | -ClockworkWeb.clock_path = Rails.root.join("clock") # default |
| 93 | +ClockworkWebPlus.clock_path = Rails.root.join("clock") # default |
67 | 94 | ``` |
68 | 95 |
|
| 96 | +> [!NOTE] |
| 97 | +> The default `clock_path` matches `clockwork_web`. Change it only if your clock file lives elsewhere. |
| 98 | +
|
69 | 99 | Turn off monitoring |
70 | 100 |
|
71 | 101 | ```ruby |
72 | | -ClockworkWeb.monitor = false |
| 102 | +ClockworkWebPlus.monitor = false |
| 103 | +``` |
| 104 | + |
| 105 | +> [!CAUTION] |
| 106 | +> Disabling monitoring stops heartbeats and multiple-process detection. The dashboard won’t show “running” status, but other features still work. |
| 107 | +
|
| 108 | +### Overdue Jobs & Health Checks |
| 109 | + |
| 110 | +The dashboard highlights overdue jobs based on schedule and last run. You can also configure an hourly health check to alert when jobs are overdue: |
| 111 | + |
| 112 | +```ruby |
| 113 | +ClockworkWebPlus.on_health_check = ->(overdue_jobs:) do |
| 114 | + # backlog contains array of hashes with details like: |
| 115 | + # { job:, should_have_run_at:, last_run:, period:, at: { hour:, min: } } |
| 116 | + if overdue_jobs.any? |
| 117 | + # send notification to Slack, email, etc. |
| 118 | + end |
| 119 | +end |
73 | 120 | ``` |
74 | 121 |
|
| 122 | +> [!NOTE] |
| 123 | +> Overdue detection uses `ClockworkWebPlus.warning_threshold` (default: 300 seconds). |
| 124 | +> - For `@at` schedules: a job is overdue when the most recent scheduled time has passed by more than `warning_threshold` and the job hasn’t run since that time. |
| 125 | +> - For periodic jobs (no `@at`): a job is overdue when `now > last_run + period + warning_threshold`. |
| 126 | +> |
| 127 | +> Example: |
| 128 | +> ```ruby |
| 129 | +> # consider jobs overdue 10 minutes after their expected time |
| 130 | +> ClockworkWebPlus.warning_threshold = 600 |
| 131 | +> ``` |
| 132 | +
|
| 133 | +> [!IMPORTANT] |
| 134 | +> With Redis configured, the health check runs at most once per hour across processes. Without Redis, throttling is per-process and approximate. |
| 135 | +
|
75 | 136 | ## History |
76 | 137 |
|
77 | 138 | View the [changelog](CHANGELOG.md) |
78 | 139 |
|
| 140 | +## Compatibility |
| 141 | +
|
| 142 | +This gem is a drop-in replacement for `clockwork_web`. For backward compatibility, the original namespace is aliased: |
| 143 | +
|
| 144 | +```ruby |
| 145 | +# Both of these work: |
| 146 | +mount ClockworkWebPlus::Engine, at: "clockwork" |
| 147 | +mount ClockworkWeb::Engine, at: "clockwork" |
| 148 | +``` |
| 149 | +
|
| 150 | +> [!TIP] |
| 151 | +> Adopting this gem can be as simple as swapping the gem name in your Gemfile. Your existing `ClockworkWeb` mounts and initializers continue to work unchanged. |
| 152 | +
|
79 | 153 | ## Contributing |
80 | 154 |
|
81 | 155 | Everyone is encouraged to help improve this project. Here are a few ways you can help: |
82 | 156 |
|
83 | | -- [Report bugs](https://github.com/ankane/clockwork_web/issues) |
84 | | -- Fix bugs and [submit pull requests](https://github.com/ankane/clockwork_web/pulls) |
| 157 | +- [Report bugs](https://github.com/chaadow/clockwork_web_plus/issues) |
| 158 | +- Fix bugs and [submit pull requests](https://github.com/chaadow/clockwork_web_plus/pulls) |
85 | 159 | - Write, clarify, or fix documentation |
86 | 160 | - Suggest or add new features |
87 | 161 |
|
88 | 162 | To get started with development: |
89 | 163 |
|
90 | 164 | ```sh |
91 | | -git clone https://github.com/ankane/clockwork_web.git |
92 | | -cd clockwork_web |
| 165 | +git clone https://github.com/chaadow/clockwork_web_plus.git |
| 166 | +cd clockwork_web_plus |
93 | 167 | bundle install |
94 | 168 | bundle exec rake test |
95 | 169 | ``` |
0 commit comments