Commit Graph

153 Commits

Author SHA1 Message Date
Ryuta Kamizono
e0e64e9474 Fix typo in activejob/CHANGELOG.md [ci-skip] 2022-08-29 15:34:01 +09:00
Sam Bostock
bc1f323338
Add ActiveJob::Serializers::BigDecimalSerializer
Previously, BigDecimal was listed as not needing a serializer.  However,
when used with an adapter storing the job arguments as JSON, it would get
serialized as a simple String, resulting in deserialization also producing
a String (instead of a BigDecimal).

By using a serializer, we ensure the round trip is safe.

During upgrade deployments of applications with multiple replicas making use of
BigDecimal job arguments with a queue adapter serializing to JSON, there exists
a possible race condition, whereby a "new" replica enqueues a job with an
argument serialized using `BigDecimalSerializer`, and an "old" replica fails to
deserialize it (as it does not have `BigDecimalSerializer`).

Therefore, to ensure safe upgrades, serialization will not use
`BigDecimalSerializer` until `config.active_job.use_big_decimal_serializer` is
enabled, which can be done safely after successful deployment of Rails 7.1.

This option will be removed in Rails 7.2, when it will become the default.
2022-07-19 15:31:41 -04:00
Jeremy Daer
8d9d8013ca Preserve job.enqueued_at timestamp precision
* Allows instrumenters to more accurately deduce queue wait time
* Retains IS08601 compatibility

References #39698
2022-07-12 18:13:16 -07:00
Gannon McGibbon
02444d9267 Add --parent option to job generator to specify parent class of job.
Example:

`bin/rails g job process_payment --parent=payment_job` generates:

```ruby
class ProcessPaymentJob < PaymentJob
  # ...
end
```
2022-07-05 20:55:38 -04:00
Gannon McGibbon
5f57c7d352 Add more detailed description to job generator 2022-06-13 14:44:28 -05:00
Gannon McGibbon
3dad2919d5 Rename behaviour to behavior in documentation 2022-05-26 17:14:18 -04:00
Jonathan Hefner
9574a39a7a Add db_runtime to Active Job instrumentation
This adds `:db_runtime` to `perform.active_job` notification payloads,
which is the total time taken by database queries while performing a
job.  This value can be used to better understand how a job's time is
spent.

This is similar to the `:db_runtime` value added to
`process_action.action_controller` notification payloads by
`ActiveRecord::Railties::ControllerRuntime`.

Closes #35354.

Co-authored-by: Cory Gwin <gwincr11@github.com>
2022-05-19 14:09:21 -05:00
Damir Zekić
c7b4a8b4ba Update CHANGELOG 2022-03-21 13:43:11 +01:00
Jean Boussier
4ca5aff9f0 Add missing bigdecimal require in ActiveJob::Arguments
Fix: https://github.com/rails/rails/issues/44399

Could cause `uninitialized constant ActiveJob::Arguments::BigDecimal (NameError)`
when loading Active Job in isolation.
2022-02-12 09:54:41 +01:00
Rafael Mendonça França
6fb54c00e4
Merge PR #43066 2022-01-06 16:53:31 +00:00
Rafael Mendonça França
83d85b2207
Start Rails 7.1 development 2021-12-07 15:52:30 +00:00
Rafael Mendonça França
7c788e9175
Remove deprecated :return_false_on_aborted_enqueue option 2021-11-19 23:15:58 +00:00
Rafael Mendonça França
10bd5e59c3
Removed deprecated behavior that was not halting after_enqueue/after_perform callbacks when a previous callback was halted with throw :abort. 2021-11-17 21:51:17 +00:00
Veerpal Brar
0f259e702d Raise error when serializing an anonymous class.
The ModuleSerializer does not support serializing anonymous classes
because when we try to deserialize the anonymous class, it wouldn't
know which class to use (since class name is nil).

For this reason, ModuleSerialzier now raises an error if the class
name is nil. Previously, ModuleSerializer would raise an `undefined
method `constantize' for nil:NilClass` error during deserialization.
It's not clear why the deserialization failed from the error.

