Skip to content

Commit

Permalink
Merge pull request #250 from smelesh/fix-wf-inheritance
Browse files Browse the repository at this point in the history
Send signal to workflow via parent interface
  • Loading branch information
roxblnfk authored Oct 28, 2022
2 parents 8e5e432 + e6bf5db commit 702863b
Show file tree
Hide file tree
Showing 20 changed files with 272 additions and 40 deletions.
9 changes: 8 additions & 1 deletion src/Client/WorkflowClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use Doctrine\Common\Annotations\Reader;
use Spiral\Attributes\AnnotationReader;
use Spiral\Attributes\AttributeReader;
use Spiral\Attributes\Composite\Composite;
use Spiral\Attributes\Composite\SelectiveReader;
use Spiral\Attributes\ReaderInterface;
use Temporal\Client\GRPC\ServiceClientInterface;
Expand Down Expand Up @@ -106,6 +105,10 @@ public function getServiceClient(): ServiceClientInterface
*/
public function start($workflow, ...$args): WorkflowRunInterface
{
if ($workflow instanceof WorkflowProxy && !$workflow->hasHandler()) {
throw new InvalidArgumentException('Unable to start workflow without workflow handler');
}

$workflowStub = WorkflowStubConverter::fromWorkflow($workflow);

$returnType = null;
Expand Down Expand Up @@ -147,6 +150,10 @@ public function startWithSignal(
array $signalArgs = [],
array $startArgs = []
): WorkflowRunInterface {
if ($workflow instanceof WorkflowProxy && !$workflow->hasHandler()) {
throw new InvalidArgumentException('Unable to start workflow without workflow handler');
}

$workflowStub = WorkflowStubConverter::fromWorkflow($workflow);

$returnType = null;
Expand Down
2 changes: 1 addition & 1 deletion src/DataConverter/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public static function fromReflectionType(\ReflectionType $type): self
}

/**
* @param string|\ReflectionClass|\ReflectionType|Type $type
* @param string|\ReflectionClass|\ReflectionType|Type|ReturnType $type
* @return Type
*/
public static function create($type): Type
Expand Down
16 changes: 16 additions & 0 deletions src/Exception/InstantiationException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

/**
* This file is part of Temporal package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Temporal\Exception;

class InstantiationException extends TemporalException
{
}
11 changes: 10 additions & 1 deletion src/Internal/Client/WorkflowProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public function __construct(
*/
public function __call(string $method, array $args)
{
if ($method === $this->prototype->getHandler()->getName()) {
if ($method === $this->prototype->getHandler()?->getName()) {
// no timeout (use async mode to get it)
return $this->client->start($this, ...$args)->getResult($this->__getReturnType());
}
Expand Down Expand Up @@ -115,4 +115,13 @@ public function __getReturnType()
{
return $this->prototype->getReturnType();
}

/**
* @return bool
* @internal
*/
public function hasHandler(): bool
{
return $this->prototype->getHandler() !== null;
}
}
12 changes: 11 additions & 1 deletion src/Internal/Declaration/Instance.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Temporal\Internal\Declaration;

use Temporal\DataConverter\ValuesInterface;
use Temporal\Exception\InstantiationException;
use Temporal\Internal\Declaration\Dispatcher\AutowiredPayloads;
use Temporal\Internal\Declaration\Prototype\Prototype;

Expand All @@ -30,9 +31,18 @@ abstract class Instance implements InstanceInterface
*/
public function __construct(Prototype $prototype, ?object $context)
{
$handler = $prototype->getHandler();

if ($handler === null) {
throw new InstantiationException(\sprintf(
'Unable to instantiate "%s" without handler method',
$prototype->getID(),
));
}

$this->prototype = $prototype;
$this->context = $context;
$this->handler = $this->createHandler($prototype->getHandler());
$this->handler = $this->createHandler($handler);
}

/**
Expand Down
12 changes: 11 additions & 1 deletion src/Internal/Declaration/Instantiator/WorkflowInstantiator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Temporal\Internal\Declaration\Instantiator;

use Temporal\Exception\InstantiationException;
use Temporal\Internal\Declaration\Prototype\PrototypeInterface;
use Temporal\Internal\Declaration\Prototype\WorkflowPrototype;
use Temporal\Internal\Declaration\WorkflowInstance;
Expand All @@ -37,7 +38,16 @@ public function instantiate(PrototypeInterface $prototype): WorkflowInstance
*/
protected function getInstance(PrototypeInterface $prototype): ?object
{
$class = $prototype->getHandler()->getDeclaringClass();
$handler = $prototype->getHandler();

if ($handler === null) {
throw new InstantiationException(\sprintf(
'Unable to instantiate workflow "%s" without handler method',
$prototype->getID(),
));
}

$class = $handler->getDeclaringClass();

if ($class !== null) {
return $class->newInstanceWithoutConstructor();
Expand Down
11 changes: 11 additions & 0 deletions src/Internal/Declaration/Prototype/ActivityPrototype.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ public function __construct(ActivityInterface $interface, string $name, \Reflect
parent::__construct($name, $handler, $class);
}

/**
* @return \ReflectionMethod
*/
public function getHandler(): \ReflectionMethod
{
$handler = parent::getHandler();
assert($handler !== null);

return $handler;
}

/**
* @return MethodRetry|null
*/
Expand Down
14 changes: 7 additions & 7 deletions src/Internal/Declaration/Prototype/Prototype.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ abstract class Prototype implements PrototypeInterface
protected string $name;

/**
* @var \ReflectionMethod
* @var \ReflectionMethod|null
*/
protected \ReflectionMethod $handler;
protected ?\ReflectionMethod $handler;

/**
* @var \ReflectionClass
Expand All @@ -32,10 +32,10 @@ abstract class Prototype implements PrototypeInterface

/**
* @param string $name
* @param \ReflectionMethod $handler
* @param \ReflectionMethod|null $handler
* @param \ReflectionClass $class
*/
public function __construct(string $name, \ReflectionMethod $handler, \ReflectionClass $class)
public function __construct(string $name, ?\ReflectionMethod $handler, \ReflectionClass $class)
{
$this->handler = $handler;
$this->name = $name;
Expand Down Expand Up @@ -79,9 +79,9 @@ public function getClass(): \ReflectionClass
}

/**
* @return \ReflectionMethod
* @return \ReflectionMethod|null
*/
public function getHandler(): \ReflectionMethod
public function getHandler(): ?\ReflectionMethod
{
return $this->handler;
}
Expand All @@ -107,6 +107,6 @@ private static function matchMethod(PrototypeInterface $prototype, string $metho
{
$handler = $prototype->getHandler();

return $handler->getName() === $method;
return $handler?->getName() === $method;
}
}
4 changes: 2 additions & 2 deletions src/Internal/Declaration/Prototype/PrototypeInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function getClass(): \ReflectionClass;
/**
* Returns the reflection of the handler function.
*
* @return \ReflectionMethod
* @return \ReflectionMethod|null
*/
public function getHandler(): \ReflectionMethod;
public function getHandler(): ?\ReflectionMethod;
}
15 changes: 6 additions & 9 deletions src/Internal/Declaration/Reader/WorkflowReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,6 @@ class WorkflowReader extends Reader
'must contain #[%s] attribute'
;

/**
* @var string
*/
private const ERROR_HANDLER_NOT_FOUND =
'Can not find workflow handler, because class %s has no method marked with #[%s] attribute'
;

/**
* @var string
*/
Expand Down Expand Up @@ -81,8 +74,7 @@ public function fromClass(string $class): WorkflowPrototype

switch (\count($prototypes)) {
case 0:
$message = \sprintf(self::ERROR_HANDLER_NOT_FOUND, $graph, WorkflowMethod::class);
throw new \LogicException($message);
return $this->withSignalsAndQueries($graph, $this->getDefaultPrototype($graph));

case 1:
return $this->withSignalsAndQueries($graph, \reset($prototypes));
Expand Down Expand Up @@ -293,6 +285,11 @@ private function getPrototype(ClassNode $graph, \ReflectionMethod $handler): ?Wo
return $prototype;
}

private function getDefaultPrototype(ClassNode $graph): WorkflowPrototype
{
return new WorkflowPrototype($graph->getReflection()->getName(), null, $graph->getReflection());
}

/**
* @param \ReflectionMethod $handler
* @param \ReflectionMethod $ctx
Expand Down
4 changes: 2 additions & 2 deletions src/Internal/Workflow/ChildWorkflowProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public function __call(string $method, array $args): PromiseInterface
if (!$this->isRunning()) {
$handler = $this->workflow->getHandler();

if ($handler->getName() !== $method) {
if ($method !== $handler?->getName()) {
throw new \BadMethodCallException(
\sprintf(self::ERROR_UNDEFINED_WORKFLOW_METHOD, $this->class, $method)
);
Expand Down Expand Up @@ -148,7 +148,7 @@ private function resolveReturnType(WorkflowPrototype $prototype): ?Type

$handler = $prototype->getHandler();

return Type::create($handler->getReturnType());
return Type::create($handler?->getReturnType());
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Internal/Workflow/ContinueAsNewProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public function __call(string $method, array $args)

$handler = $this->workflow->getHandler();

if ($method !== $handler->getName()) {
if ($method !== $handler?->getName()) {
throw new \BadMethodCallException(
\sprintf(self::ERROR_UNDEFINED_WORKFLOW_METHOD, $this->class, $method)
);
Expand Down
31 changes: 31 additions & 0 deletions tests/Fixtures/src/Workflow/SignalWorkflowWithInheritanceImpl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/**
* This file is part of Temporal package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Temporal\Tests\Workflow;

use Temporal\Workflow;

class SignalWorkflowWithInheritanceImpl implements SignalledWorkflowWithInheritance
{
private array $values = [];

public function addValue(string $value)
{
$this->values[] = $value;
}

public function run(int $count)
{
yield Workflow::await(fn() => \count($this->values) === $count);

return $this->values;
}
}
22 changes: 22 additions & 0 deletions tests/Fixtures/src/Workflow/SignalledWorkflowReusable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

/**
* This file is part of Temporal package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Temporal\Tests\Workflow;

use Temporal\Workflow\SignalMethod;
use Temporal\Workflow\WorkflowInterface;

#[WorkflowInterface]
interface SignalledWorkflowReusable
{
#[SignalMethod]
public function addValue(string $value);
}
22 changes: 22 additions & 0 deletions tests/Fixtures/src/Workflow/SignalledWorkflowWithInheritance.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

/**
* This file is part of Temporal package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Temporal\Tests\Workflow;

use Temporal\Workflow\WorkflowInterface;
use Temporal\Workflow\WorkflowMethod;

#[WorkflowInterface]
interface SignalledWorkflowWithInheritance extends SignalledWorkflowReusable
{
#[WorkflowMethod(name: 'SignalledWorkflowWithInheritance')]
public function run(int $count);
}
Loading

0 comments on commit 702863b

Please sign in to comment.