activejob 6.0.6.1 → 6.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -117,17 +117,17 @@ module ActiveJob
117
117
  # HelloJob.perform_later('elfassy')
118
118
  # end
119
119
  # end
120
- def assert_enqueued_jobs(number, only: nil, except: nil, queue: nil)
120
+ def assert_enqueued_jobs(number, only: nil, except: nil, queue: nil, &block)
121
121
  if block_given?
122
- original_count = enqueued_jobs_with(only: only, except: except, queue: queue)
122
+ original_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
123
123
 
124
- yield
124
+ assert_nothing_raised(&block)
125
125
 
126
- new_count = enqueued_jobs_with(only: only, except: except, queue: queue)
126
+ new_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
127
127
 
128
- actual_count = new_count - original_count
128
+ actual_count = (new_jobs - original_jobs).count
129
129
  else
130
- actual_count = enqueued_jobs_with(only: only, except: except, queue: queue)
130
+ actual_count = enqueued_jobs_with(only: only, except: except, queue: queue).count
131
131
  end
132
132
 
133
133
  assert_equal number, actual_count, "#{number} jobs expected, but #{actual_count} were enqueued"
@@ -279,7 +279,7 @@ module ActiveJob
279
279
 
280
280
  performed_jobs_size = new_count - original_count
281
281
  else
282
- performed_jobs_size = performed_jobs_with(only: only, except: except, queue: queue)
282
+ performed_jobs_size = performed_jobs_with(only: only, except: except, queue: queue).count
283
283
  end
284
284
 
285
285
  assert_equal number, performed_jobs_size, "#{number} jobs expected, but #{performed_jobs_size} were performed"
@@ -345,44 +345,40 @@ module ActiveJob
345
345
  #
346
346
  # def test_assert_enqueued_with
347
347
  # MyJob.perform_later(1,2,3)
348
- # assert_enqueued_with(job: MyJob, args: [1,2,3], queue: 'low')
348
+ # assert_enqueued_with(job: MyJob, args: [1,2,3])
349
349
  #
350
- # MyJob.set(wait_until: Date.tomorrow.noon).perform_later
351
- # assert_enqueued_with(job: MyJob, at: Date.tomorrow.noon)
350
+ # MyJob.set(wait_until: Date.tomorrow.noon, queue: "my_queue").perform_later
351
+ # assert_enqueued_with(at: Date.tomorrow.noon, queue: "my_queue")
352
352
  # end
353
353
  #
354
- # The +at+ and +args+ arguments also accept a proc.
354
+ # The given arguments may also be specified as matcher procs that return a
355
+ # boolean value indicating whether a job's attribute meets certain criteria.
355
356
  #
356
- # To the +at+ proc, it will get passed the actual job's at argument.
357
+ # For example, a proc can be used to match a range of times:
357
358
  #
358
359
  # def test_assert_enqueued_with
359
- # expected_time = ->(at) do
360
- # (Date.yesterday..Date.tomorrow).cover?(at)
361
- # end
360
+ # at_matcher = ->(job_at) { (Date.yesterday..Date.tomorrow).cover?(job_at) }
361
+ #
362
+ # MyJob.set(wait_until: Date.today.noon).perform_later
362
363
  #
363
- # MyJob.set(at: Date.today.noon).perform_later
364
- # assert_enqueued_with(job: MyJob, at: expected_time)
364
+ # assert_enqueued_with(job: MyJob, at: at_matcher)
365
365
  # end
366
366
  #
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.
367
+ # A proc can also be used to match a subset of a job's args:
371
368
  #
372
369
  # def test_assert_enqueued_with
373
- # expected_args = ->(job_args) do
374
- # assert job_args.first.key?(:foo)
375
- # end
370
+ # args_matcher = ->(job_args) { job_args[0].key?(:foo) }
376
371
  #
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')
372
+ # MyJob.perform_later(foo: "bar", other_arg: "No need to check in the test")
373
+ #
374
+ # assert_enqueued_with(job: MyJob, args: args_matcher)
379
375
  # end
380
376
  #
381
377
  # If a block is passed, asserts that the block will cause the job to be
382
378
  # enqueued with the given arguments.
383
379
  #
384
380
  # def test_assert_enqueued_with
385
- # assert_enqueued_with(job: MyJob, args: [1,2,3], queue: 'low') do
381
+ # assert_enqueued_with(job: MyJob, args: [1,2,3]) do
386
382
  # MyJob.perform_later(1,2,3)
387
383
  # end
388
384
  #
@@ -390,22 +386,24 @@ module ActiveJob
390
386
  # MyJob.set(wait_until: Date.tomorrow.noon).perform_later
391
387
  # end
392
388
  # end
393
- def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil)
389
+ def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil, &block)
394
390
  expected = { job: job, args: args, at: at, queue: queue }.compact
395
391
  expected_args = prepare_args_for_assertion(expected)
392
+ potential_matches = []
396
393
 
397
394
  if block_given?
398
- original_enqueued_jobs_count = enqueued_jobs.count
395
+ original_enqueued_jobs = enqueued_jobs.dup
399
396
 
400
- yield
397
+ assert_nothing_raised(&block)
401
398
 
402
- jobs = enqueued_jobs.drop(original_enqueued_jobs_count)
399
+ jobs = enqueued_jobs - original_enqueued_jobs
403
400
  else
404
401
  jobs = enqueued_jobs
405
402
  end
406
403
 
407
404
  matching_job = jobs.find do |enqueued_job|
408
405
  deserialized_job = deserialize_args_for_assertion(enqueued_job)
406
+ potential_matches << deserialized_job
409
407
 
410
408
  expected_args.all? do |key, value|
411
409
  if value.respond_to?(:call)
@@ -416,7 +414,9 @@ module ActiveJob
416
414
  end
417
415
  end
418
416
 
419
- assert matching_job, "No enqueued job found with #{expected}"
417
+ message = +"No enqueued job found with #{expected}"
418
+ message << "\n\nPotential matches: #{potential_matches.join("\n")}" if potential_matches.present?
419
+ assert matching_job, message
420
420
  instantiate_job(matching_job)
421
421
  end
422
422
 
@@ -427,42 +427,40 @@ module ActiveJob
427
427
  #
428
428
  # perform_enqueued_jobs
429
429
  #
430
- # assert_performed_with(job: MyJob, args: [1,2,3], queue: 'high')
430
+ # assert_performed_with(job: MyJob, args: [1,2,3])
431
431
  #
432
- # MyJob.set(wait_until: Date.tomorrow.noon).perform_later
432
+ # MyJob.set(wait_until: Date.tomorrow.noon, queue: "my_queue").perform_later
433
433
  #
434
434
  # perform_enqueued_jobs
435
435
  #
436
- # assert_performed_with(job: MyJob, at: Date.tomorrow.noon)
436
+ # assert_performed_with(at: Date.tomorrow.noon, queue: "my_queue")
437
437
  # end
438
438
  #
439
- # The +at+ and +args+ arguments also accept a proc.
439
+ # The given arguments may also be specified as matcher procs that return a
440
+ # boolean value indicating whether a job's attribute meets certain criteria.
440
441
  #
441
- # To the +at+ proc, it will get passed the actual job's at argument.
442
+ # For example, a proc can be used to match a range of times:
442
443
  #
443
- # def test_assert_enqueued_with
444
- # expected_time = ->(at) do
445
- # (Date.yesterday..Date.tomorrow).cover?(at)
446
- # end
444
+ # def test_assert_performed_with
445
+ # at_matcher = ->(job_at) { (Date.yesterday..Date.tomorrow).cover?(job_at) }
446
+ #
447
+ # MyJob.set(wait_until: Date.today.noon).perform_later
447
448
  #
448
- # MyJob.set(at: Date.today.noon).perform_later
449
- # assert_enqueued_with(job: MyJob, at: expected_time)
449
+ # perform_enqueued_jobs
450
+ #
451
+ # assert_performed_with(job: MyJob, at: at_matcher)
450
452
  # end
451
453
  #
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.
454
+ # A proc can also be used to match a subset of a job's args:
456
455
  #
457
456
  # 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')
457
+ # args_matcher = ->(job_args) { job_args[0].key?(:foo) }
458
+ #
459
+ # MyJob.perform_later(foo: "bar", other_arg: "No need to check in the test")
462
460
  #
463
461
  # perform_enqueued_jobs
464
462
  #
465
- # assert_performed_with(job: MyJob, args: expected_args, queue: 'high')
463
+ # assert_performed_with(job: MyJob, args: args_matcher)
466
464
  # end
467
465
  #
468
466
  # If a block is passed, that block performs all of the jobs that were
@@ -470,7 +468,7 @@ module ActiveJob
470
468
  # the job has been performed with the given arguments in the block.
471
469
  #
472
470
  # def test_assert_performed_with
473
- # assert_performed_with(job: MyJob, args: [1,2,3], queue: 'high') do
471
+ # assert_performed_with(job: MyJob, args: [1,2,3]) do
474
472
  # MyJob.perform_later(1,2,3)
475
473
  # end
476
474
  #
@@ -481,6 +479,7 @@ module ActiveJob
481
479
  def assert_performed_with(job: nil, args: nil, at: nil, queue: nil, &block)
482
480
  expected = { job: job, args: args, at: at, queue: queue }.compact
483
481
  expected_args = prepare_args_for_assertion(expected)
482
+ potential_matches = []
484
483
 
485
484
  if block_given?
486
485
  original_performed_jobs_count = performed_jobs.count
@@ -494,6 +493,7 @@ module ActiveJob
494
493
 
495
494
  matching_job = jobs.find do |enqueued_job|
496
495
  deserialized_job = deserialize_args_for_assertion(enqueued_job)
496
+ potential_matches << deserialized_job
497
497
 
498
498
  expected_args.all? do |key, value|
499
499
  if value.respond_to?(:call)
@@ -504,7 +504,10 @@ module ActiveJob
504
504
  end
505
505
  end
506
506
 
507
- assert matching_job, "No performed job found with #{expected}"
507
+ message = +"No performed job found with #{expected}"
508
+ message << "\n\nPotential matches: #{potential_matches.join("\n")}" if potential_matches.present?
509
+ assert matching_job, message
510
+
508
511
  instantiate_job(matching_job)
509
512
  end
510
513
 
@@ -563,8 +566,10 @@ module ActiveJob
563
566
  # assert_performed_jobs 1
564
567
  # end
565
568
  #
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?
569
+ # If the +:at+ option is specified, then only run jobs enqueued to run
570
+ # immediately or before the given time
571
+ def perform_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil, &block)
572
+ return flush_enqueued_jobs(only: only, except: except, queue: queue, at: at) unless block_given?
568
573
 
569
574
  validate_option(only: only, except: except)
570
575
 
@@ -573,6 +578,7 @@ module ActiveJob
573
578
  old_filter = queue_adapter.filter
574
579
  old_reject = queue_adapter.reject
575
580
  old_queue = queue_adapter.queue
581
+ old_at = queue_adapter.at
576
582
 
577
583
  begin
578
584
  queue_adapter.perform_enqueued_jobs = true
@@ -580,14 +586,16 @@ module ActiveJob
580
586
  queue_adapter.filter = only
581
587
  queue_adapter.reject = except
582
588
  queue_adapter.queue = queue
589
+ queue_adapter.at = at
583
590
 
584
- yield
591
+ assert_nothing_raised(&block)
585
592
  ensure
586
593
  queue_adapter.perform_enqueued_jobs = old_perform_enqueued_jobs
587
594
  queue_adapter.perform_enqueued_at_jobs = old_perform_enqueued_at_jobs
