Skip to content

Conversation

@mensfeld
Copy link
Collaborator

@mensfeld mensfeld commented Nov 2, 2025

Summary by CodeRabbit

  • New Features

    • Added ActiveJob Continuations support for Rails 8.1+, enabling advanced job checkpointing and resumable execution with proper graceful shutdown state tracking.
  • Chores

    • Enhanced CI/CD pipeline with automated job status verification.
  • Tests

    • Added comprehensive integration and unit tests for continuation features, including timestamp handling and shutdown state detection.

@coderabbitai
Copy link

coderabbitai bot commented Nov 2, 2025

Walkthrough

Implements ActiveJob Continuations support for Rails 8.1+ by adding shutdown state tracking through new stopping? methods on Launcher and ActiveJob adapter. Exposes launcher instance through Runner. Includes integration and unit tests, CI workflow updates, and documentation.

Changes

Cohort / File(s) Summary
Stopping State Tracking
lib/shoryuken/launcher.rb, lib/shoryuken/runner.rb, lib/shoryuken/extensions/active_job_adapter.rb
Adds internal @stopping state to Launcher initialized as false, exposes it via stopping? method. Sets @stopping to true in both stop! and stop methods. Exposes launcher via attr_reader :launcher on Runner. Adapter's stopping? method delegates to Shoryuken::Runner.instance.launcher.stopping? to support ActiveJob Continuations.
Tests
spec/integration/active_job_continuation_spec.rb, spec/shoryuken/extensions/active_job_continuation_spec.rb, spec/shoryuken/launcher_spec.rb
Adds integration tests for ContinuableTestJob with checkpoint/resume behavior across work phases. Adds unit tests for adapter stopping? state, timestamp handling with delay_seconds validation, and enqueue_at behavior for past/current/future timestamps. Tests Launcher#stopping? with stop/stop! invocations. Tests guard on Rails 8+ availability.
Documentation & CI
CHANGELOG.md, .github/workflows/specs.yml
Documents new ActiveJob Continuations feature in [7.0.0] Unreleased. Adds CI helper job that runs after all_specs and rails_specs to validate build success and fails if dependent jobs are in failure, cancelled, or skipped state.

Sequence Diagram

sequenceDiagram
    participant App as Rails App
    participant AJ as ActiveJob
    participant Adapter as ShoryukenAdapter
    participant Runner as Runner
    participant Launcher as Launcher
    participant Job as Job

    App->>AJ: Graceful shutdown signal
    AJ->>Adapter: Query stopping?
    Adapter->>Runner: Get launcher instance
    Runner->>Adapter: Return launcher
    Adapter->>Launcher: Call stopping?
    
    par Launcher State Update
        Runner->>Launcher: Call stop! / stop
        Launcher->>Launcher: Set @stopping = true
    end
    
    Launcher->>Adapter: Return stopping? = true
    Adapter->>AJ: Return true
    AJ->>Job: Signal to checkpoint<br/>instead of reject
    Job->>AJ: Enqueue continuation<br/>with checkpoint state
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Verify @stopping is consistently set in both stop and stop! methods in Launcher
  • Confirm Rails version gating in tests correctly skips on Rails < 8.0
  • Validate that the adapter properly handles the case where Shoryuken::Runner.instance.launcher is unavailable (returns false)

Possibly related PRs

  • Server side logging #850: Modifies the same ActiveJob adapter class (lib/shoryuken/extensions/active_job_adapter.rb), involving class inheritance changes that may interact with the new stopping? method addition.

Suggested reviewers

  • phstc

Poem

🐰 Hops with glee

