-
-
Notifications
You must be signed in to change notification settings - Fork 27
refactor: consolidate CallQueuedClosure to support package #1003
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,16 +4,216 @@ | |||||||||||||||||||||||||||||
| [](https://packagist.org/packages/friendsofhyperf/support) | ||||||||||||||||||||||||||||||
| [](https://github.com/friendsofhyperf/support) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Another support component for Hyperf. | ||||||||||||||||||||||||||||||
| A comprehensive support component for Hyperf providing essential utilities, helpers, and base classes. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Installation | ||||||||||||||||||||||||||||||
| ## Features | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - 🎯 **Fluent Dispatch API** - Elegant job dispatch with support for async queue, AMQP, and Kafka | ||||||||||||||||||||||||||||||
| - 🔄 **Closure Jobs** - Execute closures as background jobs with dependency injection | ||||||||||||||||||||||||||||||
| - 🛠️ **Helper Functions** - Collection of useful helper functions | ||||||||||||||||||||||||||||||
| - 📦 **Bus System** - Pending dispatch classes for various message systems | ||||||||||||||||||||||||||||||
| - 🧩 **Traits & Utilities** - Reusable traits and utility classes | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - Installation | ||||||||||||||||||||||||||||||
| ## Installation | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```shell | ||||||||||||||||||||||||||||||
| composer require friendsofhyperf/support | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Usage | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### Dispatch Helper Function | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The `dispatch()` helper function provides a fluent API for dispatching jobs to different systems: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| #### Async Queue (Closure Jobs) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||
| use function FriendsOfHyperf\Support\dispatch; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Simple closure dispatch to async queue | ||||||||||||||||||||||||||||||
| dispatch(function () { | ||||||||||||||||||||||||||||||
| // Your job logic here | ||||||||||||||||||||||||||||||
| logger()->info('Job executed!'); | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // With configuration | ||||||||||||||||||||||||||||||
| dispatch(function () { | ||||||||||||||||||||||||||||||
| // Your job logic here | ||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||
| ->onConnection('high-priority') | ||||||||||||||||||||||||||||||
| ->delay(60) // Execute after 60 seconds | ||||||||||||||||||||||||||||||
| ->setMaxAttempts(5); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // With dependency injection | ||||||||||||||||||||||||||||||
| dispatch(function (UserService $userService, LoggerInterface $logger) { | ||||||||||||||||||||||||||||||
| $users = $userService->getActiveUsers(); | ||||||||||||||||||||||||||||||
| $logger->info('Processing ' . count($users) . ' users'); | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| #### AMQP Producer Messages | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||
| use Hyperf\Amqp\Message\ProducerMessageInterface; | ||||||||||||||||||||||||||||||
| use function FriendsOfHyperf\Support\dispatch; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Dispatch AMQP message | ||||||||||||||||||||||||||||||
| dispatch($amqpMessage) | ||||||||||||||||||||||||||||||
| ->setPool('default') | ||||||||||||||||||||||||||||||
| ->setExchange('my.exchange') | ||||||||||||||||||||||||||||||
| ->setRoutingKey('my.routing.key') | ||||||||||||||||||||||||||||||
| ->setTimeout(10) | ||||||||||||||||||||||||||||||
| ->setConfirm(true); | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| #### Kafka Producer Messages | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||
| use Hyperf\Kafka\Producer\ProduceMessage; | ||||||||||||||||||||||||||||||
| use function FriendsOfHyperf\Support\dispatch; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Dispatch Kafka message | ||||||||||||||||||||||||||||||
| dispatch($kafkaMessage) | ||||||||||||||||||||||||||||||
| ->setPool('default'); | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### CallQueuedClosure | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The `CallQueuedClosure` class allows you to execute closures as async queue jobs: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||
| use FriendsOfHyperf\Support\CallQueuedClosure; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Create a closure job | ||||||||||||||||||||||||||||||
| $job = CallQueuedClosure::create(function () { | ||||||||||||||||||||||||||||||
| // Your job logic | ||||||||||||||||||||||||||||||
| return 'Job completed!'; | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Configure max attempts | ||||||||||||||||||||||||||||||
| $job->setMaxAttempts(3); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // The job can be pushed to queue manually or via dispatch() | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### Pending Dispatch Classes | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| #### PendingAsyncQueueDispatch | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Fluent API for async queue job dispatch: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||
| use FriendsOfHyperf\Support\Bus\PendingAsyncQueueDispatch; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| $pending = new PendingAsyncQueueDispatch($job); | ||||||||||||||||||||||||||||||
| $pending | ||||||||||||||||||||||||||||||
| ->onConnection('default') | ||||||||||||||||||||||||||||||
| ->delay(30) | ||||||||||||||||||||||||||||||
| ->when($condition, function ($dispatch) { | ||||||||||||||||||||||||||||||
| $dispatch->onConnection('special'); | ||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||
| ->unless($otherCondition, function ($dispatch) { | ||||||||||||||||||||||||||||||
| $dispatch->delay(60); | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| // Job is dispatched when object is destroyed | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
Comment on lines
+102
to
+120
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 文档与实现不一致:方法名错误。 示例中使用了 应用此修改以纠正方法名: $pending = new PendingAsyncQueueDispatch($job);
$pending
- ->onConnection('default')
+ ->onPool('default')
->delay(30)
->when($condition, function ($dispatch) {
- $dispatch->onConnection('special');
+ $dispatch->onPool('special');
})
->unless($otherCondition, function ($dispatch) {
$dispatch->delay(60);
});🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| #### PendingAmqpProducerMessageDispatch | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Fluent API for AMQP message dispatch: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||
| use FriendsOfHyperf\Support\Bus\PendingAmqpProducerMessageDispatch; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| $pending = new PendingAmqpProducerMessageDispatch($message); | ||||||||||||||||||||||||||||||
| $pending | ||||||||||||||||||||||||||||||
| ->setPool('default') | ||||||||||||||||||||||||||||||
| ->setExchange('my.exchange') | ||||||||||||||||||||||||||||||
| ->setRoutingKey('my.routing.key') | ||||||||||||||||||||||||||||||
| ->setTimeout(5) | ||||||||||||||||||||||||||||||
| ->setConfirm(true); | ||||||||||||||||||||||||||||||
| // Message is sent when object is destroyed | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| #### PendingKafkaProducerMessageDispatch | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Fluent API for Kafka message dispatch: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||
| use FriendsOfHyperf\Support\Bus\PendingKafkaProducerMessageDispatch; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| $pending = new PendingKafkaProducerMessageDispatch($message); | ||||||||||||||||||||||||||||||
| $pending->setPool('default'); | ||||||||||||||||||||||||||||||
| // Message is sent when object is destroyed | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### Conditional Execution | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| All pending dispatch classes support conditional execution: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||
| use function FriendsOfHyperf\Support\dispatch; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| dispatch($job) | ||||||||||||||||||||||||||||||
| ->when($shouldUseHighPriority, function ($dispatch) { | ||||||||||||||||||||||||||||||
| $dispatch->onConnection('high-priority'); | ||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||
| ->unless($isTestMode, function ($dispatch) { | ||||||||||||||||||||||||||||||
| $dispatch->delay(10); | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
Comment on lines
+151
to
+165
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 文档与实现不一致:方法名错误。 条件执行示例中使用了 应用此修改: dispatch($job)
->when($shouldUseHighPriority, function ($dispatch) {
- $dispatch->onConnection('high-priority');
+ $dispatch->onPool('high-priority');
})
->unless($isTestMode, function ($dispatch) {
$dispatch->delay(10);
});🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## API Reference | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### dispatch($job) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Creates a pending dispatch instance based on the job type: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - `Closure` → `PendingAsyncQueueDispatch` with `CallQueuedClosure` | ||||||||||||||||||||||||||||||
| - `ProducerMessageInterface` → `PendingAmqpProducerMessageDispatch` | ||||||||||||||||||||||||||||||
| - `ProduceMessage` → `PendingKafkaProducerMessageDispatch` | ||||||||||||||||||||||||||||||
| - Other objects → `PendingAsyncQueueDispatch` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### PendingAsyncQueueDispatch Methods | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - `onConnection(string $connection): static` - Set queue connection | ||||||||||||||||||||||||||||||
| - `delay(int $delay): static` - Delay job execution (seconds) | ||||||||||||||||||||||||||||||
| - `setMaxAttempts(int $attempts): static` - Set max retry attempts | ||||||||||||||||||||||||||||||
| - `when(mixed $condition, callable $callback): static` - Conditional execution | ||||||||||||||||||||||||||||||
| - `unless(mixed $condition, callable $callback): static` - Inverse conditional execution | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
Comment on lines
+178
to
+185
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. API 文档错误:方法名不匹配。 第 180 行将方法文档化为 应用此修改: ### PendingAsyncQueueDispatch Methods
-- `onConnection(string $connection): static` - Set queue connection
+- `onPool(string $pool): static` - Set queue pool
- `delay(int $delay): static` - Delay job execution (seconds)
- `setMaxAttempts(int $attempts): static` - Set max retry attempts📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
| ### PendingAmqpProducerMessageDispatch Methods | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - `setPool(string $pool): static` - Set AMQP pool name | ||||||||||||||||||||||||||||||
| - `setExchange(string $exchange): static` - Set exchange name | ||||||||||||||||||||||||||||||
| - `setRoutingKey(array|string $routingKey): static` - Set routing key(s) | ||||||||||||||||||||||||||||||
| - `setTimeout(int $timeout): static` - Set timeout (seconds) | ||||||||||||||||||||||||||||||
| - `setConfirm(bool $confirm): static` - Enable/disable confirm mode | ||||||||||||||||||||||||||||||
| - `when(mixed $condition, callable $callback): static` - Conditional execution | ||||||||||||||||||||||||||||||
| - `unless(mixed $condition, callable $callback): static` - Inverse conditional execution | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
Comment on lines
+186
to
+195
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain验证 AMQP 方法的可用性。 文档记录了 请确认:
运行以下脚本验证方法签名: 🏁 Script executed: #!/bin/bash
# 描述:验证 PendingAmqpProducerMessageDispatch 类的方法签名
# 查找类定义及其所有公共方法
ast-grep --pattern $'class PendingAmqpProducerMessageDispatch {
$$$
}'
# 搜索 setExchange 方法
rg -nP --type=php -C3 'function\s+setExchange\s*\('
# 搜索 setRoutingKey 方法
rg -nP --type=php -C3 'function\s+setRoutingKey\s*\('
# 搜索 setPool 或 onPool 方法
rg -nP --type=php -C3 'function\s+(setPool|onPool)\s*\(' -g '*PendingAmqpProducerMessageDispatch.php'Length of output: 8260 更新 README 文档中的池配置方法名称。 验证确认 需要修正:
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
| ### PendingKafkaProducerMessageDispatch Methods | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - `setPool(string $pool): static` - Set Kafka pool name | ||||||||||||||||||||||||||||||
| - `when(mixed $condition, callable $callback): static` - Conditional execution | ||||||||||||||||||||||||||||||
| - `unless(mixed $condition, callable $callback): static` - Inverse conditional execution | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### CallQueuedClosure | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - `create(Closure $closure): static` - Create a new closure job | ||||||||||||||||||||||||||||||
| - `setMaxAttempts(int $attempts): void` - Set max retry attempts | ||||||||||||||||||||||||||||||
| - `handle(): mixed` - Execute the closure (called by queue worker) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Architecture Notes | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| As of v3.1.73, this package includes the core async queue closure functionality: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - Previously in `friendsofhyperf/async-queue-closure-job` | ||||||||||||||||||||||||||||||
| - Moved here to eliminate circular dependencies | ||||||||||||||||||||||||||||||
| - The `async-queue-closure-job` package now depends on this package | ||||||||||||||||||||||||||||||
| - All functionality remains backward compatible | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Contact | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - [Twitter](https://twitter.com/huangdijia) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
文档与实现不一致:方法名错误。
示例代码中使用了
onConnection()方法(第 44 行),但根据测试文件tests/Support/DispatchTest.php的实际实现,PendingAsyncQueueDispatch使用的是onPool()方法,而非onConnection()。测试文件中的证据:
$pending->onPool('custom-pool')->onPool('high-priority')->onPool('test-pool')应用此修改以纠正方法名:
dispatch(function () { // Your job logic here }) - ->onConnection('high-priority') + ->onPool('high-priority') ->delay(60) // Execute after 60 seconds ->setMaxAttempts(5);📝 Committable suggestion
🤖 Prompt for AI Agents