diff --git a/psalm-baseline.xml b/psalm-baseline.xml index d2e6b6a4..1c68e783 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -342,34 +342,11 @@ getDetails()]]> - - &RepeatedField]]> - - - &RepeatedField]]> - - - &RepeatedField]]> - - - status->getDetails()]]> - - - - - - - - - - - - @@ -827,9 +804,6 @@ - - - getDetails()]]> getSummary()]]> @@ -997,13 +971,6 @@ getName()]]> - - - |null]]> - - - - @@ -1513,16 +1480,9 @@ - - newActivityStub($class, $options)]]> - registerQuery($queryType, $handler, $description)]]> - registerSignal($name, $handler, $description)]]> - - - - - - + + + diff --git a/src/Activity.php b/src/Activity.php index fe5886e6..9b9d069d 100644 --- a/src/Activity.php +++ b/src/Activity.php @@ -17,13 +17,25 @@ use Temporal\DataConverter\Type; use Temporal\DataConverter\ValuesInterface; use Temporal\Exception\OutOfContextException; +use Temporal\Internal\Activity\ActivityContext; use Temporal\Internal\Support\Facade; -/** - * @template-extends Facade - */ final class Activity extends Facade { + /** + * Get the current Activity context. + * @throws OutOfContextException + */ + public static function getCurrentContext(): ActivityContextInterface + { + $ctx = parent::getCurrentContext(); + /** @var ActivityContext $ctx */ + $ctx::class === ActivityContext::class or throw new OutOfContextException( + 'The Activity facade can only be used in the context of an activity execution.', + ); + return $ctx; + } + /** * Returns information about current activity execution. * @@ -31,7 +43,6 @@ final class Activity extends Facade */ public static function getInfo(): ActivityInfo { - /** @var ActivityContextInterface $context */ $context = self::getCurrentContext(); return $context->getInfo(); @@ -57,7 +68,6 @@ public static function getInfo(): ActivityInfo */ public static function getInput(): ValuesInterface { - /** @var ActivityContextInterface $context */ $context = self::getCurrentContext(); return $context->getInput(); @@ -72,7 +82,6 @@ public static function getInput(): ValuesInterface */ public static function hasHeartbeatDetails(): bool { - /** @var ActivityContextInterface $context */ $context = self::getCurrentContext(); return $context->hasHeartbeatDetails(); @@ -88,7 +97,6 @@ public static function hasHeartbeatDetails(): bool */ public static function getHeartbeatDetails($type = null): mixed { - /** @var ActivityContextInterface $context */ $context = self::getCurrentContext(); return $context->getLastHeartbeatDetails($type); @@ -101,7 +109,6 @@ public static function getHeartbeatDetails($type = null): mixed */ public static function getCancellationDetails(): ?ActivityCancellationDetails { - /** @var ActivityContextInterface $context */ $context = self::getCurrentContext(); return $context->getCancellationDetails(); @@ -118,7 +125,6 @@ public static function getCancellationDetails(): ?ActivityCancellationDetails */ public static function doNotCompleteOnReturn(): void { - /** @var ActivityContextInterface $context */ $context = self::getCurrentContext(); $context->doNotCompleteOnReturn(); @@ -150,7 +156,6 @@ public static function doNotCompleteOnReturn(): void */ public static function heartbeat($details): void { - /** @var ActivityContextInterface $context */ $context = self::getCurrentContext(); $context->heartbeat($details); @@ -161,7 +166,6 @@ public static function heartbeat($details): void */ public static function getInstance(): object { - /** @var ActivityContextInterface $context */ $context = self::getCurrentContext(); return $context->getInstance(); diff --git a/src/Internal/Support/Facade.php b/src/Internal/Support/Facade.php index dea6ef85..bf13a67e 100644 --- a/src/Internal/Support/Facade.php +++ b/src/Internal/Support/Facade.php @@ -13,9 +13,6 @@ use Temporal\Exception\OutOfContextException; -/** - * @template T of object - */ abstract class Facade { /** @@ -26,9 +23,6 @@ abstract class Facade 'from the currently running process' ; - /** - * @var object|null - */ private static ?object $ctx = null; /** @@ -40,7 +34,6 @@ private function __construct() } /** - * @param object|null $ctx * @internal */ public static function setCurrentContext(?object $ctx): void @@ -49,7 +42,6 @@ public static function setCurrentContext(?object $ctx): void } /** - * @return object * @throws OutOfContextException */ public static function getCurrentContext(): object diff --git a/src/Internal/Transport/Router/InvokeActivity.php b/src/Internal/Transport/Router/InvokeActivity.php index 1ec3c4e8..ffa1f537 100644 --- a/src/Internal/Transport/Router/InvokeActivity.php +++ b/src/Internal/Transport/Router/InvokeActivity.php @@ -101,6 +101,7 @@ static function (ActivityInput $input) use ($handler, $context): mixed { 'handleActivityInbound', )(new ActivityInput($context->getInput(), $context->getHeader())); + /** @var ActivityContext $context */ $context = Activity::getCurrentContext(); if ($context->isDoNotCompleteOnReturn()) { $resolver->reject(DoNotCompleteOnResultException::create()); diff --git a/src/Internal/Transport/Router/StartWorkflow.php b/src/Internal/Transport/Router/StartWorkflow.php index d0b9dd50..97edf8b2 100644 --- a/src/Internal/Transport/Router/StartWorkflow.php +++ b/src/Internal/Transport/Router/StartWorkflow.php @@ -25,7 +25,6 @@ use Temporal\Internal\Workflow\WorkflowContext; use Temporal\Worker\FeatureFlags; use Temporal\Worker\Transport\Command\ServerRequestInterface; -use Temporal\Workflow; use Temporal\Workflow\WorkflowInfo; final class StartWorkflow extends Route @@ -90,7 +89,6 @@ public function handle(ServerRequestInterface $request, array $headers, Deferred ); $runId = $request->getID(); - Workflow::setCurrentContext($context); $process = new Process($this->services, $runId, $instance); $this->services->running->add($process); $resolver->resolve(EncodedValues::fromValues([null])); diff --git a/src/Internal/Workflow/ActivityStub.php b/src/Internal/Workflow/ActivityStub.php index 980455f0..4ecc930a 100644 --- a/src/Internal/Workflow/ActivityStub.php +++ b/src/Internal/Workflow/ActivityStub.php @@ -70,9 +70,6 @@ public function execute( protected function request(RequestInterface $request): PromiseInterface { - /** @var Workflow\WorkflowContextInterface $context */ - $context = Workflow::getCurrentContext(); - - return $context->request($request); + return Workflow::getCurrentContext()->request($request); } } diff --git a/src/Internal/Workflow/ChildWorkflowStub.php b/src/Internal/Workflow/ChildWorkflowStub.php index 2aa21b06..2bc9fb5b 100644 --- a/src/Internal/Workflow/ChildWorkflowStub.php +++ b/src/Internal/Workflow/ChildWorkflowStub.php @@ -125,10 +125,7 @@ function (WorkflowExecution $execution) use ($name, $args) { protected function request(RequestInterface $request, bool $cancellable = true): PromiseInterface { - /** @var Workflow\WorkflowContextInterface $context */ - $context = Workflow::getCurrentContext(); - - return $context->request($request, cancellable: $cancellable); + return Workflow::getCurrentContext()->request($request, cancellable: $cancellable); } private function getOptionArray(): array diff --git a/src/Internal/Workflow/ExternalWorkflowStub.php b/src/Internal/Workflow/ExternalWorkflowStub.php index 9f047fb7..75b4ff37 100644 --- a/src/Internal/Workflow/ExternalWorkflowStub.php +++ b/src/Internal/Workflow/ExternalWorkflowStub.php @@ -77,7 +77,6 @@ public function cancel(): PromiseInterface private function request(RequestInterface $request): PromiseInterface { // todo intercept - /** @var Workflow\WorkflowContextInterface $context */ $context = Workflow::getCurrentContext(); return $context->request($request); diff --git a/src/Workflow.php b/src/Workflow.php index 1772f59a..06bbb4be 100644 --- a/src/Workflow.php +++ b/src/Workflow.php @@ -23,7 +23,6 @@ use Temporal\Exception\Failure\CanceledFailure; use Temporal\Exception\OutOfContextException; use Temporal\Internal\Support\Facade; -use Temporal\Internal\Workflow\ScopeContext; use Temporal\Workflow\ActivityStubInterface; use Temporal\Workflow\CancellationScopeInterface; use Temporal\Workflow\ChildWorkflowOptions; @@ -45,18 +44,27 @@ * * This is main class you can use in your workflow code. * - * @method static ScopeContext getCurrentContext() Get current workflow context. - * * @psalm-import-type TypeEnum from Type * @psalm-import-type DateIntervalValue from DateInterval * @see DateInterval - * - * @template-extends Facade */ final class Workflow extends Facade { public const DEFAULT_VERSION = -1; + /** + * Get the current Workflow context. + * @throws OutOfContextException + */ + public static function getCurrentContext(): WorkflowContextInterface + { + $ctx = parent::getCurrentContext(); + $ctx instanceof WorkflowContextInterface or throw new OutOfContextException( + 'The Workflow facade can be used only inside workflow code.', + ); + return $ctx; + } + /** * Returns current datetime. * @@ -192,7 +200,9 @@ public static function getInput(): ValuesInterface */ public static function async(callable $task): CancellationScopeInterface { - return self::getCurrentContext()->async($task); + $ctx = self::getCurrentContext(); + \assert($ctx instanceof ScopedContextInterface); + return $ctx->async($task); } /** @@ -244,7 +254,9 @@ public static function async(callable $task): CancellationScopeInterface */ public static function asyncDetached(callable $task): CancellationScopeInterface { - return self::getCurrentContext()->asyncDetached($task); + $ctx = self::getCurrentContext(); + \assert($ctx instanceof ScopedContextInterface); + return $ctx->asyncDetached($task); } /** @@ -352,7 +364,9 @@ public static function registerQuery( callable $handler, string $description = '', ): ScopedContextInterface { - return self::getCurrentContext()->registerQuery($queryType, $handler, $description); + $ctx = self::getCurrentContext(); + \assert($ctx instanceof ScopedContextInterface); + return $ctx->registerQuery($queryType, $handler, $description); } /** @@ -372,7 +386,9 @@ public static function registerQuery( */ public static function registerSignal(string $name, callable $handler, string $description = ''): ScopedContextInterface { - return self::getCurrentContext()->registerSignal($name, $handler, $description); + $ctx = self::getCurrentContext(); + \assert($ctx instanceof ScopedContextInterface); + return $ctx->registerSignal($name, $handler, $description); } /** @@ -491,7 +507,9 @@ public static function registerUpdate( ?callable $validator = null, string $description = '', ): ScopedContextInterface { - return self::getCurrentContext()->registerUpdate($name, $handler, $validator, $description); + $ctx = self::getCurrentContext(); + \assert($ctx instanceof ScopedContextInterface); + return $ctx->registerUpdate($name, $handler, $validator, $description); } /** @@ -995,7 +1013,6 @@ public static function getStackTrace(): string */ public static function allHandlersFinished(): bool { - /** @var ScopedContextInterface $context */ $context = self::getCurrentContext(); return $context->allHandlersFinished(); @@ -1081,7 +1098,6 @@ public static function upsertTypedSearchAttributes(SearchAttributeUpdate ...$upd */ public static function uuid(): PromiseInterface { - /** @var ScopedContextInterface $context */ $context = self::getCurrentContext(); return $context->uuid(); @@ -1094,7 +1110,6 @@ public static function uuid(): PromiseInterface */ public static function uuid4(): PromiseInterface { - /** @var ScopedContextInterface $context */ $context = self::getCurrentContext(); return $context->uuid4(); @@ -1111,7 +1126,6 @@ public static function uuid4(): PromiseInterface */ public static function uuid7(?\DateTimeInterface $dateTime = null): PromiseInterface { - /** @var ScopedContextInterface $context */ $context = self::getCurrentContext(); return $context->uuid7($dateTime); diff --git a/src/Workflow/WorkflowContextInterface.php b/src/Workflow/WorkflowContextInterface.php index e0dd1c47..945eda1c 100644 --- a/src/Workflow/WorkflowContextInterface.php +++ b/src/Workflow/WorkflowContextInterface.php @@ -440,4 +440,9 @@ public function uuid7(?\DateTimeInterface $dateTime = null): PromiseInterface; * Logs in replay mode are omitted unless {@see WorkerOptions::$enableLoggingInReplay} is set to true. */ public function getLogger(): LoggerInterface; + + /** + * Get the currently running Workflow instance. + */ + public function getInstance(): object; }