Skip to content

Commit

Permalink
Support InitMethod attribute in Workflow constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
roxblnfk committed Jan 20, 2025
1 parent 59fb515 commit d9fec58
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 16 deletions.
18 changes: 11 additions & 7 deletions src/Internal/Declaration/Dispatcher/AutowiredPayloads.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,16 @@
*/
class AutowiredPayloads extends Dispatcher
{
public function dispatchValues(object $ctx, ValuesInterface $values): mixed
public function dispatch(object $ctx, array $arguments): mixed
{
try {
return parent::dispatch($ctx, $arguments);
} catch (\TypeError $e) {
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
}
}

public function resolveArguments(ValuesInterface $values): array
{
$arguments = [];
try {
Expand All @@ -30,11 +39,6 @@ public function dispatchValues(object $ctx, ValuesInterface $values): mixed
} catch (\Throwable $e) {
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
}

try {
return parent::dispatch($ctx, $arguments);
} catch (\TypeError $e) {
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
}
return $arguments;
}
}
11 changes: 10 additions & 1 deletion src/Internal/Declaration/MethodHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,17 @@ public function __construct(
$this->dispatcher = new AutowiredPayloads($reflection);
}

/**
* Resolve arguments for the method.
*/
public function resolveArguments(ValuesInterface $values): array
{
return $this->dispatcher->resolveArguments($values);
}

public function __invoke(ValuesInterface $values): mixed
{
return $this->dispatcher->dispatchValues($this->instance, $values);
$arguments = $this->resolveArguments($values);
return $this->dispatcher->dispatch($this->instance, $arguments);
}
}
19 changes: 17 additions & 2 deletions src/Internal/Declaration/WorkflowInstance.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Temporal\Internal\Declaration\Prototype\WorkflowPrototype;
use Temporal\Internal\Declaration\WorkflowInstance\SignalQueue;
use Temporal\Internal\Interceptor;
use Temporal\Workflow\InitMethod;

/**
* @psalm-type QueryHandler = \Closure(QueryInput): mixed
Expand All @@ -29,6 +30,8 @@
* @psalm-type UpdateExecutor = \Closure(UpdateInput, callable(ValuesInterface): mixed, Deferred): PromiseInterface
* @psalm-type ValidateUpdateExecutor = \Closure(UpdateInput, callable(ValuesInterface): mixed): mixed
* @psalm-type UpdateValidator = \Closure(UpdateInput, UpdateHandler): void
*
* @internal
*/
final class WorkflowInstance extends Instance implements WorkflowInstanceInterface
{
Expand Down Expand Up @@ -139,11 +142,23 @@ public function setUpdateValidator(\Closure $validator): self
/**
* Trigger constructor in Process context.
*/
public function initConstructor(): void
public function init(array $arguments = []): void
{
if (\method_exists($this->context, '__construct')) {
if (!\method_exists($this->context, '__construct')) {
return;
}

if ($arguments === []) {
$this->context->__construct();
return;
}

// Check InitMethod attribute
$reflection = new \ReflectionMethod($this->context, '__construct');
$attributes = $reflection->getAttributes(InitMethod::class);
$attributes === []
? $this->context->__construct()
: $this->context->__construct(...$arguments);
}

public function getSignalQueue(): SignalQueue
Expand Down
7 changes: 6 additions & 1 deletion src/Internal/Declaration/WorkflowInstanceInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@
use Temporal\Interceptor\WorkflowInbound\UpdateInput;
use Temporal\Internal\Declaration\Prototype\WorkflowPrototype;

/**
* @internal
*/
interface WorkflowInstanceInterface extends InstanceInterface
{
/**
* Trigger constructor in Process context.
* If the constructor is tagged with {@see \Temporal\Workflow\InitMethod} attribute,
* it will be executed with the {@see \Temporal\Workflow\WorkflowMethod} arguments.
*/
public function initConstructor(): void;
public function init(array $arguments = []): void;

/**
* @param non-empty-string $name
Expand Down
14 changes: 11 additions & 3 deletions src/Internal/Workflow/Process/Process.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use JetBrains\PhpStorm\Pure;
use React\Promise\Deferred;
use React\Promise\PromiseInterface;
use Temporal\DataConverter\EncodedValues;
use Temporal\DataConverter\ValuesInterface;
use Temporal\Exception\DestructMemorizedInstanceException;
use Temporal\Exception\Failure\CanceledFailure;
Expand Down Expand Up @@ -176,12 +177,19 @@ function (\Throwable $e): void {
/**
* @param MethodHandler|\Closure(ValuesInterface): mixed $handler
*/
public function start(MethodHandler|\Closure $handler, ?ValuesInterface $values, bool $deferred): void
public function start(MethodHandler|\Closure $handler, ValuesInterface $values, bool $deferred): void
{
try {
$this->makeCurrent();
$this->context->getWorkflowInstance()->initConstructor();
parent::start($handler, $values, $deferred);

// Prepare typed input
\assert($handler instanceof MethodHandler);
$arguments = $handler->resolveArguments($values ?? EncodedValues::empty());

// Manage init method
$this->context->getWorkflowInstance()->init($arguments);

parent::start($handler, EncodedValues::fromValues($arguments), $deferred);
} catch (\Throwable $e) {
$this->complete($e);
} finally {
Expand Down
4 changes: 2 additions & 2 deletions src/Internal/Workflow/Process/Scope.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public function getContext(): WorkflowContext
/**
* @param MethodHandler|\Closure(ValuesInterface): mixed $handler
*/
public function start(MethodHandler|\Closure $handler, ?ValuesInterface $values, bool $deferred): void
public function start(MethodHandler|\Closure $handler, ValuesInterface $values, bool $deferred): void
{
// Create a coroutine generator
$this->coroutine = DeferredGenerator::fromHandler($handler, $values ?? EncodedValues::empty())
Expand Down Expand Up @@ -234,7 +234,7 @@ public function cancel(?\Throwable $reason = null): void
public function startScope(callable $handler, bool $detached, ?string $layer = null): CancellationScopeInterface
{
$scope = $this->createScope($detached, $layer);
$scope->start($handler(...), null, false);
$scope->start($handler(...), EncodedValues::empty(), false);

return $scope;
}
Expand Down

0 comments on commit d9fec58

Please sign in to comment.