activejob 6.0.5.1 → 6.1.7.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.5.1
4
+ version: 6.1.7.1
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: 2022-07-12 00:00:00.000000000 Z
11
+ date: 2023-01-17 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.5.1
19
+ version: 6.1.7.1
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.5.1
26
+ version: 6.1.7.1
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.5.1/activejob/CHANGELOG.md
99
- documentation_uri: https://api.rubyonrails.org/v6.0.5.1/
102
+ changelog_uri: https://github.com/rails/rails/blob/v6.1.7.1/activejob/CHANGELOG.md
103
+ documentation_uri: https://api.rubyonrails.org/v6.1.7.1/
100
104
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
101
- source_code_uri: https://github.com/rails/rails/tree/v6.0.5.1/activejob
105
+ source_code_uri: https://github.com/rails/rails/tree/v6.1.7.1/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.3.3
122
+ rubygems_version: 3.4.3
119
123
  signing_key:
120
124
  specification_version: 4
121
125
  summary: Job framework with pluggable queues.