Skip to content

Conversation

@huangdijia
Copy link
Contributor

@huangdijia huangdijia commented Nov 13, 2025

Summary

This PR introduces a new fluent dispatch API that provides a more expressive and flexible way to dispatch jobs, AMQP messages, and Kafka messages. The implementation follows Laravel's dispatch pattern while adapting it for Hyperf's architecture.

Key Features

New dispatch() Helper Function

  • Namespace-qualified helper: FriendsOfHyperf\Support\dispatch()
  • Returns pending dispatch objects that support method chaining
  • Automatically wraps closures in CallQueuedClosure
  • Type-safe return types for better IDE support

Pending Dispatch Classes

  1. PendingAsyncQueueDispatch (for async queue jobs)

    • onPool(string $pool) - Set the queue pool
    • delay(int $delay) - Set delay in seconds
    • setMaxAttempts(int $maxAttempts) - Set maximum retry attempts
  2. PendingAmqpProducerMessageDispatch (for AMQP messages)

    • onPool(string $pool) - Set the AMQP connection pool
    • setPayload(mixed $data) - Set message payload
    • withHeader(string $key, mixed $value, ?int $ttl) - Add custom headers
    • setConfirm(bool $confirm) - Enable publisher confirms
    • setTimeout(int $timeout) - Set timeout in seconds
  3. PendingKafkaProducerMessageDispatch (for Kafka messages)

    • onPool(string $pool) - Set the Kafka producer pool
    • setKey(string $key) - Set partition key
    • setValue(string $value) - Set message value
    • withHeader(string $key, string $value) - Add custom headers

Additional Features

  • All pending dispatch classes support Hyperf's Conditionable trait for conditional method chaining
  • Automatic execution on object destruction (RAII pattern)
  • Backward compatible - existing code continues to work

Example Usage

use function FriendsOfHyperf\Support\dispatch;

// Async queue with fluent API
dispatch(new ProcessPodcast($podcast))
    ->onPool('high-priority')
    ->delay(60)
    ->setMaxAttempts(3);

// AMQP message with fluent API
dispatch($amqpMessage)
    ->onPool('notifications')
    ->withHeader('trace-id', $traceId)
    ->setConfirm(true)
    ->setTimeout(10);

// Kafka message with fluent API
dispatch($kafkaMessage)
    ->onPool('events')
    ->withHeader('user-id', $userId)
    ->setKey($partitionKey);

// Closure support with async queue
dispatch(function () use ($data) {
    // Process data
})->onPool('default')->delay(30);

// Conditional chaining
dispatch($job)
    ->when($isPriority, fn($d) => $d->onPool('high-priority'))
    ->unless($isImmediate, fn($d) => $d->delay(60));

Migration Notes

Deprecation Notice

The global dispatch() helper in friendsofhyperf/helpers is now deprecated and will be removed in v3.2. Users should migrate to the namespace-qualified version:

// Old (deprecated)
dispatch($job);

// New (recommended)
use function FriendsOfHyperf\Support\dispatch;
dispatch($job);

Breaking Changes

None. This PR is fully backward compatible.

Test Plan

  • Unit tests for all dispatch scenarios (55 test assertions)
  • Test async queue dispatch with various configurations
  • Test AMQP message dispatch with headers and confirmation
  • Test Kafka message dispatch with headers and partitioning
  • Test closure wrapping in CallQueuedClosure
  • Test fluent method chaining
  • Test conditional chaining with Conditionable trait
  • Test error handling and edge cases
  • Test backward compatibility
  • Verify automatic execution on object destruction

Benefits

  1. Improved Developer Experience: Fluent API makes code more readable and self-documenting
  2. Type Safety: Strong return types enable better IDE autocomplete and static analysis
  3. Consistency: Unified API across different message broker types
  4. Flexibility: Conditional chaining enables dynamic configuration based on runtime conditions
  5. Maintainability: Cleaner code structure reduces cognitive load

Related Issues

Closes any related issues if applicable.

Checklist

  • Code follows project conventions
  • Added comprehensive tests
  • All tests pass
  • Documentation/examples included in commit message
  • Backward compatible
  • No breaking changes

