Skip to content

Commit

Permalink
Implement job batches
Browse files Browse the repository at this point in the history
  • Loading branch information
matteeyah committed Jan 14, 2024
1 parent 98b8c35 commit 2f364fa
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 0 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,24 @@ class MyJob < ActiveJob::Base
end
```

### Grouping jobs into batches

```ruby
job = MyJob.perform_later
other_job = OtherJob.perform_later

batch = ActiveJob::Status::Batch.new(job, other_job)
batch.status
# "queued"
```

The batch status can be `queued`, `failed`, `completed` or `working`.

1. The batch is considered `queued` if **all** of the jobs are `queued`
2. The batch is considered `failed` if **one** of the jobs is `failed`
3. The batch is considered `completed` if **all** of the jobs are `completed`
4. The batch is considered `working` in all other circumstances

## ActiveJob::Status and exceptions

Internally, ActiveJob::Status uses `ActiveSupport#rescue_from` to catch every `Exception` to apply the `failed` status
Expand Down
1 change: 1 addition & 0 deletions lib/activejob-status.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
require "activejob-status/status"
require "activejob-status/progress"
require "activejob-status/throttle"
require "activejob-status/batch"

module ActiveJob
module Status
Expand Down
23 changes: 23 additions & 0 deletions lib/activejob-status/batch.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

module ActiveJob
module Status
class Batch
def initialize(*jobs)
@statuses = jobs.map { |job| ActiveJob::Status.get(job) }
end

def status
if @statuses.all? { |status| status[:status] == "queued" }
"queued"
elsif @statuses.any? { |status| status[:status] == "failed" }
"failed"
elsif @statuses.all? { |status| status[:status] == "completed" }
"completed"
else
"working"
end
end
end
end
end
52 changes: 52 additions & 0 deletions spec/specs/active_job/status/batch_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# frozen_string_literal: true

require_relative "../../../spec_helper"
require_relative "../../../jobs/test_jobs"

RSpec.describe ActiveJob::Status::Batch do
describe "#status" do
it "returns queued when all jobs are queued" do
first_job = BaseJob.perform_later
second_job = BaseJob.perform_later
batch = described_class.new(first_job, second_job)

ActiveJob::Status.get(first_job).update(status: "queued")
ActiveJob::Status.get(second_job).update(status: "queued")

expect(batch.status).to eq("queued")
end

it "returns failed when one job is failed" do
first_job = BaseJob.perform_later
second_job = BaseJob.perform_later
batch = described_class.new(first_job, second_job)

ActiveJob::Status.get(first_job).update(status: "failed")
ActiveJob::Status.get(second_job).update(status: "completed")

expect(batch.status).to eq("failed")
end

it "returns completed when all jobs are completed" do
first_job = BaseJob.perform_later
second_job = BaseJob.perform_later
batch = described_class.new(first_job, second_job)

ActiveJob::Status.get(first_job).update(status: "completed")
ActiveJob::Status.get(second_job).update(status: "completed")

expect(batch.status).to eq("completed")
end

it "returns working in other cases" do
first_job = BaseJob.perform_later
second_job = BaseJob.perform_later
batch = described_class.new(first_job, second_job)

ActiveJob::Status.get(first_job).update(status: "queued")
ActiveJob::Status.get(second_job).update(status: "working")

expect(batch.status).to eq("working")
end
end
end

0 comments on commit 2f364fa

Please sign in to comment.