Commit Graph

280 Commits

Author SHA1 Message Date
George Ma
9b069eed46 Add regression test for memoized queue adapter 2024-05-14 13:06:48 -04:00
Alex Ghiculescu
2194a738c7 Active Job: Correctly use the desired test adapter in tests 2024-05-09 17:35:50 +10:00
fatkodima
702638291c
Fix tests without assertions in the framework 2024-04-30 23:29:30 +00:00
Jean Boussier
afa019835b Fix ActiveJob::EnqueueAfterTransactionCommit API
Fix: https://github.com/rails/rails/pull/51426#issuecomment-2042611790

`perform_later` is supposed to return the Job instance on success,
and `false` on error.

When the `enqueue` is automatically delayed, it's of course impossible
to predict if the actual queueing will succeed, but for backward compatibility
reasons, it's best to assume it will.

If necessary, you can hold onto the job instance and check for
`#successfully_enqueued?` after the transaction has completed.
2024-04-10 09:20:12 +02:00
Jean Boussier
e922c59207 Implement Active Job enqueue_after_transaction_commit
A fairly common mistake with Rails is to enqueue a job from inside a
transaction, with a record as argumemnt, which then lead to a RecordNotFound
error when picked up by the queue.

This is even one of the arguments advanced for job runners backed by the
database such as `solid_queue`, `delayed_job` or `good_job`.

But relying on this is undesirable in my opinion as it makes the Active Job
abstraction leaky, and if in the future you need to migrate to another backend
or even just move the queue to a separate database, you may experience a lot of
race conditions of the sort.

To resolve this problem globally, we can make Active Job optionally transaction
aware, and automatically defer job queueing to `after_commit`.

Co-Authored-By: Cristian Bica <cristian.bica@gmail.com>
2024-04-03 16:32:16 +02:00
Jean Boussier
50daadaa71 Update test suite for compatibility with Ruby 3.4-dev
https://bugs.ruby-lang.org/issues/19117 and https://bugs.ruby-lang.org/issues/16495
slightly change how backtrace are rendered which makes a few tests fail.
2024-02-16 11:55:44 +01:00
Rafael Mendonça França
154f7c2181
Register autoload for ActiveJob::Arguments
Since #50715, there are cases where `ActiveJob::Arguments` is used
but not required anymore in the test environment. This could be a
test for a custom argument serializer.

One solution could be to add a require "active_job/arguments" in
all the usages, but that isn't a convention we follow in Rails.

Instead, let's register the autoload for `ActiveJob::Arguments` in
`active_job.rb` so that it's always available when needed.
2024-02-13 20:34:10 +00:00
John Hawthorn
1a4474e7ee
Revert "Do not overwrite AJ logger if it is supplied" 2023-12-04 17:32:50 -08:00
Hartley McGuire
d64acfdcac
Fix Active Job skips
Similarly to Action Mailbox, these tests didn't pass because the skip
patch was included before ActiveSupport::TestCase was defined. Moving
the patch to the bottom of the file fixes the issue.

Once the skip patch was fixed, all of the skips were due to differences
in adapters which aren't really test skips as much as tests that should
not ever run against those adapters.
2023-11-30 11:11:22 -05:00
Aerdayne
e03cc187f5 Do not overwrite AJ logger if it is supplied
Use conditional assignment within 'active_job.logger' initializer
2023-11-25 09:36:45 +01:00
Rafael Mendonça França
03dae98092
Remove deprecated :exponentially_longer value for the :wait in retry_on 2023-11-22 22:13:59 +00:00
Rafael Mendonça França
798289699d
Remove deprecated support to set numeric values to scheduled_at attribute 2023-11-22 22:13:06 +00:00
Rafael Mendonça França
2a761d23d2
Remove deprecated primitive serializer for BigDecimal arguments 2023-11-22 22:13:03 +00:00
Katherine Oelsner
e57e462a62 ActiveJob: fallback serializing String subclasses
https://github.com/rails/rails/pull/50090 broke serialization of String
subclasses that don't have serializers, like ActiveSupport::SafeBuffer.