Summary by CodeRabbit

  • 新功能

    • 引入统一分发入口,支持异步队列、AMQP 与 Kafka 的延迟(析构时)发送与流式配置(池、延迟、确认、头等)。
  • 文档

    • 添加分发函数的弃用注记并给出替代建议;补充参数与返回类型说明。
  • 测试

    • 新增全面的分发系统测试,覆盖闭包、作业、消息、链式配置、条件分支与错误路径。

This commit introduces a new fluent dispatch API to provide a more expressive and flexible way to dispatch jobs, AMQP messages, and Kafka messages.

Key changes:
- Add new `FriendsOfHyperf\Support\dispatch()` helper function that returns pending dispatch objects
- Implement `PendingAsyncQueueDispatch` for async queue jobs with fluent methods: `onPool()`, `delay()`, `setMaxAttempts()`
- Implement `PendingAmqpProducerMessageDispatch` for AMQP messages with fluent methods: `onPool()`, `setPayload()`, `withHeader()`, `setConfirm()`, `setTimeout()`
- Implement `PendingKafkaProducerMessageDispatch` for Kafka messages with fluent methods: `onPool()`, `setKey()`, `setValue()`, `withHeader()`
- All pending dispatch classes support Hyperf's `Conditionable` trait for conditional chaining
- Automatically wrap closures in `CallQueuedClosure` when dispatched
- Deprecate global `dispatch()` helper in favor of namespace-qualified version
- Add comprehensive test coverage for all dispatch scenarios

Benefits:
- Cleaner, more readable code with method chaining
- Type-safe dispatch configuration
- Consistent API across different message broker types
- Backward compatible with existing code

Example usage:
```php
use function FriendsOfHyperf\Support\dispatch;

// Async queue with fluent API
dispatch(new ProcessPodcast($podcast))
    ->onPool('high-priority')
    ->delay(60)
    ->setMaxAttempts(3);

// AMQP message with fluent API
dispatch($amqpMessage)
    ->onPool('notifications')
    ->withHeader('trace-id', $traceId)
    ->setConfirm(true)
    ->setTimeout(10);

// Kafka message with fluent API
dispatch($kafkaMessage)
    ->onPool('events')
    ->withHeader('user-id', $userId)
    ->setKey($partitionKey);

// Closure support
dispatch(function () {
    // Job logic here
})->onPool('default')->delay(30);
```
@coderabbitai
Copy link

coderabbitai bot commented Nov 13, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

新增命名空间下的 dispatch() 辅助函数及三个 Pending*Dispatch 类(AMQP、AsyncQueue、Kafka),将消息/任务的实际发送延迟到对象销毁时执行;同时在旧 helpers 的 dispatch docblock 中添加弃用说明并更新相关类型声明与测试。

Changes

Cohort / File(s) 变更摘要
弃用注释
src/helpers/src/Functions.php
为全局 dispatch 函数的 docblock 添加弃用说明(自 v3.1 弃用,v3.2 移除),不改变实现签名或行为。
新增 Pending 分发类(AMQP)
src/support/src/Bus/PendingAmqpProducerMessageDispatch.php
新增类 PendingAmqpProducerMessageDispatch:封装 ProducerMessageInterface,支持 onPool/setPayload/withHeader/setConfirm/setTimeout 等链式配置;在析构时通过容器的 AMQP Producer 发送消息,并对 headers 做懒初始化(AMQPTable)。
新增 Pending 分发类(AsyncQueue)
src/support/src/Bus/PendingAsyncQueueDispatch.php
新增类 PendingAsyncQueueDispatch:封装 JobInterface,支持 setMaxAttempts/onPool/delay 等链式配置;在析构时通过容器的 AsyncQueue Driver 推送任务(默认 pool 为 "default",delay 为 0)。
新增 Pending 分发类(Kafka)
src/support/src/Bus/PendingKafkaProducerMessageDispatch.php
新增类 PendingKafkaProducerMessageDispatch:封装 Kafka ProduceMessage,支持 onPool/setKey/setValue/withHeader 等链式配置;在析构时通过 ProducerManager 的生产者调用 sendBatch 发送消息,并对 headers 使用 RecordHeader。
核心辅助函数(Support)
src/support/src/Functions.php
新增命名空间下 dispatch($job) 函数:对传入类型(Closure、ProducerMessageInterface、ProduceMessage、JobInterface)进行匹配并返回相应的 Pending*Dispatch 对象;不支持类型时抛出 InvalidArgumentException;对 Closure 做 CallQueuedClosure 包装。
测试
tests/Support/DispatchTest.php
新增 DispatchTest:覆盖闭包、JobInterface、AMQP/Kafka 消息、链式 API、析构时执行、条件配置与错误路径等多个场景;使用容器 mocks 验证在析构时驱动/生产者被调用。
类型声明/导出调整
types/Helpers/Functions.php, types/Support/Support.php
types/Helpers/Functions.php 中移除对全局 dispatch() 的导出测试;types/Support/Support.php 新增对命名空间 dispatch 的导入与对返回类型(PendingAsyncQueueDispatch)的类型断言补充。

Sequence Diagram(s)

sequenceDiagram
    participant User as 用户代码
    participant SupportFns as FriendsOfHyperf\Support\dispatch()
    participant Pending as Pending*Dispatch
    participant Container as ApplicationContext
    participant Driver as 驱动/生产者

    User->>SupportFns: dispatch($job)
    activate SupportFns
    SupportFns->>SupportFns: 匹配类型 (Closure / AMQP / Kafka / Job)
    alt AMQP
        SupportFns-->>Pending: 返回 PendingAmqpProducerMessageDispatch
    else Kafka
        SupportFns-->>Pending: 返回 PendingKafkaProducerMessageDispatch
    else AsyncQueue
        SupportFns-->>Pending: 返回 PendingAsyncQueueDispatch
    else Closure
        SupportFns-->>Pending: 包装为 CallQueuedClosure -> PendingAsyncQueueDispatch
    else Unsupported
        SupportFns-->>User: 抛出 InvalidArgumentException
    end
    deactivate SupportFns

    User->>Pending: 链式配置 (onPool/setTimeout/delay/withHeader...)
    activate Pending
    Pending-->>User: 返回 this
    deactivate Pending

    Note over User,Pending: Pending 对象销毁时触发实际发送
    User->>Pending: __destruct()
    activate Pending
    Pending->>Container: getContainer()->get(Driver)
    Pending->>Driver: produce()/sendBatch()/push()
    Driver-->>Pending: 返回/抛错
    deactivate Pending
Loading

Estimated code review effort

🎯 3 (中等) | ⏱️ ~25 分钟

  • 建议重点检查:
    • 三个 Pending*Dispatch 在析构中调用容器/驱动的容错与异常处理逻辑。
    • AMQP/Kafka header 的懒初始化与目标类型兼容性(AMQPTable / RecordHeader)。
    • dispatch() 的类型匹配顺序、Closure 包装与边界情况(接口存在但类型不匹配)以及抛错信息一致性。
    • 单元测试的 mock 配置是否准确模拟缺失驱动/生产者的错误分支。

Possibly related PRs

Poem

🐰 我是派信的小兔子,口袋里藏着队列梦,
三路消息悄悄待命,析构一刻齐飞奔。
AMQP、Kafka 与 Async,链式点点都随身,
一跃送达云端远,胡萝卜奖励请别忘。 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% 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 PR标题准确反映了主要变更:引入了dispatch()辅助函数的流畅API,这正是本PR的核心目标。

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e0e126 and beb8d27.

📒 Files selected for processing (3)
  • src/support/src/Functions.php (1 hunks)
  • types/Helpers/Functions.php (1 hunks)
  • types/Support/Support.php (2 hunks)

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 PHPStan (2.1.31)

At least one path must be specified to analyse.


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

@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: 0

🧹 Nitpick comments (1)
src/support/src/Functions.php (1)

39-44: 简化类型检查逻辑。

interface_exists()class_exists() 检查是多余的。如果 instanceof 检查成功,则该接口或类必然已存在。这些防御性检查增加了不必要的运行时开销。