Jobs now pause to breathe and rest,
Continuations put to test,
Stopping gracefully with care,
Rails and Shoryuken, a perfect pair! 🎉

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "support AJ continuation in rails 8.1" directly and clearly captures the primary objective of this pull request. "AJ" (ActiveJob) and "continuation" are standard Rails terminology, making the intent immediately understandable. The title is concise, specific about the target Rails version, and accurately reflects the main changes across all modified files—including the launcher stopping state tracking, adapter public methods, integration tests, and CI workflow updates that collectively enable ActiveJob Continuations support. The title avoids vague language, noise, and emoji while remaining readable and scannable in git history.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch aj-continuation-support

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for ActiveJob Continuations (Rails 8.1+) to Shoryuken by implementing the stopping? method in the ActiveJob adapter. This allows jobs to detect when Shoryuken is shutting down and checkpoint their progress for graceful resumption.

Key changes:

  • Added stopping? method to the ActiveJob adapter that checks Shoryuken's shutdown state
  • Added stopping? flag to the Launcher class to track shutdown state
  • Exposed the Launcher instance through the Runner for adapter access

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
lib/shoryuken/launcher.rb Added @stopping flag and stopping? method to track shutdown state
lib/shoryuken/runner.rb Exposed launcher instance via attr_reader for external access
lib/shoryuken/extensions/active_job_adapter.rb Implemented stopping? method to support ActiveJob Continuations
spec/shoryuken/launcher_spec.rb Added tests for stopping? method behavior
spec/shoryuken/extensions/active_job_continuation_spec.rb Added unit tests for ActiveJob Continuation support
spec/integration/active_job_continuation_spec.rb Added integration tests for continuable jobs
CHANGELOG.md Documented the new ActiveJob Continuations feature

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mensfeld mensfeld marked this pull request as ready for review November 2, 2025 17:04
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3bfac4d and 5e1eb97.

📒 Files selected for processing (8)
  • .github/workflows/specs.yml (1 hunks)
  • CHANGELOG.md (1 hunks)
  • lib/shoryuken/extensions/active_job_adapter.rb (1 hunks)
  • lib/shoryuken/launcher.rb (3 hunks)
  • lib/shoryuken/runner.rb (1 hunks)
  • spec/integration/active_job_continuation_spec.rb (1 hunks)
  • spec/shoryuken/extensions/active_job_continuation_spec.rb (1 hunks)
  • spec/shoryuken/launcher_spec.rb (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
spec/shoryuken/launcher_spec.rb (3)
lib/shoryuken/extensions/active_job_adapter.rb (1)
  • stopping? (48-51)
lib/shoryuken/launcher.rb (3)
  • stopping? (19-21)
  • stop (43-56)
  • stop! (30-41)
lib/shoryuken/manager.rb (1)
  • stop_new_dispatching (30-32)
CHANGELOG.md (2)
lib/shoryuken/extensions/active_job_concurrent_send_adapter.rb (2)
  • ActiveJob (5-50)
  • ShoryukenConcurrentSendAdapter (20-48)
spec/integration/launcher_spec.rb (1)
  • include (107-125)
spec/integration/active_job_continuation_spec.rb (3)
lib/shoryuken/extensions/active_job_adapter.rb (7)
  • include (103-113)
  • perform (108-112)
  • stopping? (48-51)
  • instance (19-121)
  • instance (21-24)
  • enqueue_at (30-32)
  • enqueue_at (64-66)
lib/shoryuken/launcher.rb (2)
  • include (4-120)
  • stopping? (19-21)
lib/shoryuken/runner.rb (1)
  • include (15-139)
spec/shoryuken/extensions/active_job_continuation_spec.rb (1)
lib/shoryuken/extensions/active_job_adapter.rb (3)
  • stopping? (48-51)
  • enqueue_at (30-32)
  • enqueue_at (64-66)
lib/shoryuken/extensions/active_job_adapter.rb (1)
lib/shoryuken/launcher.rb (1)
  • stopping? (19-21)
lib/shoryuken/launcher.rb (1)
lib/shoryuken/extensions/active_job_adapter.rb (1)
  • stopping? (48-51)
🪛 GitHub Check: CodeQL
.github/workflows/specs.yml

[warning] 75-88: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{}}

🪛 RuboCop (1.81.6)
spec/integration/active_job_continuation_spec.rb

[warning] 15-51: Do not define constants this way within a block.

(Lint/ConstantDefinitionInBlock)

