Skip to content

Commit 69858a0

Browse files
authored
Merge pull request #662: Friendly context outbound exception
2 parents dfa5fb0 + c94a7c0 commit 69858a0

File tree

10 files changed

+54
-87
lines changed

10 files changed

+54
-87
lines changed

psalm-baseline.xml

Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -342,34 +342,11 @@
342342
<InvalidArgument>
343343
<code><![CDATA[$message->getDetails()]]></code>
344344
</InvalidArgument>
345-
<MismatchingDocblockParamType>
346-
<code><![CDATA[\ArrayAccess<int, Any>&RepeatedField]]></code>
347-
</MismatchingDocblockParamType>
348-
<MismatchingDocblockPropertyType>
349-
<code><![CDATA[\ArrayAccess<int, Any>&RepeatedField]]></code>
350-
</MismatchingDocblockPropertyType>
351-
<MismatchingDocblockReturnType>
352-
<code><![CDATA[\ArrayAccess<int, Any>&RepeatedField]]></code>
353-
</MismatchingDocblockReturnType>
354345
</file>
355346
<file src="src/Exception/Client/ServiceClientException.php">
356347
<ImplementedReturnTypeMismatch>
357348
<code><![CDATA[RepeatedField]]></code>
358349
</ImplementedReturnTypeMismatch>
359-
<InvalidReturnStatement>
360-
<code><![CDATA[$this->status->getDetails()]]></code>
361-
</InvalidReturnStatement>
362-
<InvalidReturnType>
363-
<code><![CDATA[RepeatedField]]></code>
364-
</InvalidReturnType>
365-
</file>
366-
<file src="src/Exception/Client/UnpackDetailsTrait.php">
367-
<RawObjectIteration>
368-
<code><![CDATA[$details]]></code>
369-
</RawObjectIteration>
370-
<UndefinedInterfaceMethod>
371-
<code><![CDATA[count]]></code>
372-
</UndefinedInterfaceMethod>
373350
</file>
374351
<file src="src/Exception/Client/WorkflowException.php">
375352
<UnsafeInstantiation>
@@ -827,9 +804,6 @@
827804
<NullableReturnStatement>
828805
<code><![CDATA[$mapper]]></code>
829806
</NullableReturnStatement>
830-
<PossibleRawObjectIteration>
831-
<code><![CDATA[$value]]></code>
832-
</PossibleRawObjectIteration>
833807
<PossiblyNullArgument>
834808
<code><![CDATA[$metadata->getDetails()]]></code>
835809
<code><![CDATA[$metadata->getSummary()]]></code>
@@ -997,13 +971,6 @@
997971
<code><![CDATA[$reflection->getName()]]></code>
998972
</PropertyTypeCoercion>
999973
</file>
1000-
<file src="src/Internal/Support/Facade.php">
1001-
<InvalidDocblock>
1002-
<code><![CDATA[object<T>|null]]></code>
1003-
<code><![CDATA[private static ?object $ctx = null;]]></code>
1004-
<code><![CDATA[public static function getCurrentContext(): object]]></code>
1005-
</InvalidDocblock>
1006-
</file>
1007974
<file src="src/Internal/Support/Inheritance.php">
1008975
<PossiblyFalseArgument>
1009976
<code><![CDATA[$implements]]></code>
@@ -1513,16 +1480,9 @@
15131480
</UnsafeInstantiation>
15141481
</file>
15151482
<file src="src/Workflow.php">
1516-
<InvalidReturnStatement>
1517-
<code><![CDATA[self::getCurrentContext()->newActivityStub($class, $options)]]></code>
1518-
<code><![CDATA[self::getCurrentContext()->registerQuery($queryType, $handler, $description)]]></code>
1519-
<code><![CDATA[self::getCurrentContext()->registerSignal($name, $handler, $description)]]></code>
1520-
</InvalidReturnStatement>
1521-
<InvalidReturnType>
1522-
<code><![CDATA[ScopedContextInterface]]></code>
1523-
<code><![CDATA[ScopedContextInterface]]></code>
1524-
<code><![CDATA[T]]></code>
1525-
</InvalidReturnType>
1483+
<UndefinedInterfaceMethod>
1484+
<code><![CDATA[getUpdateContext]]></code>
1485+
</UndefinedInterfaceMethod>
15261486
</file>
15271487
<file src="src/Workflow/ChildWorkflowOptions.php">
15281488
<PossiblyNullReference>