可以简化为:

 return match (true) {
-    interface_exists(ProducerMessageInterface::class) && $job instanceof ProducerMessageInterface => new PendingAmqpProducerMessageDispatch($job),
-    class_exists(ProduceMessage::class) && $job instanceof ProduceMessage => new PendingKafkaProducerMessageDispatch($job),
-    interface_exists(JobInterface::class) && $job instanceof JobInterface => new PendingAsyncQueueDispatch($job),
+    $job instanceof ProducerMessageInterface => new PendingAmqpProducerMessageDispatch($job),
+    $job instanceof ProduceMessage => new PendingKafkaProducerMessageDispatch($job),
+    $job instanceof JobInterface => new PendingAsyncQueueDispatch($job),
     default => throw new InvalidArgumentException('Unsupported job type.')
 };
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d31d443 and 7e0e126.

📒 Files selected for processing (6)
  • src/helpers/src/Functions.php (1 hunks)
  • src/support/src/Bus/PendingAmqpProducerMessageDispatch.php (1 hunks)
  • src/support/src/Bus/PendingAsyncQueueDispatch.php (1 hunks)
  • src/support/src/Bus/PendingKafkaProducerMessageDispatch.php (1 hunks)
  • src/support/src/Functions.php (1 hunks)
  • tests/Support/DispatchTest.php (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/*/src/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

All component PHP code must use the namespace pattern FriendsOfHyperf{ComponentName}

Files:

  • src/support/src/Functions.php
  • src/support/src/Bus/PendingAmqpProducerMessageDispatch.php
  • src/helpers/src/Functions.php
  • src/support/src/Bus/PendingKafkaProducerMessageDispatch.php
  • src/support/src/Bus/PendingAsyncQueueDispatch.php
**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.php: Code style must follow PSR-12 and be formatted by PHP-CS-Fixer per .php-cs-fixer.php
Run PHPStan and keep the codebase passing per phpstan.neon.dist

Files:

  • src/support/src/Functions.php
  • src/support/src/Bus/PendingAmqpProducerMessageDispatch.php
  • src/helpers/src/Functions.php
  • tests/Support/DispatchTest.php
  • src/support/src/Bus/PendingKafkaProducerMessageDispatch.php
  • src/support/src/Bus/PendingAsyncQueueDispatch.php
tests/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

All tests should reside under tests/ and use PHPUnit following Hyperf testing patterns

Files:

  • tests/Support/DispatchTest.php
🧬 Code graph analysis (5)
src/support/src/Functions.php (5)
src/async-queue-closure-job/src/CallQueuedClosure.php (1)
  • CallQueuedClosure (21-55)
src/support/src/Bus/PendingAmqpProducerMessageDispatch.php (1)
  • PendingAmqpProducerMessageDispatch (22-76)
src/support/src/Bus/PendingAsyncQueueDispatch.php (1)
  • PendingAsyncQueueDispatch (19-56)
src/support/src/Bus/PendingKafkaProducerMessageDispatch.php (1)
  • PendingKafkaProducerMessageDispatch (25-67)
src/helpers/src/Functions.php (1)
  • dispatch (197-224)
src/support/src/Bus/PendingAmqpProducerMessageDispatch.php (3)
src/http-client/src/PendingRequest.php (2)
  • pool (841-852)
  • timeout (585-590)
src/support/src/Bus/PendingAsyncQueueDispatch.php (3)
  • __construct (27-29)
  • __destruct (31-37)
  • onPool (45-49)
src/support/src/Bus/PendingKafkaProducerMessageDispatch.php (4)
  • __construct (31-33)
  • __destruct (35-41)
  • onPool (43-47)
  • withHeader (61-66)
tests/Support/DispatchTest.php (5)
src/async-queue-closure-job/src/CallQueuedClosure.php (1)
  • CallQueuedClosure (21-55)
src/support/src/Bus/PendingAmqpProducerMessageDispatch.php (5)
  • PendingAmqpProducerMessageDispatch (22-76)
  • onPool (44-48)
  • setConfirm (65-69)
  • setTimeout (71-75)
  • withHeader (56-63)
src/support/src/Bus/PendingAsyncQueueDispatch.php (4)
  • PendingAsyncQueueDispatch (19-56)
  • onPool (45-49)
  • delay (51-55)
  • setMaxAttempts (39-43)
src/support/src/Bus/PendingKafkaProducerMessageDispatch.php (3)
  • PendingKafkaProducerMessageDispatch (25-67)
  • onPool (43-47)
  • withHeader (61-66)
src/support/src/Functions.php (1)
  • dispatch (33-45)
src/support/src/Bus/PendingKafkaProducerMessageDispatch.php (3)
src/facade/src/Kafka.php (2)
  • Kafka (22-54)
  • sendBatch (33-47)
src/support/src/Bus/PendingAmqpProducerMessageDispatch.php (4)
  • __construct (32-34)
  • __destruct (36-42)
  • onPool (44-48)
  • withHeader (56-63)
src/support/src/Bus/PendingAsyncQueueDispatch.php (3)
  • __construct (27-29)
  • __destruct (31-37)
  • onPool (45-49)
src/support/src/Bus/PendingAsyncQueueDispatch.php (3)
src/facade/src/AsyncQueue.php (1)
  • AsyncQueue (22-40)
src/support/src/Bus/PendingAmqpProducerMessageDispatch.php (3)
  • __construct (32-34)
  • __destruct (36-42)
  • onPool (44-48)
src/support/src/Bus/PendingKafkaProducerMessageDispatch.php (3)
  • __construct (31-33)
  • __destruct (35-41)
  • onPool (43-47)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: Test on PHP 8.3 with Swoole 5.1.8
  • GitHub Check: Test on PHP 8.1 with Swoole 6.1.2
  • GitHub Check: Test on PHP 8.2 with Swoole 5.1.8
  • GitHub Check: Test on PHP 8.1 with Swoole 5.1.8
  • GitHub Check: Test on PHP 8.1 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.2 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.2 with Swoole 6.1.2
  • GitHub Check: Test on PHP 8.3 with Swoole 6.1.2
  • GitHub Check: Test on PHP 8.3 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.1 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.1 with Swoole 5.1.8
  • GitHub Check: Test on PHP 8.3 with Swoole 6.1.2
  • GitHub Check: Test on PHP 8.1 with Swoole 6.1.2
  • GitHub Check: Test on PHP 8.2 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.2 with Swoole 5.1.8
  • GitHub Check: Test on PHP 8.2 with Swoole 6.1.2
  • GitHub Check: Test on PHP 8.3 with Swoole 5.1.8
  • GitHub Check: Test on PHP 8.3 with Swoole 6.0.2
🔇 Additional comments (8)
src/helpers/src/Functions.php (1)

193-193: 文档更新正确,提供了清晰的迁移路径。

弃用注解明确说明了版本时间线和推荐的替代方案,有助于用户平滑迁移。

src/support/src/Functions.php (1)

35-37: 闭包包装逻辑正确。

将闭包自动包装为 CallQueuedClosure 使得队列可以序列化和执行闭包,这是队列系统的常见模式。

src/support/src/Bus/PendingAsyncQueueDispatch.php (1)

19-56: 实现清晰且符合预期。

该类通过析构函数模式实现延迟执行,提供流式 API 用于配置队列、延迟和最大重试次数。使用 Conditionable trait 支持条件链式调用,整体设计合理。

src/support/src/Bus/PendingAmqpProducerMessageDispatch.php (2)

36-42: 析构函数逻辑正确,短路求值使用得当。

Line 38 使用 && 短路求值来条件性地设置 pool name,简洁高效。析构函数确保在对象销毁时自动发送消息。


56-63: 验证外部库 Hyperf AMQP 的 ProducerMessageInterface 公开 API

根据代码分析和 web 搜索:

  • ProducerMessageInterface 来自外部库 Hyperf\Amqp\Message,而非本地实现
  • 当前代码通过闭包的 call() 方法访问 $this->message 的私有属性 $properties 来设置 application_headers
  • 相同的闭包模式也被使用在 src/sentry/src/Tracing/Aspect/AmqpProducerAspect.php
  • web 搜索结果显示 ProducerMessageInterface 可能不提供便捷的公开方法来动态添加 headers

通过闭包访问私有属性是在与受限外部库交互时的合理适配方案,尤其是:

  • 代码有明确的 @property 类型提示声明意图
  • 代码有 @phpstan-ignore-line 注释
  • 此模式在代码库中被一致使用
  • 功能由测试覆盖

请确认 Hyperf AMQP 库的 ProducerMessageInterface 文档,验证是否真的不存在公开的 header 设置方法(如 setHeader()addHeader() 等)。如果公开方法存在,应使用之;如果不存在,当前实现是合理的。

src/support/src/Bus/PendingKafkaProducerMessageDispatch.php (2)

35-41: 析构函数实现正确。

通过 ProducerManager 获取生产者并使用 sendBatch 发送消息,符合 Hyperf Kafka 的使用模式。


49-66: 闭包模式是必要的实现方案,而非可避免的脆弱性。

验证发现,longlang/phpkafka v1.2.5 中的 ProduceMessage 类不提供公共的 setter 方法(如 setKey()setValue() 等)来修改已构建对象的属性。属性 keyvalueheaders 都是私有的。因此,使用闭包访问这些私有属性是修改已构建消息对象的唯一可行方案

这个实现方式:

  • 与现有的 PendingAmqpProducerMessageDispatch 模式保持一致
  • 由测试用例验证其正确性(如 testPendingKafkaProducerMessageDispatchFluentChaining
  • 是外部库 API 设计的必然结果,而非代码设计问题

无需修改。

tests/Support/DispatchTest.php (1)

1-548: 测试覆盖全面且结构良好。

测试套件包含 55 个断言,覆盖了:

  • 不同任务类型的调度(闭包、JobInterface、AMQP、Kafka)
  • 流式 API 的链式调用
  • 条件配置(when/unless)
  • 析构时的执行行为
  • 错误处理和向后兼容性

使用 Mockery 进行依赖隔离,通过反射验证内部状态,测试设计合理。

@huangdijia huangdijia merged commit 5c5e385 into main Nov 13, 2025
3 checks passed
@huangdijia huangdijia deleted the feature/dispatch-helper-fluent-api branch November 13, 2025 23:58
huangdijia added a commit that referenced this pull request Nov 14, 2025
* feat: introduce fluent API for dispatch() helper function

This commit introduces a new fluent dispatch API to provide a more expressive and flexible way to dispatch jobs, AMQP messages, and Kafka messages.

Key changes:
- Add new `FriendsOfHyperf\Support\dispatch()` helper function that returns pending dispatch objects
- Implement `PendingAsyncQueueDispatch` for async queue jobs with fluent methods: `onPool()`, `delay()`, `setMaxAttempts()`
- Implement `PendingAmqpProducerMessageDispatch` for AMQP messages with fluent methods: `onPool()`, `setPayload()`, `withHeader()`, `setConfirm()`, `setTimeout()`
- Implement `PendingKafkaProducerMessageDispatch` for Kafka messages with fluent methods: `onPool()`, `setKey()`, `setValue()`, `withHeader()`
- All pending dispatch classes support Hyperf's `Conditionable` trait for conditional chaining
- Automatically wrap closures in `CallQueuedClosure` when dispatched
- Deprecate global `dispatch()` helper in favor of namespace-qualified version
- Add comprehensive test coverage for all dispatch scenarios

Benefits:
- Cleaner, more readable code with method chaining
- Type-safe dispatch configuration
- Consistent API across different message broker types
- Backward compatible with existing code

Example usage:
```php
use function FriendsOfHyperf\Support\dispatch;

// Async queue with fluent API
dispatch(new ProcessPodcast($podcast))
    ->onPool('high-priority')
    ->delay(60)
    ->setMaxAttempts(3);

// AMQP message with fluent API
dispatch($amqpMessage)
    ->onPool('notifications')
    ->withHeader('trace-id', $traceId)
    ->setConfirm(true)
    ->setTimeout(10);

// Kafka message with fluent API
dispatch($kafkaMessage)
    ->onPool('events')
    ->withHeader('user-id', $userId)
    ->setKey($partitionKey);

// Closure support
dispatch(function () {
    // Job logic here
})->onPool('default')->delay(30);
```

* feat: add dispatch() function tests in Support and Functions helpers

* fix: update docblock for dispatch() function to clarify parameter type

---------

Co-Authored-By: Deeka Wong <8337659+huangdijia@users.noreply.github.com>
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.

2 participants