🔇 Additional comments (16)
.github/workflows/specs.yml (1)

74-88: LGTM! Standard CI success pattern.

The CI success job correctly aggregates the results of all spec jobs, ensuring the overall CI status reflects all test outcomes.

The static analysis warning about missing permissions is valid. Consider adding an explicit permissions block to follow security best practices:

  ci-success:
    name: CI Success
    runs-on: ubuntu-latest
    if: always()
    permissions:
      contents: read
    needs:
      - all_specs
      - rails_specs

This limits the GITHUB_TOKEN to read-only access, reducing security risk if the workflow is compromised.

CHANGELOG.md (1)

2-9: Excellent documentation of the new feature.

The changelog entry clearly describes the ActiveJob Continuations support, including key implementation details and the Rails PR reference.

lib/shoryuken/runner.rb (1)

19-20: Clean API addition with good documentation.

Exposing the launcher instance enables external components (like the ActiveJob adapter) to query the shutdown state. The documentation clearly indicates the return type.

spec/shoryuken/launcher_spec.rb (1)

105-125: Comprehensive test coverage for stopping? behavior.

The tests verify the default state and transitions after both stop and stop! are called, with appropriate mocking of manager dependencies.

lib/shoryuken/launcher.rb (3)

7-21: Well-documented stopping state implementation.

The stopping? method and @stopping flag are clearly documented and correctly initialized. The YARD documentation explains the purpose and usage for ActiveJob Continuations.


30-31: Correct state transition in stop!

Setting @stopping = true at the beginning of stop! ensures the flag is set before any shutdown logic executes.


43-44: Correct state transition in stop.

Setting @stopping = true at the beginning of stop ensures the flag is set before any shutdown logic executes, consistent with stop!.

lib/shoryuken/extensions/active_job_adapter.rb (2)

40-51: Robust implementation with safe navigation.

The stopping? method correctly uses the safe navigation operator to handle cases where the launcher is not yet initialized, returning false as a safe default.


70-75: Correct handling of past timestamps for continuations.

The calculate_delay method correctly allows negative delays (past timestamps), which SQS treats as immediate delivery. The 15-minute check only applies to future delays, which is the correct behavior for ActiveJob Continuations that may need to retry immediately.

spec/shoryuken/extensions/active_job_continuation_spec.rb (2)

22-51: Comprehensive stopping? behavior tests.

The tests cover all scenarios: launcher not initialized, launcher initialized but not stopping, and launcher stopping. Good use of test doubles to isolate the behavior.


53-95: Thorough timestamp handling tests.

The tests verify correct behavior for past, future, and current timestamps, including the critical requirement that past timestamps result in non-positive delay_seconds for immediate delivery.

spec/integration/active_job_continuation_spec.rb (5)

10-12: Appropriate version guard for Rails 8+ feature.

The skip condition correctly prevents these tests from running on Rails versions that don't support ActiveJob::Continuable.


15-51: Well-structured test job for continuation testing.

The ContinuableTestJob implementation correctly uses the step/checkpoint pattern with cursor tracking, execution logging, and checkpoint recording for validation.

Note: The RuboCop warning about defining constants in a block is acceptable in test context, as this is a standard RSpec pattern for test-specific classes.


53-70: Thorough stopping state tests.

The tests verify both uninitialized and initialized launcher scenarios, including the state transition when @stopping is set to true.


72-90: Critical test for continuation retry semantics.

This test verifies the key behavior that past timestamps (used in continuation retries) result in delay_seconds <= 0, ensuring immediate delivery through SQS.


93-144: Comprehensive timestamp boundary testing.

The tests cover all timestamp scenarios with appropriate assertions on delay_seconds values, including tolerance for timing variations.

@mensfeld mensfeld merged commit d118603 into main Nov 3, 2025
20 checks passed
@mensfeld mensfeld deleted the aj-continuation-support branch November 3, 2025 08:22
@myumura
Copy link
Contributor

myumura commented Nov 4, 2025

LGTM🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants