@@ -210,6 +210,94 @@ defmodule Sentry.Integrations.Oban.ErrorReporterTest do
210210 assert [ event ] = Sentry.Test . pop_sentry_reports ( )
211211 assert event . tags . custom_tag == "custom_value"
212212 end
213+
214+ test "skip_retries_callback skips when callback returns true" do
215+ job =
216+ % { "id" => "123" , "entity" => "user" , "type" => "delete" }
217+ |> MyWorker . new ( )
218+ |> Ecto.Changeset . apply_action! ( :validate )
219+
220+ reason = % RuntimeError { message: "oops" }
221+
222+ Sentry.Test . start_collecting ( )
223+
224+ job_attempt_1 = Map . merge ( job , % { attempt: 1 , max_attempts: 3 } )
225+
226+ # Callback returns true -> skip reporting
227+ assert :ok =
228+ ErrorReporter . handle_event (
229+ [ :oban , :job , :exception ] ,
230+ % { } ,
231+ % { job: job_attempt_1 , kind: :error , reason: reason , stacktrace: [ ] } ,
232+ skip_retries_callback: fn _worker , job -> job . attempt < job . max_attempts end
233+ )
234+
235+ assert [ ] = Sentry.Test . pop_sentry_reports ( )
236+
237+ # Final attempt: callback returns false -> report
238+ job_attempt_3 = Map . merge ( job , % { attempt: 3 , max_attempts: 3 } )
239+
240+ assert :ok =
241+ ErrorReporter . handle_event (
242+ [ :oban , :job , :exception ] ,
243+ % { } ,
244+ % { job: job_attempt_3 , kind: :error , reason: reason , stacktrace: [ ] } ,
245+ skip_retries_callback: fn _worker , job -> job . attempt < job . max_attempts end
246+ )
247+
248+ assert [ event ] = Sentry.Test . pop_sentry_reports ( )
249+ assert event . original_exception == % RuntimeError { message: "oops" }
250+ assert event . tags . oban_worker == "Sentry.Integrations.Oban.ErrorReporterTest.MyWorker"
251+ end
252+
253+ test "skip_retries_callback receives worker module and job" do
254+ job =
255+ % { "id" => "123" , "entity" => "user" , "type" => "delete" }
256+ |> MyWorker . new ( )
257+ |> Ecto.Changeset . apply_action! ( :validate )
258+
259+ reason = % RuntimeError { message: "oops" }
260+ test_pid = self ( )
261+
262+ Sentry.Test . start_collecting ( )
263+
264+ assert :ok =
265+ ErrorReporter . handle_event (
266+ [ :oban , :job , :exception ] ,
267+ % { } ,
268+ % { job: job , kind: :error , reason: reason , stacktrace: [ ] } ,
269+ skip_retries_callback: fn worker , received_job ->
270+ send ( test_pid , { :callback_args , worker , received_job } )
271+ false
272+ end
273+ )
274+
275+ assert_receive { :callback_args , worker , received_job }
276+ assert worker == MyWorker
277+ assert received_job == job
278+ end
279+
280+ test "skip_retries_callback reports when callback returns false" do
281+ Sentry.Test . start_collecting ( )
282+
283+ emit_telemetry_for_failed_job ( :error , % RuntimeError { message: "oops" } , [ ] ,
284+ skip_retries_callback: fn _worker , _job -> false end
285+ )
286+
287+ assert [ event ] = Sentry.Test . pop_sentry_reports ( )
288+ assert event . original_exception == % RuntimeError { message: "oops" }
289+ end
290+
291+ test "skip_retries_callback handles errors gracefully and defaults to reporting" do
292+ Sentry.Test . start_collecting ( )
293+
294+ emit_telemetry_for_failed_job ( :error , % RuntimeError { message: "oops" } , [ ] ,
295+ skip_retries_callback: fn _worker , _job -> raise "callback error" end
296+ )
297+
298+ assert [ event ] = Sentry.Test . pop_sentry_reports ( )
299+ assert event . original_exception == % RuntimeError { message: "oops" }
300+ end
213301 end
214302
215303 ## Helpers
0 commit comments