activejob 6.0.6.1 → 6.1.7.6

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.
@@ -9,12 +9,14 @@ module ActiveJob
9
9
  extend ActiveSupport::Autoload
10
10
 
11
11
  autoload :ObjectSerializer
12
+ autoload :TimeObjectSerializer
12
13
  autoload :SymbolSerializer
13
14
  autoload :DurationSerializer
14
15
  autoload :DateTimeSerializer
15
16
  autoload :DateSerializer
16
17
  autoload :TimeWithZoneSerializer
17
18
  autoload :TimeSerializer
19
+ autoload :ModuleSerializer
18
20
 
19
21
  mattr_accessor :_additional_serializers
20
22
  self._additional_serializers = Set.new
@@ -58,6 +60,7 @@ module ActiveJob
58
60
  DateTimeSerializer,
59
61
  DateSerializer,
60
62
  TimeWithZoneSerializer,
61
- TimeSerializer
63
+ TimeSerializer,
64
+ ModuleSerializer
62
65
  end
63
66
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/class/subclasses"
4
+ require "active_support/testing/assertions"
4
5
 
5
6
  module ActiveJob
6
7
  # Provides helper methods for testing Active Job
@@ -9,6 +10,8 @@ module ActiveJob
9
10
  :performed_jobs, :performed_jobs=,
10
11
  to: :queue_adapter
11
12
 
13
+ include ActiveSupport::Testing::Assertions
14
+
12
15
  module TestQueueAdapter
13
16
  extend ActiveSupport::Concern
14
17
 
@@ -117,17 +120,17 @@ module ActiveJob
117
120
  # HelloJob.perform_later('elfassy')
118
121
  # end
119
122
  # end
120
- def assert_enqueued_jobs(number, only: nil, except: nil, queue: nil)
123
+ def assert_enqueued_jobs(number, only: nil, except: nil, queue: nil, &block)
121
124
  if block_given?
122
- original_count = enqueued_jobs_with(only: only, except: except, queue: queue)
125
+ original_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
123
126
 
124
- yield
127
+ assert_nothing_raised(&block)
125
128
 
126
- new_count = enqueued_jobs_with(only: only, except: except, queue: queue)
129
+ new_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
127
130
 
128
- actual_count = new_count - original_count
131
+ actual_count = (new_jobs - original_jobs).count
129
132
  else
130
- actual_count = enqueued_jobs_with(only: only, except: except, queue: queue)
133
+ actual_count = enqueued_jobs_with(only: only, except: except, queue: queue).count
131
134
  end
132
135
 
133
136
  assert_equal number, actual_count, "#{number} jobs expected, but #{actual_count} were enqueued"
@@ -279,7 +282,7 @@ module ActiveJob
279
282
 
280
283
  performed_jobs_size = new_count - original_count
281
284
  else
282
- performed_jobs_size = performed_jobs_with(only: only, except: except, queue: queue)
285
+ performed_jobs_size = performed_jobs_with(only: only, except: except, queue: queue).count
283
286
  end
284
287
 
285
288
  assert_equal number, performed_jobs_size, "#{number} jobs expected, but #{performed_jobs_size} were performed"
@@ -345,44 +348,40 @@ module ActiveJob
345
348
  #
346
349
  # def test_assert_enqueued_with
347
350
  # MyJob.perform_later(1,2,3)
348
- # assert_enqueued_with(job: MyJob, args: [1,2,3], queue: 'low')
351
+ # assert_enqueued_with(job: MyJob, args: [1,2,3])
349
352
  #
350
- # MyJob.set(wait_until: Date.tomorrow.noon).perform_later
351
- # assert_enqueued_with(job: MyJob, at: Date.tomorrow.noon)
353
+ # MyJob.set(wait_until: Date.tomorrow.noon, queue: "my_queue").perform_later
354
+ # assert_enqueued_with(at: Date.tomorrow.noon, queue: "my_queue")
352
355
  # end
353
356
  #
354
- # The +at+ and +args+ arguments also accept a proc.
357
+ # The given arguments may also be specified as matcher procs that return a
358
+ # boolean value indicating whether a job's attribute meets certain criteria.
355
359
  #