Co-authored-by: John Hawthorn <john@hawthorn.email>
2023-11-20 23:41:19 +00:00
fatkodima
14578eaa4f Fix ActiveJob arguments serialization to correctly serialize String subclasses having custom serializers
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2023-11-18 01:55:24 +02:00
Jean Boussier
9497f47131 Turn skips into errors on Rails CI
We had a few cases of tests being skipped accidentally on CI
hence not bein ran for a long time.

Skipping make sense when running the test suite locally, e.g.
you may not have Redis or some other dependency running.

But on CI, a test not being ran should be considered an error.
2023-10-26 12:46:01 +02:00
Akhil G Krishnan
6eb93332c4 Typo fix in BigDecimal job arguments warning 2023-10-19 21:22:31 +05:30
Dustin Brown
be9d0f05a4 Don't include enqueuing info when job wasn't enqueued 2023-10-11 10:57:36 -07:00
Bart de Water
95b6fbd00f Stop building AS::Notifications::Event manually
It's possible since Rails 6 (3ea2857943dc294d7809930b4cc5b318b9c39577) to let the framework create Event objects, but the guides and docs weren't updated to lead with this example.

Manually instantiating an Event doesn't record CPU time and allocations, I've seen it more than once that people copy-pasting the example code get confused about these stats returning 0. The tests here show that - just like the apps I've worked on - the old pattern keeps getting copy-pasted.
2023-09-29 12:34:23 -04:00
Rafael Mendonça França
32eba97a08
Make sure scheduled_at is a Time object when asserting enqueued jobs
When the `:at` attribute is sent to the test adapter it is converted
to a float, and that float is what is added to the payload, so we
need to convert back to a Time object.

See:
8a37276416/activejob/lib/active_job/enqueuing.rb (L95)
8a37276416/activejob/lib/active_job/queue_adapters/test_adapter.rb (L34)
2023-09-27 15:29:11 +00:00
Ben Sheldon [he/him]
c919b474a7
Set, serialize, and deserialize Active Job scheduled_at as Time; deserialize enqueued_at as Time; deprecate setting scheduled_at= with numeric/epoch
Co-authored-by: Adam Pahlevi <adam.pahlevi@gmail.com>
2023-09-26 17:01:41 -07:00
Victor Mours
1bdabc1102 Clarify that the default retry strategy uses polynomial backoff and not exponential backoff 2023-09-16 00:51:14 +02:00
Shouichi Kamiya
7ff936570b Add tests for AJ events
Because events are documented but not tested.
2023-09-14 16:05:26 +09:00
Shouichi Kamiya
51ac8b9f6f Enable Minitest/LiteralAsActualArgument
There are assertions that expected/actual arguments are passed in the
reversed order by mistake. Enabling the LiteralAsActualArgument rule
prevents this mistake from happening.

The existing tests were auto-corrected by rubocop with a bit of
indentation adjustment.

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
2023-09-13 10:09:32 +09:00
Ben Sheldon
b1b7debaa3
Fix Active Job log message to correctly report a job failed to enqueue when the adapter raises an ActiveJob::EnqueueError 2023-09-02 07:52:43 -07:00
Rafael Mendonça França
53a3a95d01
Merge PR #48010 2023-08-21 17:39:03 +00:00
Jonathan del Strother
074d431493
Fix invalid durations in ActiveJob serialization
Durations that were round-tripped through ActiveJob::Arguments.serialize
would appear fine at a first glance, but trying to perform
duration-math on them would fail:

