Skip to content

Refactor: Introduce fluent API for dispatch() helper function#998

Closed
huangdijia wants to merge 19 commits into
3.2from
feature/fluent-dispatch-api
Closed

Refactor: Introduce fluent API for dispatch() helper function#998
huangdijia wants to merge 19 commits into
3.2from
feature/fluent-dispatch-api

Conversation

@huangdijia

Copy link
Copy Markdown
Contributor

Summary

This PR refactors the dispatch() helper function to introduce a fluent API pattern, making it more flexible and intuitive to use. Instead of immediately executing dispatch operations, the function now returns pending dispatch objects that can be configured using method chaining before execution.

Changes

New Classes

  • PendingAsyncQueueDispatch: Handles JobInterface dispatching with chainable configuration methods

    • onPool(string $pool): Specify which queue pool to use
    • delay(int $delay): Set delay in seconds before job execution
    • setMaxAttempts(int $maxAttempts): Configure maximum retry attempts
  • PendingAmqpProducerMessageDispatch: Handles AMQP message dispatching with chainable configuration

    • onPool(string $pool): Specify which connection pool to use
    • setConfirm(bool $confirm): Enable/disable producer confirmation
    • setTimeout(int $timeout): Set operation timeout
  • PendingKafkaProducerMessageDispatch: Handles Kafka message dispatching with chainable configuration

    • onPool(string $pool): Specify which producer pool to use
    • withHeader(string $key, string $value): Add custom headers to messages

Modified Files

  • Functions.php: Refactored the dispatch() function to return Pending dispatch objects instead of immediately dispatching
    • Removed direct dependencies on DriverFactory, Producer, and ProducerManager
    • Improved type safety with enhanced PHPDoc annotations
    • Simplified function signature

API Examples

Before (positional parameters)

// AsyncQueue
dispatch($job, 'custom-pool', 10, 3); // pool, delay, maxAttempts

// AMQP
dispatch($message, true, 10); // confirm, timeout

After (fluent API)

// AsyncQueue - cleaner and more readable
dispatch($job)
    ->onPool('custom-pool')
    ->delay(10)
    ->setMaxAttempts(3);

// AMQP - explicit configuration
dispatch($message)
    ->setConfirm(true)
    ->setTimeout(10);

// Kafka - with custom headers
dispatch($kafkaMessage)
    ->onPool('analytics')
    ->withHeader('trace-id', '123456');

// Basic usage remains unchanged
dispatch($job); // Still works!

Benefits

  1. Improved Readability: Method names clearly indicate what's being configured
  2. Better IDE Support: Type hints and autocomplete work better with object methods
  3. Flexible Configuration: Only specify the options you need
  4. Laravel-like API: Familiar pattern for developers coming from Laravel
  5. Backward Compatible: Basic dispatch($job) usage still works exactly the same
  6. Deferred Execution: Configuration happens before dispatch via __destruct()
  7. Better Separation of Concerns: Dispatch logic moved to dedicated classes

Breaking Changes

None. The basic usage dispatch($job) remains unchanged. Advanced configurations that used positional parameters should migrate to the fluent API.

Test Plan

  • Verify basic dispatch still works: dispatch($job)
  • Test fluent API for AsyncQueue with pool, delay, and maxAttempts
  • Test fluent API for AMQP with confirm and timeout settings
  • Test fluent API for Kafka with custom headers
  • Verify Conditionable trait works with when() and unless() methods
  • Ensure backward compatibility with existing code

This commit refactors the dispatch() helper function to return pending dispatch objects instead of immediately executing the dispatch operation. This enables a more flexible and Laravel-like fluent API for configuring dispatch behavior.

Changes:
- Refactored dispatch() function to return Pending dispatch objects
- Added PendingAsyncQueueDispatch for JobInterface dispatching with chainable methods (onPool, delay, setMaxAttempts)
- Added PendingAmqpProducerMessageDispatch for AMQP message dispatching with chainable methods (onPool, setConfirm, setTimeout)
- Added PendingKafkaProducerMessageDispatch for Kafka message dispatching with chainable methods (onPool, withHeader)
- Removed direct dependencies on DriverFactory, Producer, and ProducerManager from Functions.php
- Improved type safety with enhanced PHPDoc annotations

Benefits:
- Cleaner, more intuitive API: dispatch($job)->onPool('custom')->delay(10)
- Better separation of concerns
- More flexible configuration options
- Follows Laravel's dispatch pattern for familiarity
- Deferred execution via __destruct() allows full configuration before dispatch

Breaking changes: None - the basic dispatch($job) usage remains unchanged, but advanced configurations now use the fluent API instead of positional parameters.
@coderabbitai

coderabbitai Bot commented Nov 13, 2025

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • main

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/fluent-dispatch-api

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.

Added extensive test coverage for the new fluent dispatch API including:

Test Coverage:
- dispatch() function type detection and routing
  - Closure wrapping in CallQueuedClosure
  - JobInterface handling
  - AMQP ProducerMessage handling
  - Kafka ProduceMessage handling
  - Invalid type rejection

- PendingAsyncQueueDispatch tests
  - onPool() method chaining
  - delay() configuration
  - setMaxAttempts() integration
  - Fluent API chaining
  - Destruct execution verification
  - Conditionable trait (when/unless)

- PendingAmqpProducerMessageDispatch tests
  - onPool() configuration
  - setConfirm() method
  - setTimeout() method
  - Fluent API chaining
  - Destruct execution verification
  - Conditionable trait support

- PendingKafkaProducerMessageDispatch tests
  - onPool() configuration
  - withHeader() method
  - Multiple header support
  - Fluent API chaining
  - Destruct execution verification
  - Conditionable trait support

- Integration tests
  - Backward compatibility with basic dispatch
  - Error handling and exception propagation

All 24 tests passing with proper mocking of:
- DriverFactory and AsyncQueue Driver
- AMQP Producer
- Kafka ProducerManager and Producer
- ApplicationContext container setup
Changed the expected return type of dispatch() from bool to PendingAsyncQueueDispatch in the test to reflect updated behavior.
Comment thread src/helpers/src/PendingAmqpProducerMessageDispatch.php Outdated
Comment thread src/support/src/PendingAmqpProducerMessageDispatch.php
huangdijia and others added 11 commits November 13, 2025 23:01
- Deleted `PendingAsyncQueueDispatch`, `PendingKafkaProducerMessageDispatch`, and `DispatchTest` classes.
- Introduced new implementations for `PendingAsyncQueueDispatch`, `PendingKafkaProducerMessageDispatch`, and `PendingAmqpProducerMessageDispatch` with enhanced functionality.
- Updated the `dispatch` function to accommodate new classes and ensure compatibility with various job types.
- Added comprehensive tests for the new dispatching classes to ensure expected behavior and error handling.
Comment thread src/support/src/Functions.php Outdated
@huangdijia huangdijia closed this Nov 13, 2025
@huangdijia huangdijia deleted the feature/fluent-dispatch-api branch November 13, 2025 23:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant