jobtick 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef3818e1dd990c8e9eb1a46b5ed83dcd91fa62e7487adecc999173a855de990a
4
- data.tar.gz: 1f5fa1a374a40d710d6ba193e46b0adef866546ec9f4e7b192d4801040c9975f
3
+ metadata.gz: dff65ac46c3a2ce39e670a9b940726f11e7f72ab5695812031417097fbf6e2d6
4
+ data.tar.gz: bb6044dd0c4c43c9e956de1eec4a5f2032ba6787aebfb9f1ddae8267ff79c35a
5
5
  SHA512:
6
- metadata.gz: af465b7b4d392967a684e066c018d8f288b032a22590aa37f66e332b293fb0fb9c2964dc6e43ec5513b89d7e99150542cb0c475fd48b1dfe1dc25c582bd65dcd
7
- data.tar.gz: 1c42f458a2ba090e5afca3de65dba113e0fdf1c0db466fe411b97cdc068cba45a65c913bacce13bfa05ebe4724fd001f8fee9568fbd72da2490f0714f5c3e45d
6
+ metadata.gz: 80ac95fe4fa508de3656ed0cc187657e9e3c2be0f68a76451dc4e1b0633a51b81e4f86ec0665163278daeb12d64e374f0496f6a1c1c7596aac673519cdc6fc87
7
+ data.tar.gz: c0ce19f6cc1b5cf3f7bad98a38448bf012dafb09dd74fade6934b797ab94f05f82971d5e49cad5a3067f862b29d3cb65f373d8b139468d5912cbc7f7cdb15271
data/README.md CHANGED
@@ -61,21 +61,6 @@ No changes to individual job files. No manual monitor creation. No names to keep
61
61
 
62
62
  ## What gets monitored
63
63
 
64
- ### Whenever (`config/schedule.rb`)
65
-
66
- ```ruby
67
- # Your existing schedule.rb — no changes needed
68
- every 1.day, at: '2:00 am' do
69
- runner 'InvoiceJob.perform_later'
70
- end
71
-
72
- every :hour do
73
- runner 'SyncInventoryJob.perform_later'
74
- end
75
- ```
76
-
77
- JobTick reads this file at deploy time and creates a monitor for each job automatically.
78
-
79
64
  ### Solid Queue (`config/recurring.yml`)
80
65
 
81
66
  ```yaml
@@ -89,12 +74,17 @@ sync_exchange_rates:
89
74
  schedule: every hour
90
75
  ```
91
76
 
92
- Each entry becomes a monitor. If `NightlyReportJob` doesn't run within its expected window, you get an alert.
77
+ At boot, JobTick reads this file and registers a monitor for each entry. It then installs an `around_perform` hook into `ActiveJob::Base` so every job execution automatically sends `started`, `completed`, and `failed` pings. No changes to your job files.
93
78
 
94
79
  ### Sidekiq periodic jobs
95
80
 
81
+ Supports both **sidekiq-cron** and **Sidekiq::Periodic**:
82
+
96
83
  ```ruby
97
- # Your existing Sidekiq config no changes needed
84
+ # sidekiq-cron loaded from config/sidekiq_cron.yml or in an initializer
85
+ Sidekiq::Cron::Job.create(name: 'Nightly Cleanup', cron: '0 2 * * *', class: 'NightlyCleanupWorker')
86
+
87
+ # Sidekiq::Periodic
98
88
  Sidekiq.configure_server do |config|
99
89
  config.periodic do |mgr|
100
90
  mgr.register('0 * * * *', HourlyDigestWorker)
@@ -103,6 +93,30 @@ Sidekiq.configure_server do |config|
103
93
  end
104
94
  ```
105
95
 
96
+ JobTick installs a server middleware that wraps every job execution. For native Sidekiq workers (`Sidekiq::Worker` subclasses) pings are sent by the middleware. For Active Job workers dispatched through Sidekiq, pings are sent by the `around_perform` hook instead, so nothing is double-counted.
97
+
98
+ ### Whenever (`config/schedule.rb`)
99
+
100
+ Whenever schedules jobs as cron shell commands, so there is no Ruby hook point to instrument automatically. One setup step is required: run the generator and update your `config/schedule.rb` to use the `jobtick_runner` and `jobtick_rake` job types instead of the built-in `runner` and `rake`:
101
+
102
+ ```
103
+ bundle exec rake jobtick:whenever:setup
104
+ ```
105
+
106
+ This prints the two `job_type` definitions to add to the top of your schedule file, then use them in place of the standard types:
107
+
108
+ ```ruby
109
+ every 1.day, at: '2:00 am' do
110
+ jobtick_runner 'InvoiceJob.perform_later', monitor_key: 'whenever.invoice_job'
111
+ end
112
+
113
+ every :hour do
114
+ jobtick_rake 'reports:sync', monitor_key: 'whenever.reports_sync'
115
+ end
116
+ ```
117
+
118
+ The job types wrap execution with `curl` pings to the JobTick API, so no changes to individual job classes are needed.
119
+
106
120
  ---
107
121
 
108
122
  ## What you get
@@ -121,7 +135,7 @@ end
121
135
 
122
136
  ## Requirements
123
137
 
124
- - Ruby >= 3.2
138
+ - Ruby >= 3.3
125
139
  - Rails >= 7.0
126
140
  - One or more of: Whenever, Solid Queue, Sidekiq
127
141
 
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JobTick
4
+ module Hooks
5
+ module ActiveJob
6
+ def self.included(base)
7
+ base.around_perform do |job, block|
8
+ key = JobTick.monitor_key_for(job.class.name)
9
+ if key
10
+ JobTick::Monitor.run(key) { block.call }
11
+ else
12
+ block.call
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JobTick
4
+ module Middleware
5
+ class Sidekiq
6
+ def call(_worker, job, _queue)
7
+ # Active Job wrappers are handled by the around_perform hook
8
+ return yield if job["wrapped"]
9
+
10
+ key = JobTick.monitor_key_for(job["class"])
11
+ return yield unless key
12
+
13
+ JobTick::Monitor.run(key) { yield }
14
+ end
15
+
16
+ def self.install
17
+ ::Sidekiq.configure_server do |config|
18
+ config.server_middleware do |chain|
19
+ chain.add(JobTick::Middleware::Sidekiq)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -7,6 +7,9 @@ module JobTick
7
7
  next unless JobTick.config.enabled
8
8
 
9
9
  JobTick::Registry.sync
10
+
11
+ ::ActiveJob::Base.include(JobTick::Hooks::ActiveJob) if defined?(::ActiveJob::Base)
12
+ JobTick::Middleware::Sidekiq.install if defined?(::Sidekiq)
10
13
  end
11
14
  end
12
15
 
@@ -9,6 +9,10 @@ module JobTick
9
9
  Parsers::Sidekiq.parse
10
10
  ].flatten.compact
11
11
 
12
+ JobTick.monitor_map = monitors.each_with_object({}) do |m, map|
13
+ map[m[:task]] = m[:key] if m[:task]
14
+ end
15
+
12
16
  return [] if monitors.empty?
13
17
 
14
18
  app_name = Rails.application.class.module_parent_name if defined?(Rails)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JobTick
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/jobtick.rb CHANGED
@@ -9,6 +9,8 @@ require_relative "jobtick/parsers/whenever"
9
9
  require_relative "jobtick/parsers/solid_queue"
10
10
  require_relative "jobtick/parsers/sidekiq"
11
11
  require_relative "jobtick/registry"
12
+ require_relative "jobtick/hooks/active_job"
13
+ require_relative "jobtick/middleware/sidekiq"
12
14
  require_relative "jobtick/railtie" if defined?(Rails::Railtie)
13
15
 
14
16
  module JobTick
@@ -31,9 +33,22 @@ module JobTick
31
33
  defined?(Rails) ? Rails.logger : Logger.new($stdout)
32
34
  end
33
35
 
36
+ def monitor_map
37
+ @monitor_map ||= {}
38
+ end
39
+
40
+ def monitor_map=(map)
41
+ @monitor_map = map
42
+ end
43
+
44
+ def monitor_key_for(class_name)
45
+ monitor_map[class_name.to_s]
46
+ end
47
+
34
48
  def reset!
35
49
  @config = nil
36
50
  @client = nil
51
+ @monitor_map = {}
37
52
  end
38
53
  end
39
54
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jobtick
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clearstack Labs
@@ -39,6 +39,8 @@ files:
39
39
  - lib/jobtick.rb
40
40
  - lib/jobtick/client.rb
41
41
  - lib/jobtick/configuration.rb
42
+ - lib/jobtick/hooks/active_job.rb
43
+ - lib/jobtick/middleware/sidekiq.rb
42
44
  - lib/jobtick/monitor.rb
43
45
  - lib/jobtick/parsers/sidekiq.rb
44
46
  - lib/jobtick/parsers/solid_queue.rb