Skip to content

Commit 6a91939

Browse files
authored
fix(crons): Skip scheduled jobs with unsupported schedules (#3165)
1 parent fe83a79 commit 6a91939

4 files changed

Lines changed: 39 additions & 26 deletions

File tree

‎sentry-rails/lib/sentry/rails/solid_queue_recurring.rb‎

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ def monitor_for(task, job)
5252
return unless slug
5353

5454
config = Sentry::Cron::FugitSchedule.from_cron(cron_for(task))
55-
{ "slug" => slug, "crontab" => config&.schedule&.value, "timezone" => config&.timezone }.compact
55+
return unless config
56+
57+
{ "slug" => slug, "crontab" => config.schedule.value, "timezone" => config.timezone }.compact
5658
rescue StandardError => e
5759
Sentry.sdk_logger.error(Sentry::LOGGER_PROGNAME) { "Not monitoring Solid Queue recurring task #{task.key}: #{e.class}: #{e.message}" }
5860
nil
@@ -62,18 +64,17 @@ def perform(job)
6264
data = job.instance_variable_get(:@_sentry_recurring_task)
6365
return yield unless data && Sentry.initialized?
6466

65-
slug = data["slug"]
66-
if data["crontab"]
67-
cron_config = Sentry.configuration.cron
68-
monitor_config = Sentry::Cron::MonitorConfig.from_crontab(
69-
data["crontab"],
70-
timezone: data["timezone"],
71-
checkin_margin: cron_config.default_checkin_margin,
72-
max_runtime: cron_config.default_max_runtime
73-
)
74-
end
67+
return yield unless data["crontab"]
68+
69+
cron_config = Sentry.configuration.cron
70+
monitor_config = Sentry::Cron::MonitorConfig.from_crontab(
71+
data["crontab"],
72+
timezone: data["timezone"],
73+
checkin_margin: cron_config.default_checkin_margin,
74+
max_runtime: cron_config.default_max_runtime
75+
)
7576

76-
Sentry::Cron::MonitorCheckIns.with_check_in(slug, monitor_config: monitor_config) { yield }
77+
Sentry::Cron::MonitorCheckIns.with_check_in(data["slug"], monitor_config: monitor_config) { yield }
7778
end
7879

7980
def patch

‎sentry-rails/spec/active_job/solid_queue_recurring_spec.rb‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,10 @@ def perform
104104
expect(check_ins.first.monitor_config.to_h[:schedule]).to eq(type: :crontab, value: "*/15 * * * *")
105105
end
106106

107-
it "sends check-ins without a config for schedules Crons cannot express" do
107+
it "does not monitor schedules Crons cannot express" do
108108
run_task("every_ten_seconds", class: "ReportJob", schedule: "every 10 seconds")
109109

110-
expect(check_ins.map(&:status)).to eq([:in_progress, :ok])
111-
expect(check_ins.map(&:monitor_config)).to all(be_nil)
110+
expect(check_ins).to be_empty
112111
end
113112

114113
it "applies SolidQueue.time_zone to schedules without a zone" do

‎sentry-ruby/lib/sentry/rufus_scheduler.rb‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
module Sentry
4-
# Sends Crons check-ins for rufus-scheduler `cron`, `every` and `interval` jobs.
4+
# Sends Crons check-ins for rufus-scheduler `cron` and `every` jobs.
55
# Enable with `config.enabled_patches << :rufus_scheduler`.
66
module RufusScheduler
77
module Job
@@ -46,7 +46,7 @@ def sentry_monitor
4646
end
4747

4848
class << self
49-
# Returns [slug, monitor_config], or nil for jobs that aren't monitored (like `at`/`in`).
49+
# Returns [slug, monitor_config], or nil for jobs that aren't monitored (like `at`/`in`, or unsupported schedules).
5050
def monitor_for(job)
5151
return unless job.is_a?(::Rufus::Scheduler::RepeatJob)
5252
return if job.opts[:sentry_monitor] == false
@@ -61,7 +61,13 @@ def monitor_for(job)
6161
return
6262
end
6363

64-
[slug, monitor_config_for(job)]
64+
monitor_config = monitor_config_for(job)
65+
unless monitor_config
66+
Sentry.sdk_logger.debug(Sentry::LOGGER_PROGNAME) { "Not monitoring rufus-scheduler job #{slug}: its schedule can't be expressed as a Crons schedule." }
67+
return
68+
end
69+
70+
[slug, monitor_config]
6571
end
6672

6773
private
@@ -98,8 +104,7 @@ def monitor_config_for(job)
98104
when ::Rufus::Scheduler::EveryJob
99105
Sentry::Cron::FugitSchedule.from_seconds(job.frequency)
100106
end
101-
# IntervalJob waits `interval` after each run ends, so it has no fixed
102-
# schedule to monitor against.
107+
# IntervalJob waits `interval` after each run ends, so no fixed schedule matches it.
103108
end
104109
end
105110
end

‎sentry-ruby/spec/sentry/rufus_scheduler_spec.rb‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,26 @@ def monitor_config(type, schedule, **opts)
5959
expect(sentry_events.map(&:status)).to eq([:in_progress, :error])
6060
end
6161

62-
it "sends no config for cron lines Crons can't express" do
63-
expect(monitor_config(:cron, "*/10 * * * * *", name: "job")).to be_nil
64-
expect(sentry_events.count).to eq(2)
62+
it "does not monitor cron lines Crons can't express" do
63+
expect(schedule(:cron, "*/10 * * * * *", name: "job").call(true)).to eq(42)
64+
65+
expect(sentry_events).to be_empty
6566
end
6667

6768
it "sends an interval config for every jobs" do
6869
expect(monitor_config(:every, "2h", name: "job")[:schedule]).to eq(type: :interval, value: 2, unit: :hour)
6970
end
7071

71-
it "sends check-ins without config for interval jobs" do
72-
expect(monitor_config(:interval, "5m", name: "job")).to be_nil
73-
expect(sentry_events.count).to eq(2)
72+
it "does not monitor every jobs Crons can't express" do
73+
schedule(:every, "90s", name: "job").call(true)
74+
75+
expect(sentry_events).to be_empty
76+
end
77+
78+
it "does not monitor interval jobs" do
79+
expect(schedule(:interval, "5m", name: "job").call(true)).to eq(42)
80+
81+
expect(sentry_events).to be_empty
7482
end
7583

7684
it "does not monitor one-off jobs" do

0 commit comments

Comments
 (0)