src/Activity.php

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,32 @@
1717
use Temporal\DataConverter\Type;
1818
use Temporal\DataConverter\ValuesInterface;
1919
use Temporal\Exception\OutOfContextException;
20+
use Temporal\Internal\Activity\ActivityContext;
2021
use Temporal\Internal\Support\Facade;
2122

22-
/**
23-
* @template-extends Facade<ActivityContextInterface>
24-
*/
2523
final class Activity extends Facade
2624
{
25+
/**
26+
* Get the current Activity context.
27+
* @throws OutOfContextException
28+
*/
29+
public static function getCurrentContext(): ActivityContextInterface
30+
{
31+
$ctx = parent::getCurrentContext();
32+
/** @var ActivityContext $ctx */
33+
$ctx::class === ActivityContext::class or throw new OutOfContextException(
34+
'The Activity facade can only be used in the context of an activity execution.',
35+
);
36+
return $ctx;
37+
}
38+
2739
/**
2840
* Returns information about current activity execution.
2941
*
3042
* @throws OutOfContextException in the absence of the activity execution context.
3143
*/
3244
public static function getInfo(): ActivityInfo
3345
{
34-
/** @var ActivityContextInterface $context */
3546
$context = self::getCurrentContext();
3647

3748
return $context->getInfo();
@@ -57,7 +68,6 @@ public static function getInfo(): ActivityInfo
5768
*/
5869
public static function getInput(): ValuesInterface
5970
{
60-
/** @var ActivityContextInterface $context */
6171
$context = self::getCurrentContext();
6272

6373
return $context->getInput();
@@ -72,7 +82,6 @@ public static function getInput(): ValuesInterface
7282
*/
7383
public static function hasHeartbeatDetails(): bool
7484
{
75-
/** @var ActivityContextInterface $context */
7685
$context = self::getCurrentContext();
7786

7887
return $context->hasHeartbeatDetails();
@@ -88,7 +97,6 @@ public static function hasHeartbeatDetails(): bool
8897
*/
8998
public static function getHeartbeatDetails($type = null): mixed
9099
{
91-
/** @var ActivityContextInterface $context */
92100
$context = self::getCurrentContext();
93101

94102
return $context->getLastHeartbeatDetails($type);
@@ -101,7 +109,6 @@ public static function getHeartbeatDetails($type = null): mixed
101109
*/
102110
public static function getCancellationDetails(): ?ActivityCancellationDetails
103111
{
104-
/** @var ActivityContextInterface $context */
105112
$context = self::getCurrentContext();
106113

107114
return $context->getCancellationDetails();
@@ -118,7 +125,6 @@ public static function getCancellationDetails(): ?ActivityCancellationDetails
118125
*/
119126
public static function doNotCompleteOnReturn(): void
120127
{
121-
/** @var ActivityContextInterface $context */
122128
$context = self::getCurrentContext();
123129

124130
$context->doNotCompleteOnReturn();
@@ -150,7 +156,6 @@ public static function doNotCompleteOnReturn(): void
150156
*/
151157
public static function heartbeat($details): void
152158
{
153-
/** @var ActivityContextInterface $context */
154159
$context = self::getCurrentContext();
155160

156161
$context->heartbeat($details);
@@ -161,7 +166,6 @@ public static function heartbeat($details): void
161166
*/
162167
public static function getInstance(): object
163168
{
164-
/** @var ActivityContextInterface $context */
165169
$context = self::getCurrentContext();
166170

167171
return $context->getInstance();

src/Internal/Support/Facade.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@
1313

1414
use Temporal\Exception\OutOfContextException;
1515

16-
/**
17-
* @template T of object
18-
*/
1916
abstract class Facade
2017
{
2118
/**
@@ -26,9 +23,6 @@ abstract class Facade
2623
'from the currently running process'
2724
;
2825

29-
/**
30-
* @var object<T>|null
31-
*/
3226
private static ?object $ctx = null;
3327

3428
/**
@@ -40,7 +34,6 @@ private function __construct()
4034
}
4135

4236
/**
43-
* @param object<T>|null $ctx
4437
* @internal
4538
*/
4639
public static function setCurrentContext(?object $ctx): void
@@ -49,7 +42,6 @@ public static function setCurrentContext(?object $ctx): void
4942
}
5043

5144
/**
52-
* @return object<T>
5345
* @throws OutOfContextException
5446
*/
5547
public static function getCurrentContext(): object

src/Internal/Transport/Router/InvokeActivity.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ static function (ActivityInput $input) use ($handler, $context): mixed {
101101
'handleActivityInbound',
102102
)(new ActivityInput($context->getInput(), $context->getHeader()));
103103

104+
/** @var ActivityContext $context */
104105
$context = Activity::getCurrentContext();
105106
if ($context->isDoNotCompleteOnReturn()) {
106107
$resolver->reject(DoNotCompleteOnResultException::create());

src/Internal/Transport/Router/StartWorkflow.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
use Temporal\Internal\Workflow\WorkflowContext;
2626
use Temporal\Worker\FeatureFlags;
2727
use Temporal\Worker\Transport\Command\ServerRequestInterface;
28-
use Temporal\Workflow;
2928
use Temporal\Workflow\WorkflowInfo;
3029

3130
final class StartWorkflow extends Route
@@ -90,7 +89,6 @@ public function handle(ServerRequestInterface $request, array $headers, Deferred
9089
);
9190
$runId = $request->getID();
9291

93-
Workflow::setCurrentContext($context);
9492
$process = new Process($this->services, $runId, $instance);
9593
$this->services->running->add($process);
9694
$resolver->resolve(EncodedValues::fromValues([null]));

src/Internal/Workflow/ActivityStub.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,6 @@ public function execute(
7070

7171
protected function request(RequestInterface $request): PromiseInterface
7272
{
73-
/** @var Workflow\WorkflowContextInterface $context */
74-
$context = Workflow::getCurrentContext();
75-
76-
return $context->request($request);
73+
return Workflow::getCurrentContext()->request($request);
7774
}
7875
}

src/Internal/Workflow/ChildWorkflowStub.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,7 @@ function (WorkflowExecution $execution) use ($name, $args) {
125125

126126
protected function request(RequestInterface $request, bool $cancellable = true): PromiseInterface
127127
{
128-
/** @var Workflow\WorkflowContextInterface $context */
129-
$context = Workflow::getCurrentContext();
130-
131-
return $context->request($request, cancellable: $cancellable);
128+
return Workflow::getCurrentContext()->request($request, cancellable: $cancellable);
132129
}
133130

134131
private function getOptionArray(): array

src/Internal/Workflow/ExternalWorkflowStub.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ public function cancel(): PromiseInterface
7777
private function request(RequestInterface $request): PromiseInterface
7878
{
7979
// todo intercept
80-
/** @var Workflow\WorkflowContextInterface $context */
8180
$context = Workflow::getCurrentContext();
8281

8382
return $context->request($request);

src/Workflow.php

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
use Temporal\Exception\Failure\CanceledFailure;
2424
use Temporal\Exception\OutOfContextException;
2525
use Temporal\Internal\Support\Facade;
26-
use Temporal\Internal\Workflow\ScopeContext;
2726
use Temporal\Workflow\ActivityStubInterface;
2827
use Temporal\Workflow\CancellationScopeInterface;
2928
use Temporal\Workflow\ChildWorkflowOptions;
@@ -45,18 +44,27 @@
4544
*
4645
* This is main class you can use in your workflow code.
4746
*
48-
* @method static ScopeContext getCurrentContext() Get current workflow context.
49-
*
5047
* @psalm-import-type TypeEnum from Type
5148
* @psalm-import-type DateIntervalValue from DateInterval
5249
* @see DateInterval
53-
*
54-
* @template-extends Facade<ScopedContextInterface>
5550
*/
5651
final class Workflow extends Facade
5752
{
5853
public const DEFAULT_VERSION = -1;
5954

55+
/**
56+
* Get the current Workflow context.
57+
* @throws OutOfContextException
58+
*/
59+
public static function getCurrentContext(): WorkflowContextInterface
60+
{
61+
$ctx = parent::getCurrentContext();
62+
$ctx instanceof WorkflowContextInterface or throw new OutOfContextException(
63+
'The Workflow facade can be used only inside workflow code.',
64+
);
65+
return $ctx;
66+
}
67+
6068
/**
6169
* Returns current datetime.
6270
*
@@ -192,7 +200,9 @@ public static function getInput(): ValuesInterface
192200
*/
193201
public static function async(callable $task): CancellationScopeInterface
194202
{
195-
return self::getCurrentContext()->async($task);
203+
$ctx = self::getCurrentContext();
204+
\assert($ctx instanceof ScopedContextInterface);
205+
return $ctx->async($task);
196206
}
197207

198208
/**
@@ -244,7 +254,9 @@ public static function async(callable $task): CancellationScopeInterface
244254
*/
245255
public static function asyncDetached(callable $task): CancellationScopeInterface
246256
{
247-
return self::getCurrentContext()->asyncDetached($task);
257+
$ctx = self::getCurrentContext();
258+
\assert($ctx instanceof ScopedContextInterface);
259+
return $ctx->asyncDetached($task);
248260
}
249261

250262
/**
@@ -352,7 +364,9 @@ public static function registerQuery(
352364
callable $handler,
353365
string $description = '',
354366
): ScopedContextInterface {
355-
return self::getCurrentContext()->registerQuery($queryType, $handler, $description);
367+
$ctx = self::getCurrentContext();
368+
\assert($ctx instanceof ScopedContextInterface);
369+
return $ctx->registerQuery($queryType, $handler, $description);
356370
}
357371

358372
/**
@@ -372,7 +386,9 @@ public static function registerQuery(
372386
*/
373387
public static function registerSignal(string $name, callable $handler, string $description = ''): ScopedContextInterface
374388
{
375-
return self::getCurrentContext()->registerSignal($name, $handler, $description);
389+
$ctx = self::getCurrentContext();
390+
\assert($ctx instanceof ScopedContextInterface);
391+
return $ctx->registerSignal($name, $handler, $description);
376392
}
377393

378394
/**
@@ -491,7 +507,9 @@ public static function registerUpdate(
491507
?callable $validator = null,
492508
string $description = '',
493509
): ScopedContextInterface {
494-
return self::getCurrentContext()->registerUpdate($name, $handler, $validator, $description);
510+
$ctx = self::getCurrentContext();
511+
\assert($ctx instanceof ScopedContextInterface);
512+
return $ctx->registerUpdate($name, $handler, $validator, $description);
495513
}
496514

497515
/**
@@ -995,7 +1013,6 @@ public static function getStackTrace(): string
9951013
*/
9961014
public static function allHandlersFinished(): bool
9971015
{
998-
/** @var ScopedContextInterface $context */
9991016
$context = self::getCurrentContext();
10001017

10011018
return $context->allHandlersFinished();
@@ -1081,7 +1098,6 @@ public static function upsertTypedSearchAttributes(SearchAttributeUpdate ...$upd
10811098
*/
10821099
public static function uuid(): PromiseInterface
10831100
{
1084-
/** @var ScopedContextInterface $context */
10851101
$context = self::getCurrentContext();
10861102

10871103
return $context->uuid();
@@ -1094,7 +1110,6 @@ public static function uuid(): PromiseInterface
10941110
*/
10951111
public static function uuid4(): PromiseInterface
10961112
{
1097-
/** @var ScopedContextInterface $context */
10981113
$context = self::getCurrentContext();
10991114

11001115
return $context->uuid4();
@@ -1111,7 +1126,6 @@ public static function uuid4(): PromiseInterface
11111126
*/
11121127
public static function uuid7(?\DateTimeInterface $dateTime = null): PromiseInterface
11131128
{
1114-
/** @var ScopedContextInterface $context */
11151129
$context = self::getCurrentContext();
11161130

11171131
return $context->uuid7($dateTime);

src/Workflow/WorkflowContextInterface.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,4 +440,9 @@ public function uuid7(?\DateTimeInterface $dateTime = null): PromiseInterface;
440440
* Logs in replay mode are omitted unless {@see WorkerOptions::$enableLoggingInReplay} is set to true.
441441
*/
442442
public function getLogger(): LoggerInterface;
443+
444+
/**
445+
* Get the currently running Workflow instance.
446+
*/
447+
public function getInstance(): object;
443448
}

0 commit comments

Comments
 (0)