temporal-php / support
简化使用 Temporal PHP SDK 的辅助工具
Requires
- php: >=8.1
- temporal/sdk: ^2.8
Requires (Dev)
- buggregator/trap: ^1.4
- dereuromark/composer-prefer-lowest: ^0.1.10
- pestphp/pest: ^2.34
- pestphp/pest-plugin-arch: ^2.7
- phpunit/phpunit: ^10.5
- vimeo/psalm: ^5.23
Suggests
- buggregator/trap: For better debugging and protobuf messages dumping
README
Temporal PHP 支持
使用 Temporal 提高开发体验该包包含属性、辅助工具、工厂、接口、拦截器等,以增强使用 Temporal PHP SDK 时的开发者体验。
安装
要安装该包到您的 PHP 应用程序中,请使用 Composer 将其添加为项目的一个开发依赖项
composer require temporal-php/support
使用
工厂
该包提供工厂以更方便的方式创建 Activity 和 Worker 存根。使用这些工厂,代码更少,因为所有嵌套选项都移动到单个方法参数中。
使用 \Temporal\Support\Factory\ActivityStub
工厂创建一个 Activity 存根
use \Temporal\Support\Factory\ActivityStub; #[\Temporal\Workflow\WorkflowInterface] class HelloWorkflow { #[\Temporal\Workflow\WorkflowMethod] public function run(string $user) { yield ActivityStub::activity( class: UserService::class, startToCloseTimeout: 60, retryAttempts: 5, )->getContactEmail($user)->then( fn (string $email) => ActivityStub::activity( class: HelloService::class, startToCloseTimeout: '10 minutes', retryAttempts: 5, )->sendHelloEmail($user, $email), ); } }
使用 \Temporal\Support\Factory\WorkflowStub
工厂在客户端范围内创建一个 Workflow 存根
use \Temporal\Support\Factory\WorkflowStub; /** * @var \Temporal\Client\WorkflowClient $client */ $stub = WorkflowStub::workflow($client, HelloWorkflow::class, executionTimeout: '1 day'); $run = $client->start($stub, 'User'); // ...
或者在流程范围内创建一个子流程存根
use \Temporal\Support\Factory\WorkflowStub; #[\Temporal\Workflow\WorkflowInterface] class RegisterWorkflow { #[\Temporal\Workflow\WorkflowMethod] public function run(string $user) { yield \Temporal\Promise::all([ WorkflowStub::childWorkflow(GreetingWorkflow::class, executionTimeout: '1 hour')->greet($user), WorkflowStub::childWorkflow(SubscribeNewsWorkflow::class, executionTimeout: '10 minutes')->subscribe($user), WorkflowStub::childWorkflow(PrepareUserSpaceWorkflow::class, executionTimeout: '1 hour')->handle($user), ])->then( // Suppress failures onRejected: static fn () => null, ); // ... } }
属性
属性可以用于 Workflow 或 Activity 定义,以设置默认存根选项。
#[\Temporal\Support\Attribute\TaskQueue('my-task-queue')] #[\Temporal\Support\Attribute\RetryPolicy(attempts: 5)] #[WorkflowInterface] interface HelloWorkflow { #[WorkflowMethod] public function greet(string $name); } $stub = \Temporal\Support\Factory\WorkflowStub::workflow($client, HelloWorkflow::class); // TaskQueue is now set to 'my-task-queue' and RetryPolicy to 5 attempts $stub->greet('User'); // You can override the default options $stub = \Temporal\Support\Factory\WorkflowStub::workflow( $client, HelloWorkflow::class, taskQueue: 'another-task-queue', retryAttempts: 1, )->greet('User');
注意
只有当您使用此包中的 Activity 和 Worker 工厂时,属性才会工作。
警告
在工厂中使用的定义上使用属性。因此,如果您将接口和实现分开,则将属性应用于接口。
VirtualPromise 接口
每次我们在 Workflow 中使用 yield
等待操作完成时,实际上都会产生一个 Promise。在这个点上,IDE 和静态分析器通常会迷失在类型定义中,我们因为这个问题而遇到困难和不便。然而,如果 Promise 接口有 @yield
注解,我们就可以向 IDE 解释我们期望从协程中返回什么类型的值。然而,由于 ReactPHP 尚未计划 将 @yield
注解添加到他们的 Promise 中(Temporal PHP 使用 ReactPHP Promise),我们建议使用我们的类型解决方案 - VirtualPromise
。
use Temporal\Support\VirtualPromise; #[\Temporal\Activity\ActivityInterface] class HelloService { /** * @param non-empty-string $name * * @return VirtualPromise<non-empty-string> */ public function greet(string $name) { // ... } } #[\Temporal\Workflow\WorkflowInterface] class WorkflowClass { #[\Temporal\Workflow\WorkflowMethod] public function run(string $name) { $activity = \Temporal\Support\Factory\ActivityStub::activity(HelloService::class); // IDE will know that $name is a non-empty-string $name = yield $activity->greet($name); // ... } }
警告
不要自己实现 VirtualPromise
接口,只需将其用作类型提示。
注意
PHPStorm 和 Psalm 可以处理 @yield
注解,但 PHPStan 还不能(问题)。
贡献
我们相信社区驱动型开发的力量。以下是您可以如何做出贡献的方法