588
595
  queue_adapter.filter = old_filter
589
596
  queue_adapter.reject = old_reject
590
597
  queue_adapter.queue = old_queue
598
+ queue_adapter.at = old_at
591
599
  end
592
600
  end
593
601
 
@@ -609,10 +617,10 @@ module ActiveJob
609
617
  performed_jobs.clear
610
618
  end
611
619
 
612
- def jobs_with(jobs, only: nil, except: nil, queue: nil)
620
+ def jobs_with(jobs, only: nil, except: nil, queue: nil, at: nil)
613
621
  validate_option(only: only, except: except)
614
622
 
615
- jobs.count do |job|
623
+ jobs.dup.select do |job|
616
624
  job_class = job.fetch(:job)
617
625
 
618
626
  if only
@@ -625,6 +633,10 @@ module ActiveJob
625
633
  next false unless queue.to_s == job.fetch(:queue, job_class.queue_name)
626
634
  end
627
635
 
636
+ if at && job[:at]
637
+ next false if job[:at] > at.to_f
638
+ end
639
+
628
640
  yield job if block_given?
629
641
 
630
642
  true
@@ -637,41 +649,28 @@ module ActiveJob
637
649
  ->(job) { Array(filter).include?(job.fetch(:job)) }
638
650
  end
639
651
 
640
- def enqueued_jobs_with(only: nil, except: nil, queue: nil, &block)
641
- jobs_with(enqueued_jobs, only: only, except: except, queue: queue, &block)
652
+ def enqueued_jobs_with(only: nil, except: nil, queue: nil, at: nil, &block)
653
+ jobs_with(enqueued_jobs, only: only, except: except, queue: queue, at: at, &block)
642
654
  end
643
655
 
644
656
  def performed_jobs_with(only: nil, except: nil, queue: nil, &block)
645
657
  jobs_with(performed_jobs, only: only, except: except, queue: queue, &block)
646
658
  end
647
659
 
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
660
+ def flush_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil)
661
+ enqueued_jobs_with(only: only, except: except, queue: queue, at: at) do |payload|
662
+ queue_adapter.enqueued_jobs.delete(payload)
651
663
  queue_adapter.performed_jobs << payload
652
- end
664
+ instantiate_job(payload).perform_now
665
+ end.count
653
666
  end
654
667
 
655
668
  def prepare_args_for_assertion(args)
656
669
  args.dup.tap do |arguments|
657
- if arguments[:at] && !arguments[:at].respond_to?(:call)
670
+ if arguments[:at].acts_like?(:time)
658
671
  at_range = arguments[:at] - 1..arguments[:at] + 1
659
672
  arguments[:at] = ->(at) { at_range.cover?(at) }
660
673
  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
674
  end
676
675
  end
677
676
 
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-2020 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.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-17 00:00:00.000000000 Z
11
+ date: 2020-11-02 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.0.rc1
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.0.rc1
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,12 +99,11 @@ 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.0.rc1/activejob/CHANGELOG.md
103
+ documentation_uri: https://api.rubyonrails.org/v6.1.0.rc1/
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
102
- rubygems_mfa_required: 'true'
103
- post_install_message:
105
+ source_code_uri: https://github.com/rails/rails/tree/v6.1.0.rc1/activejob
106
+ post_install_message:
104
107
  rdoc_options: []
105
108
  require_paths:
106
109
  - lib
@@ -111,12 +114,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
111
114
  version: 2.5.0
112
115
  required_rubygems_version: !ruby/object:Gem::Requirement
113
116
  requirements:
114
- - - ">="
117
+ - - ">"
115
118
  - !ruby/object:Gem::Version
116
- version: '0'
119
+ version: 1.3.1
117
120
  requirements: []
118
- rubygems_version: 3.4.3
119
- signing_key:
121
+ rubygems_version: 3.1.4
122
+ signing_key:
120
123
  specification_version: 4
121
124
  summary: Job framework with pluggable queues.
122
125
  test_files: []