356
- # To the +at+ proc, it will get passed the actual job's at argument.
360
+ # For example, a proc can be used to match a range of times:
357
361
  #
358
362
  # def test_assert_enqueued_with
359
- # expected_time = ->(at) do
360
- # (Date.yesterday..Date.tomorrow).cover?(at)
361
- # end
363
+ # at_matcher = ->(job_at) { (Date.yesterday..Date.tomorrow).cover?(job_at) }
364
+ #
365
+ # MyJob.set(wait_until: Date.today.noon).perform_later
362
366
  #
363
- # MyJob.set(at: Date.today.noon).perform_later
364
- # assert_enqueued_with(job: MyJob, at: expected_time)
367
+ # assert_enqueued_with(job: MyJob, at: at_matcher)
365
368
  # end
366
369
  #
367
- # To the +args+ proc, it will get passed the actual job's arguments
368
- # Your proc needs to return a boolean value determining if
369
- # the job's arguments matches your expectation. This is useful to check only
370
- # for a subset of arguments.
370
+ # A proc can also be used to match a subset of a job's args:
371
371
  #
372
372
  # def test_assert_enqueued_with
373
- # expected_args = ->(job_args) do
374
- # assert job_args.first.key?(:foo)
375
- # end
373
+ # args_matcher = ->(job_args) { job_args[0].key?(:foo) }
374
+ #
375
+ # MyJob.perform_later(foo: "bar", other_arg: "No need to check in the test")
376
376
  #
377
- # MyJob.perform_later(foo: 'bar', other_arg: 'No need to check in the test')
378
- # assert_enqueued_with(job: MyJob, args: expected_args, queue: 'low')
377
+ # assert_enqueued_with(job: MyJob, args: args_matcher)
379
378
  # end
380
379
  #
381
380
  # If a block is passed, asserts that the block will cause the job to be
382
381
  # enqueued with the given arguments.
383
382
  #
384
383
  # def test_assert_enqueued_with
385
- # assert_enqueued_with(job: MyJob, args: [1,2,3], queue: 'low') do
384
+ # assert_enqueued_with(job: MyJob, args: [1,2,3]) do
386
385
  # MyJob.perform_later(1,2,3)
387
386
  # end
388
387
  #
@@ -390,22 +389,24 @@ module ActiveJob
390
389
  # MyJob.set(wait_until: Date.tomorrow.noon).perform_later
391
390
  # end
392
391
  # end
393
- def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil)
392
+ def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil, &block)
394
393
  expected = { job: job, args: args, at: at, queue: queue }.compact
395
394
  expected_args = prepare_args_for_assertion(expected)
395
+ potential_matches = []
396
396
 
397
397
  if block_given?
398
- original_enqueued_jobs_count = enqueued_jobs.count
398
+ original_enqueued_jobs = enqueued_jobs.dup
399
399
 
400
- yield
400
+ assert_nothing_raised(&block)
401
401
 
402
- jobs = enqueued_jobs.drop(original_enqueued_jobs_count)
402
+ jobs = enqueued_jobs - original_enqueued_jobs
403
403
  else
404
404
  jobs = enqueued_jobs
405
405
  end
406
406
 
407
407
  matching_job = jobs.find do |enqueued_job|
408
408
  deserialized_job = deserialize_args_for_assertion(enqueued_job)
409
+ potential_matches << deserialized_job
409
410
 
410
411
  expected_args.all? do |key, value|
411
412
  if value.respond_to?(:call)
@@ -416,7 +417,9 @@ module ActiveJob
416
417
  end
417
418
  end
418
419
 
419
- assert matching_job, "No enqueued job found with #{expected}"
420
+ message = +"No enqueued job found with #{expected}"
421
+ message << "\n\nPotential matches: #{potential_matches.join("\n")}" if potential_matches.present?
422
+ assert matching_job, message
420
423
  instantiate_job(matching_job)
421
424
  end
422
425
 
@@ -427,42 +430,40 @@ module ActiveJob
427
430
  #
428
431
  # perform_enqueued_jobs
429
432
  #