```
irb(main):001:0> d = ActiveJob::Arguments.deserialize(ActiveJob::Arguments.serialize([1.year]))[0]
=> 1 year
irb(main):002:0> d + 1.day
activesupport-6.1.4.4/lib/active_support/duration.rb:242:in `+': undefined method `merge' for [[:years, 1]]:Array (NoMethodError)
```
2023-08-13 11:27:16 +01:00
Yasuo Honda
d867313fbc
Merge pull request #48626 from ghiculescu/active-job-async-test
Active Job: `async` adapter should always run jobs immediately if `immediate` set
2023-07-03 09:37:56 +09:00
Alex Ghiculescu
639dab59dc Active Job: async adapter should always run jobs immediately if immediate set
This is an internal fix, not user facing. I noticed it while working on https://github.com/rails/rails/pull/48585.

The `async` adapter has an `immediate` option, which should only be used in tests. This option should tell the adapter to run jobs inline. This works correctly with `perform_later`, but it does not work with `enqueue_at`, which is what other internal mechanisms such as `retry_job` use.

This PR fixes this bug.
2023-07-03 09:02:51 +10:00
Alex Ghiculescu
2385b6e4e5 Fix incorrect arguments for Active Job test job
This is an internal fix, not user facing.

Currently the `LoggingJob` does not accept more than one argument. But there's [a few tests](f46d3452ae/activejob/test/cases/test_helper_test.rb (L518-L537)) that call it with multiple arguments and assert that it is queued correctly. Those tests pass because the job is not performed, but if the job was performed, they'd fail.

This PR just fixes `LoggingJob` to accept a splat of arguments, and adds a test to ensure that it works correctly.
2023-07-02 16:25:09 +10:00
Alex Ghiculescu
ba70a5be86 Make perform_enqueued_jobs compatible with all Active Job adapters 2023-06-28 20:08:08 +10:00
Alex Baldwin
719e49485f Fix error ActiveJob passed class with permitted?
Resolves #48561
Co-authored-by: Sampat Badhe <sampatbadhe@gmail.com>
2023-06-23 10:51:46 -04:00
Alex
10bb51a123 Update Active Job testing guide
The testing guide for Active Job currently implies that when you queue a job it will be performed.

This isn't true; by default jobs are enqueued, not performed.

This PR fleshes out the docs a bit to show both examples, and adds a test to confirm the default behaviour.
2023-06-20 09:58:33 +10:00
Rob Cardy
659d41110f
This method lets job authors define a block which will be run when a job is about to be discarded.
This has utility for gems/modules included on jobs, which can tie into this behaviour and run something when a job fails.
after_discard respects the existing retry behaviour, but will run even if a retried exception is handled in a block.
2023-05-08 14:28:42 -04:00
Yasuo Honda
0b5f6ad82f
Merge pull request #48157 from shivamsinghchahar/improve-aj-queue-adapter-test
Improve AJ queue adapter test case
2023-05-08 11:44:12 +09:00
Shivam Chahar
daf6e2b0de Improve AJ queue adapter test case
In this test case we only check if the third child's queue adpter is nil or not. We should instead check if the queue adapter is the same as base adapter to ensure that it did not change when we changed qdapters for other jobs.
50f0c0f064/activejob/test/cases/queue_adapter_test.rb (L44-L52)
2023-05-07 12:44:53 +05:30
Shivam Chahar
8ccf129ea1 Fix typo in activejob tests
changes `know` -> `known` in activejob serializers test
2023-05-03 20:38:48 +05:30
Shivam Chahar
17d1b83b07 Add tests for AJ to verify queue name passed as symbol. Ref: #48034 2023-04-26 21:37:00 +05:30
Sander Verdonschot
6daba18791
Allow queue adapters to provide a custom name
This gives queue adapters more freedom to name and organize their code.

For example, if `FancyQueue` wants to have their adapter at
`FancyQueue::ActiveJobAdapter`, the name would be `active_job` before this
change. After this change, they can implement `queue_adapter_name` to return
`fancy_queue`.
2023-04-20 13:23:50 -04:00
Sander Verdonschot
6b4acb57e2
Fix name extraction for module queue adapters
Before this change, setting a module as queue adapter would result in
`queue_adapter_name` being `"module"`. This PR fixes the name extraction logic
to handle module or class queue adapters.
2023-04-19 18:51:49 -04:00
fatkodima
5ab2034730 [ActiveJob] Add logging for enqueue_all 2023-04-04 13:18:19 +03:00
fatkodima
f6d56fed27 Add support for logging background job enqueue callers 2023-04-02 03:23:42 +03:00
Pascal Zumkehr
3d3ed6eeb0 Make delayed job display_name failsafe
The display_name method is used by delayed job to log information
about a certain job, including failure messages. Whenever a job class
is moved or deleted, the instances still scheduled cannot be
constantized anymore, causing display_name and hence the log method to
raise an exception. In certain cases, e.g. when logging happens in a
rescue block, this may terminate the entire delayed job worker. With
the failsafe method, the worker handles failed jobs gracefully and
continues work, all with appropriate log output.
2023-03-02 13:38:38 +01:00
Sander Verdonschot
9b62f88a2f
Add perform_all_later to enqueue multiple jobs at once
Sidekiq has a useful optimisation called `push_bulk` that enqueues many jobs at
once, eliminating the repeated Redis roundtrips. However, this feature is not
exposed through Active Job, so it only works for `Sidekiq::Worker` jobs. This
adds a barrier to Active Job adoption for apps that rely on this feature. It
also makes it harder for other queue adapters to implement similar
functionality, as they then have to take care of serialization, callbacks, etc.
themselves.

This commit adds `ActiveJob.perform_all_later(<job1>, <job2>)`, backed by
Sidekiq's `push_bulk` and with a fallback to enqueuing serially if the queue
adapter does not support bulk enqueue.

The performance benefit for 1000 jobs can be more than an order of magnitude:

| Enqueue type       | Serial time (ms) | Bulk time (ms) | Speedup |
| ------------------ | ---------------- | -------------- | ------- |
| Raw Sidekiq        |             2661 |            119 |     22x |
| Active Job Sidekiq |             2853 |            208 |     14x |

(Measured in a simple test app in our production environment.)

Instrumentation for perform_all_later uses a new event `enqueue_all.active_job`
2023-02-02 16:39:22 -05:00
Jonathan Hefner
77db302aa0 Add ActiveJob.deprecator
This commit adds `ActiveJob.deprecator` and replaces all usages of
`ActiveSupport::Deprecation.warn` in `activejob/lib` with
`ActiveJob.deprecator`.

Additionally, this commit adds `ActiveJob.deprecator` to
`Rails.application.deprecators` so that it can be configured via
settings such as `config.active_support.report_deprecations`.

This commit also removes a defunct `ActiveSupport::Deprecation.silence`
call that was added in 9eb4b4ed01f893c2fc7ff3ee4f99301dec7ea3c2 but not
removed when the deprecation was completed in
10bd5e59c3291bb2034869e97cca30634a559afb.
2022-10-31 17:04:26 -05:00
Ariel Valentin
658fd53741
fix: Ensure ActiveJob::TestHelper sets scheduled_at to a Float
I noticed a difference in behavior when inspecting `ActiveJob::Core#scheduled_at` in non-test environments vs when inspecting in while executing tests.

Prior to this change, `ActiveJob::TestHelper` would set `ActiveJob::Core#scheduled_at` to a `Time` object in tests,
however this attribute was set to a `Float` objects in non-test environments:

<d1aa6af5cc/activejob/lib/active_job/core.rb (L161)>

This change ensures parity in all runtime environments.
2022-10-17 19:22:24 +00: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
Jonathan Rochkind
dcce260edc Add job_id and exception message to ActiveJob retry/discard logging
In other log messages like perform/performed and ActiveJob error logging, the job ID and exception message were already included, eg:

    Error performing TestFailureJob (Job ID: d70ad13e-e58b-409c-a8cc-e0447fc792b5) from Resque(default) in 1446.56ms: RuntimeError (Error Message):

But log message related to retry/discard behavior from ActiveJob::Exceptions did not include the Job ID or exception message. We now include them, in a consistent format with other existing messages.

Job ID is especially useful because, while other ActiveJob-related log messages get the Job ID via tagged logging, retry-related log messages do not currently end up tagged with Job ID. And it's really useful to use Job ID to be able to collect all the log lines related to a particular job, put the error messages together with the retry and subsequent perform messages.

We also include job.executions in the enqueue_retry log message because it was available and useful, to know if this is the 1st retry or 2nd or whatever. Previously job.executions was included in retry_stopped logging, but not enqueue_retry.
2022-02-08 10:06:21 -05:00
Rafael Mendonça França
6fb54c00e4
Merge PR #43066 2022-01-06 16:53:31 +00:00