In this commit, we raise an explicit error when trying to serialize
an anonymous class indicating this behaviour is not supported.
2021-10-13 11:55:23 -04:00
Rafael Mendonça França
d177551c30
Preparing for 7.0.0.alpha2 release 2021-09-15 18:22:51 -04:00
Rafael Mendonça França
9b7be48212
Preparing for 7.0.0.alpha1 release 2021-09-15 17:55:08 -04:00
Jacopo
20545fc820 Allow testing discard_on/retry_on ActiveJob::DeserializationError
Previously in `perform_enqueued_jobs`, `deserialize_arguments_if_needed`
was called before calling `perform_now`. When a record no longer exists
and is serialized using GlobalID this led to raising
an `ActiveJob::DeserializationError` before reaching `perform_now` call.
This behaviour makes difficult testing the job `discard_on/retry_on` logic.

Now `deserialize_arguments_if_needed` call is postponed to when `perform_now`
is called.

Example:

```ruby
class UpdateUserJob < ActiveJob::Base
  discard_on ActiveJob::DeserializationError

  def perform(user)
    # ...
  end
end

User.destroy_all
assert_nothing_raised do
  perform_enqueued_jobs only: UpdateUserJob
end
assert_no_enqueued_jobs
```

Before this changes the test will fail, now it passes.
2021-08-23 21:16:56 +02:00
Daniel Morton
94ccd5410d
retry_on parameter attempts now accepts :unlimited (#41761)
In some applications, some classes of errors may be raised during the
execution of a job which the developer would want to retry forever.

These classes of errors would most likely be infrastructure problems that
the developer knows will be resolved eventually but may take a variable
amount of time or errors where due to application business logic, there
could be something temporarily blocking the job from executing, like a
resource that is needed for the job being locked for a lengthy amount of
time.

While an arbitrarily large number of attempts could previously be passed,
this is inexpressive as sometimes the developer may just need the job to
continue to be retried until it eventually succeeds. Without this,
developers would need to include additional code to handle the situation
where the job eventually fails its attempts limit and has to be re-enqueued
manually.

As with many things this should be used with caution and only for errors
that the developer knows will definitely eventually be resolved, allowing
the job to continue.

[Daniel Morton + Rafael Mendonça França]
2021-07-28 18:32:19 -04:00
Ryuta Kamizono
e50b0e3ab3 Fixup CHANGELOGs [ci skip] 2021-07-21 10:08:08 +09:00
Wojciech Wnętrzak
e2db5f205a
Added possibility to check on :priority in test helper methods 2021-07-15 07:46:21 +02:00
Dirkjan Bussink
0523532a3c
Always use OpenSSL constants for Digest operations
As also previously discussed in
https://github.com/rails/rails/pull/40770#issuecomment-748347066, this
moves the usage of Digest constants to always use the OpenSSL version of
those Digest implementations.
2021-06-30 13:57:54 +02:00
Felipe Sateler
5bb5453cd7 Add Range serializer for ActiveJob
Missing Range support means users need to add start/finish pair
of arguments instead of simply passing a Range object.
2021-05-15 23:22:26 -04:00
Ryuta Kamizono
f8b354bf3b Fix typo s/adapaters/adapters/ [ci skip] 2021-02-07 05:41:07 +09:00
Daniel Morton
ee60ce5606 Communicate enqueue failures to callers of perform_later
There is presently no clean way of telling a caller of `perform_later`
the reason why a job failed to enqueue. When the job is enqueued
successfully, the job object itself is returned, but when the job can
not be enqueued, only `false` is returned. This does not allow callers
to distinguish between classes of failures.

One important class of failures is when the job backend experiences a
network partition when communicating with its underlying datastore. It
is entirely possible for that network partition to recover and as such,
code attempting to enqueue a job may wish to take action to reenqueue
that job after a brief delay. This is distinguished from the class of
failures where due a business rule defined in a callback in the
application, a job fails to enqueue and should not be retried.

This PR changes the following:

- Allows a block to be passed to the `perform_later` method. After the
  `enqueue` method is executed, but before the result is returned, the
  job will be yielded to the block. This allows the code invoking the
  `perform_later` method to inspect the job object, even in failure
  scenarios.

- Adds an exception `EnqueueError` which job adapters can raise if they
  detect a problem specific to their underlying implementation or
  infrastructure during the enqueue process.

- Adds two properties to the job base class: `successfully_enqueued` and
  `enqueue_error`. `enqueue_error` will be populated by the `enqueue`
  method if it rescues an `EnqueueError` raised by the job backend.
  `successfully_enqueued` will be true if the job is not rejected by
  callbacks and does not cause the job backend to raise an
  `EnqueueError` and will be `false` otherwise.

This will allow developers to do something like the following:

    MyJob.perform_later do |job|
      unless job.successfully_enqueued?
        if job.enqueue_error&.message == "Redis was unavailable"
          # invoke some code that will retry the job after a delay
        end
      end
    end
2021-02-05 16:32:43 -05:00
Rafael Mendonça França
bea721aa91
Merge remote-tracking branch 'origin/main' into skip-logging-rescuable-exceptions 2021-02-02 01:09:06 +00:00
Rafael Mendonça França
efa64bb295
Refactor the code to keep instrumentation and log inside the modules
Use inheritance to keep the behavior in the right modules.

The order of Instrumentation and Logging had to change to be
flipped to keep the current behavior.
2021-02-02 01:07:24 +00:00
Étienne Barrié
142ae54e54 Allow jobs to rescue all exceptions
Before this commit, only StandardError exceptions can be handled by
rescue_from handlers.

This changes the rescue clause to catch all Exception objects, allowing
rescue handlers to be defined for Exception classes not inheriting from
StandardError.

This means that rescue handlers that are rescuing Exceptions outside of
StandardError exceptions may rescue exceptions that were not being
rescued before this change.

Co-authored-by: Adrianna Chang <adrianna.chang@shopify.com>
2021-01-23 08:35:51 -05:00
HU Hailin
b8baeb44ae change the perform instrumentation to wrap perform_now instead of the perform method. 2020-12-31 11:13:03 +09:00
HU Hailin
0c6f32a9f9 Skip logging rescuable exceptions which are defined in rescue_from/retry_on/discard_on.
Update activejob/CHANGELOG.md

Co-authored-by: Rafael França <rafael@franca.dev>
2020-12-31 11:12:58 +09:00
Rafael Mendonça França
59f7f5889e
Start Rails 6.2 development 🎉 2020-12-03 01:35:29 +00:00
Ryuta Kamizono
53331b478d Fix typos [ci skip] 2020-11-09 15:23:39 +09:00
Rafael Mendonça França
8389f9902c
Preparing for 6.1.0.rc1 release 2020-11-02 21:12:47 +00:00
Guo Xiang Tan
bda10bf3a8
Recover precision when serializing Time, TimeWithZone and DateTime. 2020-10-30 19:58:13 +00:00
Rafael Mendonça França
fd24cf1c5d
Return false when enqueuing a job is aborted 2020-10-30 00:25:31 +00:00
Ryuta Kamizono
6f2126c760 Fixup CHANGELOGs [ci skip] 2020-04-15 21:23:24 +09:00
Rafael Mendonça França
855c9897eb
Move CHANGELOG entry to the top 2020-04-08 17:22:38 -04:00
Rafael Mendonça França
d16396e1ce
Merge pull request #38605 from dmitry/issue-38584
While using perform_enqueued_jobs enqueued jobs must be stored as well
2020-04-08 17:21:57 -04:00
Rafael Mendonça França
d9dc569d5b
Merge pull request #38749 from etiennebarrie/perform_enqueued_jobs_only_once
Perform enqueued jobs only once
2020-03-19 18:30:16 -04:00
Étienne Barrié
c6d621d132 Remove jobs from queue when performing in tests
This makes sure jobs don't run twice if `perform_enqueued_jobs` is
called twice without a block.

This also mimics the behavior of using `perform_enqueued_jobs` with a
block, where at the end of the block performed jobs are not in
`enqueued_jobs` but instead in `performed_jobs`.
2020-03-16 15:09:33 -04:00
Rafael França
d2d8b2892d
Merge pull request #38702 from aditya-vector/activejob-jitter-documentation-update
Updates to ActiveJob::Exceptions.retry_on with jitter documentation [skip ci]
2020-03-11 13:43:19 -04:00
Aditya Narsapurkar
895c39fe96 Updates to ActiveJob::Exceptions.retry_on with jitter documentation [skip ci]
- Changelog updated
- Method documentation updated
2020-03-11 21:49:55 +05:30
Edouard CHIN
17e304def8 AJ perform_enqueued_jobs shouldn't perform job retries:
- ### Problem

  If we use `perform_enqueued_jobs` without a block, a job that
  uses a retry mechanism to reeenqueue itself would get performed
  right away.
  This behaviour make sense when using `perform_enqueued_jobs` with
  a block.

  However I'm expecting `perform_enqueued_jobs` without a block to
  perform jobs that are **already** in the queue not the ones that
  will get enqueued afterwards.

  ### Solution

  Dup the array of jobs given to avoid future mutation.
2020-03-09 19:46:11 -04:00
Wojciech Wnętrzak
d12a31b193
Add support for que name to Que adapter.
Co-authored-by: Brad Nauta <bradnauta@gmail.com>
2020-03-04 13:50:13 +01:00
dmitry
7e6e6eb56f While using perform_enqueued_jobs enqueued jobs must be stored as well #38584 2020-02-28 13:32:06 +01:00
Ryuta Kamizono
1d3eb7be13 Fixup CHANGELOGs [ci skip] 2020-02-25 14:14:54 +09:00
Douglas Lara
10803d6985 fix typos 2020-01-15 00:11:40 -03:00
Edouard CHIN
bbfab0b33a Don't run AJ after_enqueue / after_perform when chain is halted:
- ### Problem

  ```ruby
    MyJob < ApplicationJob
      before_enqueue { throw(:abort) }
      after_enqueue { # enters here }
    end
  ```
  I find AJ behaviour on after_enqueue and after_perform callbacks
  weird as they get run even when the callback chain is halted.
  It's counter intuitive to run the after_enqueue callbacks even
  though the job wasn't event enqueued.

  ### Solution

  In Rails 6.2, I propose to make the new behaviour the default
  and stop running after callbacks when the chain is halted.
  For application that wants this behaviour now or in 6.1
  they can do so by adding the `config.active_job.skip_after_callbacks_if_terminated = true`
  in their configuration file.
2019-12-09 17:17:23 +01:00
Edouard CHIN
0d3aec4969 Fix ActiveJob logging when callback chain is halted:
- ### Problem

  ActiveJob will always log "Enqueued MyJob (Job ID) ..." even
  if the job doesn't get enqueued through the adapter.
  Same problem happens when performing a Job, "Performed MyJob (Job ID) ..." will be logged even when job wasn't performed at all.
  This situation can happen either if the callback chain is terminated
  (before_enqueue throwing an `abort`) or if an exception is raised.

  ### Solution

  Check if the callback chain is aborted/exception is raised, and  log accordingly.
2019-12-09 16:17:55 +01:00
Anthony Ross
5f7621878d Add jitter to :exponentially_longer
Prior to this change, exponentially_longer had adverse consequences
during system-wide downstream failures.  This change adds a random value to the
back off calculation in order to prevent the thundering herd
problem, whereby all retry jobs would retry at the same time.

Specifically this change adds a jitter option to retry_on to enable users of it to
scope the randomness calculation to a reasonable amount.  The default is
15% of the exponential back off calculation.
2019-11-27 16:03:11 -08:00
Ryuta Kamizono
214f439343 Fixup CHANGELOGs [ci skip] 2019-11-24 09:20:00 +09:00