430
- # assert_performed_with(job: MyJob, args: [1,2,3], queue: 'high')
433
+ # assert_performed_with(job: MyJob, args: [1,2,3])
431
434
  #
432
- # MyJob.set(wait_until: Date.tomorrow.noon).perform_later
435
+ # MyJob.set(wait_until: Date.tomorrow.noon, queue: "my_queue").perform_later
433
436
  #
434
437
  # perform_enqueued_jobs
435
438
  #
436
- # assert_performed_with(job: MyJob, at: Date.tomorrow.noon)
439
+ # assert_performed_with(at: Date.tomorrow.noon, queue: "my_queue")
437
440
  # end
438
441
  #
439
- # The +at+ and +args+ arguments also accept a proc.
442
+ # The given arguments may also be specified as matcher procs that return a
443
+ # boolean value indicating whether a job's attribute meets certain criteria.
440
444
  #
441
- # To the +at+ proc, it will get passed the actual job's at argument.
445
+ # For example, a proc can be used to match a range of times:
442
446
  #
443
- # def test_assert_enqueued_with
444
- # expected_time = ->(at) do
445
- # (Date.yesterday..Date.tomorrow).cover?(at)
446
- # end
447
+ # def test_assert_performed_with
448
+ # at_matcher = ->(job_at) { (Date.yesterday..Date.tomorrow).cover?(job_at) }
449
+ #
450
+ # MyJob.set(wait_until: Date.today.noon).perform_later
451
+ #
452
+ # perform_enqueued_jobs
447
453
  #
448
- # MyJob.set(at: Date.today.noon).perform_later
449
- # assert_enqueued_with(job: MyJob, at: expected_time)
454
+ # assert_performed_with(job: MyJob, at: at_matcher)
450
455
  # end
451
456
  #
452
- # To the +args+ proc, it will get passed the actual job's arguments
453
- # Your proc needs to return a boolean value determining if
454
- # the job's arguments matches your expectation. This is useful to check only
455
- # for a subset of arguments.
457
+ # A proc can also be used to match a subset of a job's args:
456
458
  #
457
459
  # def test_assert_performed_with
458
- # expected_args = ->(job_args) do
459
- # assert job_args.first.key?(:foo)
460
- # end
461
- # MyJob.perform_later(foo: 'bar', other_arg: 'No need to check in the test')
460
+ # args_matcher = ->(job_args) { job_args[0].key?(:foo) }
461
+ #
462
+ # MyJob.perform_later(foo: "bar", other_arg: "No need to check in the test")
462
463
  #
463
464
  # perform_enqueued_jobs
464
465
  #
465
- # assert_performed_with(job: MyJob, args: expected_args, queue: 'high')
466
+ # assert_performed_with(job: MyJob, args: args_matcher)
466
467
  # end
467
468
  #
468
469
  # If a block is passed, that block performs all of the jobs that were
@@ -470,7 +471,7 @@ module ActiveJob
470
471
  # the job has been performed with the given arguments in the block.
471
472
  #
472
473
  # def test_assert_performed_with
473
- # assert_performed_with(job: MyJob, args: [1,2,3], queue: 'high') do
474
+ # assert_performed_with(job: MyJob, args: [1,2,3]) do
474
475
  # MyJob.perform_later(1,2,3)
475
476
  # end
476
477
  #
@@ -481,6 +482,7 @@ module ActiveJob
481
482
  def assert_performed_with(job: nil, args: nil, at: nil, queue: nil, &block)
482
483
  expected = { job: job, args: args, at: at, queue: queue }.compact
483
484
  expected_args = prepare_args_for_assertion(expected)
485
+ potential_matches = []
484
486
 
485
487
  if block_given?
486
488
  original_performed_jobs_count = performed_jobs.count
@@ -494,6 +496,7 @@ module ActiveJob
494
496
 
495
497
  matching_job = jobs.find do |enqueued_job|
496
498
  deserialized_job = deserialize_args_for_assertion(enqueued_job)
499
+ potential_matches << deserialized_job
497
500
 
498
501
  expected_args.all? do |key, value|
499
502
  if value.respond_to?(:call)
@@ -504,7 +507,10 @@ module ActiveJob
504
507
  end
505
508
  end
506
509
 
507
- assert matching_job, "No performed job found with #{expected}"
510
+ message = +"No performed job found with #{expected}"
511
+ message << "\n\nPotential matches: #{potential_matches.join("\n")}" if potential_matches.present?
512
+ assert matching_job, message
513
+
508
514
  instantiate_job(matching_job)
509
515
  end
510
516
 
@@ -563,8 +569,10 @@ module ActiveJob
563
569
  # assert_performed_jobs 1
564
570
  # end
565
571
  #
566
- def perform_enqueued_jobs(only: nil, except: nil, queue: nil)
567
- return flush_enqueued_jobs(only: only, except: except, queue: queue) unless block_given?
572
+ # If the +:at+ option is specified, then only run jobs enqueued to run
573
+ # immediately or before the given time
574
+ def perform_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil, &block)
575
+ return flush_enqueued_jobs(only: only, except: except, queue: queue, at: at) unless block_given?
568
576
 
569
577
  validate_option(only: only, except: except)
570
578
 
@@ -573,6 +581,7 @@ module ActiveJob
573
581
  old_filter = queue_adapter.filter
574
582
  old_reject = queue_adapter.reject
575
583
  old_queue = queue_adapter.queue
584
+ old_at = queue_adapter.at
576
585
 
577
586
  begin
578
587
  queue_adapter.perform_enqueued_jobs = true
@@ -580,14 +589,16 @@ module ActiveJob
580
589
  queue_adapter.filter = only
581
590
  queue_adapter.reject = except
582
591
  queue_adapter.queue = queue
592
+ queue_adapter.at = at
583
593
 
584
- yield
594
+ assert_nothing_raised(&block)
585
595
  ensure
586
596
  queue_adapter.perform_enqueued_jobs = old_perform_enqueued_jobs
587
597
  queue_adapter.perform_enqueued_at_jobs = old_perform_enqueued_at_jobs
588
598
  queue_adapter.filter = old_filter
589
599
  queue_adapter.reject = old_reject
590
600
  queue_adapter.queue = old_queue
601
+ queue_adapter.at = old_at
591
602
  end
592
603
  end
593
604
 
@@ -609,10 +620,10 @@ module ActiveJob
609
620
  performed_jobs.clear
610
621
  end
611
622
 
612
- def jobs_with(jobs, only: nil, except: nil, queue: nil)
623
+ def jobs_with(jobs, only: nil, except: nil, queue: nil, at: nil)
613
624
  validate_option(only: only, except: except)
614
625
 
615
- jobs.count do |job|
626
+ jobs.dup.select do |job|
616
627
  job_class = job.fetch(:job)
617
628
 
618
629
  if only
@@ -625,6 +636,10 @@ module ActiveJob
625
636
  next false unless queue.to_s == job.fetch(:queue, job_class.queue_name)
626
637
  end
627
638
 
639
+ if at && job[:at]
640
+ next false if job[:at] > at.to_f
641
+ end
642
+
628
643
  yield job if block_given?
629
644
 
630
645
  true
@@ -637,41 +652,28 @@ module ActiveJob
637
652
  ->(job) { Array(filter).include?(job.fetch(:job)) }
638
653
  end
639
654
 
640
- def enqueued_jobs_with(only: nil, except: nil, queue: nil, &block)
641
- jobs_with(enqueued_jobs, only: only, except: except, queue: queue, &block)
655
+ def enqueued_jobs_with(only: nil, except: nil, queue: nil, at: nil, &block)
656
+ jobs_with(enqueued_jobs, only: only, except: except, queue: queue, at: at, &block)
642
657
  end
643
658
 
644
659
  def performed_jobs_with(only: nil, except: nil, queue: nil, &block)
645
660
  jobs_with(performed_jobs, only: only, except: except, queue: queue, &block)
646
661
  end
647
662
 
648
- def flush_enqueued_jobs(only: nil, except: nil, queue: nil)
649
- enqueued_jobs_with(only: only, except: except, queue: queue) do |payload|
650
- instantiate_job(payload).perform_now
663
+ def flush_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil)
664
+ enqueued_jobs_with(only: only, except: except, queue: queue, at: at) do |payload|
665
+ queue_adapter.enqueued_jobs.delete(payload)
651
666
  queue_adapter.performed_jobs << payload
652
- end
667
+ instantiate_job(payload).perform_now
668
+ end.count
653
669
  end
654
670
 
655
671
  def prepare_args_for_assertion(args)
656
672
  args.dup.tap do |arguments|
657
- if arguments[:at] && !arguments[:at].respond_to?(:call)
673
+ if arguments[:at].acts_like?(:time)
658
674
  at_range = arguments[:at] - 1..arguments[:at] + 1
659
675
  arguments[:at] = ->(at) { at_range.cover?(at) }
660
676
  end
661
- arguments[:args] = round_time_arguments(arguments[:args]) if arguments[:args]
662
- end
663
- end
664
-
665
- def round_time_arguments(argument)
666
- case argument
667
- when Time, ActiveSupport::TimeWithZone, DateTime
668
- argument.change(usec: 0)
669
- when Hash
670
- argument.transform_values { |value| round_time_arguments(value) }
671
- when Array
672
- argument.map { |element| round_time_arguments(element) }
673
- else
674
- argument
675
677
  end
676
678
  end
677
679
 
data/lib/active_job.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2014-2019 David Heinemeier Hansson
4
+ # Copyright (c) 2014-2022 David Heinemeier Hansson
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining
7
7
  # a copy of this software and associated documentation files (the
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activejob
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.6.1
4
+ version: 6.1.7.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-17 00:00:00.000000000 Z
11
+ date: 2023-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 6.0.6.1
19
+ version: 6.1.7.6
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 6.0.6.1
26
+ version: 6.1.7.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: globalid
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -57,6 +57,8 @@ files:
57
57
  - lib/active_job/exceptions.rb
58
58
  - lib/active_job/execution.rb
59
59
  - lib/active_job/gem_version.rb
60
+ - lib/active_job/instrumentation.rb
61
+ - lib/active_job/log_subscriber.rb
60
62
  - lib/active_job/logging.rb
61
63
  - lib/active_job/queue_adapter.rb
62
64
  - lib/active_job/queue_adapters.rb
@@ -78,8 +80,10 @@ files:
78
80
  - lib/active_job/serializers/date_serializer.rb
79
81
  - lib/active_job/serializers/date_time_serializer.rb
80
82
  - lib/active_job/serializers/duration_serializer.rb
83
+ - lib/active_job/serializers/module_serializer.rb
81
84
  - lib/active_job/serializers/object_serializer.rb
82
85
  - lib/active_job/serializers/symbol_serializer.rb
86
+ - lib/active_job/serializers/time_object_serializer.rb
83
87
  - lib/active_job/serializers/time_serializer.rb
84
88
  - lib/active_job/serializers/time_with_zone_serializer.rb
85
89
  - lib/active_job/test_case.rb
@@ -95,10 +99,10 @@ licenses:
95
99
  - MIT
96
100
  metadata:
97
101
  bug_tracker_uri: https://github.com/rails/rails/issues
98
- changelog_uri: https://github.com/rails/rails/blob/v6.0.6.1/activejob/CHANGELOG.md
99
- documentation_uri: https://api.rubyonrails.org/v6.0.6.1/
102
+ changelog_uri: https://github.com/rails/rails/blob/v6.1.7.6/activejob/CHANGELOG.md
103
+ documentation_uri: https://api.rubyonrails.org/v6.1.7.6/
100
104
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
101
- source_code_uri: https://github.com/rails/rails/tree/v6.0.6.1/activejob
105
+ source_code_uri: https://github.com/rails/rails/tree/v6.1.7.6/activejob
102
106
  rubygems_mfa_required: 'true'
103
107
  post_install_message:
104
108
  rdoc_options: []
@@ -115,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
119
  - !ruby/object:Gem::Version
116
120
  version: '0'
117
121
  requirements: []
118
- rubygems_version: 3.4.3
122
+ rubygems_version: 3.3.3
119
123
  signing_key:
120
124
  specification_version: 4
121
125
  summary: Job framework with pluggable queues.