Skip to content

Commit faac77a

Browse files
committed
Make Workflow Context readonly during init
1 parent e09b307 commit faac77a

File tree

3 files changed

+39
-3
lines changed

3 files changed

+39
-3
lines changed

src/Internal/Workflow/Process/Process.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ public function initAndStart(
208208
$instance->init();
209209
}
210210

211+
$context->setReadonly(false);
212+
211213
// Execute
212214
//
213215
// Run workflow handler in an interceptor pipeline
@@ -234,7 +236,7 @@ function (WorkflowInput $input) use ($context, $arguments, $handler, $deferred):
234236
));
235237
} catch (\Throwable $e) {
236238
/** @psalm-suppress RedundantPropertyInitializationCheck */
237-
isset($this->context) or $this->setContext($context);
239+
isset($this->context) or $this->setContext($context->setReadonly(false));
238240
$this->complete($e);
239241
} finally {
240242
Workflow::setCurrentContext(null);

src/Internal/Workflow/WorkflowContext.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ class WorkflowContext implements WorkflowContextInterface, HeaderCarrier, Destro
8989

9090
private array $trace = [];
9191
private bool $continueAsNew = false;
92+
private bool $readonly = true;
9293

9394
/** @var Pipeline<WorkflowOutboundRequestInterceptor, PromiseInterface> */
9495
private Pipeline $requestInterceptor;
@@ -148,9 +149,10 @@ public function getInput(): ValuesInterface
148149
return $this->input->input;
149150
}
150151

151-
public function setInput(Input $input): void
152+
public function setReadonly(bool $value = true): static
152153
{
153-
$this->input = $input;
154+
$this->readonly = $value;
155+
return $this;
154156
}
155157

156158
public function withInput(Input $input): static
@@ -460,6 +462,7 @@ public function request(
460462
bool $cancellable = true,
461463
bool $waitResponse = true,
462464
): PromiseInterface {
465+
$this->readonly and throw new \RuntimeException('Workflow is not initialized.');
463466
$this->recordTrace();
464467

465468
// Intercept workflow outbound calls

tests/Acceptance/Extra/Interceptors/ContextTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
namespace Temporal\Tests\Acceptance\Extra\Interceptors\Context;
66

77
use PHPUnit\Framework\Attributes\Test;
8+
use React\Promise\PromiseInterface;
89
use Temporal\Activity;
910
use Temporal\Client\WorkflowStubInterface;
1011
use Temporal\DataConverter\EncodedValues;
12+
use Temporal\DataConverter\Type;
1113
use Temporal\Exception\Client\WorkflowFailedException;
1214
use Temporal\Exception\Failure\ApplicationFailure;
1315
use Temporal\Interceptor\ActivityInbound\ActivityInput;
@@ -65,6 +67,13 @@ public function failInInterceptorExecute(
6567
self::assertStringContainsString('exception-in-execute', $prev->getOriginalMessage());
6668
}
6769
}
70+
71+
#[Test]
72+
public function readonlyContextInConstructor(
73+
#[Stub('Extra_Interceptors_Context_Readonly')] WorkflowStubInterface $stub,
74+
): void {
75+
self::assertTrue($stub->getResult(Type::TYPE_BOOL), 'Workflow instance in context is not readonly');
76+
}
6877
}
6978

7079
class WorkerServices
@@ -131,6 +140,28 @@ public function handle(mixed ...$input)
131140
}
132141
}
133142

143+
#[WorkflowInterface]
144+
class TestReadonlyConstructorWorkflow
145+
{
146+
private ?PromiseInterface $uuid = null;
147+
148+
#[Workflow\WorkflowInit]
149+
public function __construct(mixed ...$input)
150+
{
151+
try {
152+
$this->uuid = Workflow::uuid7();
153+
} catch (\Throwable $e) {
154+
$e->getMessage() === 'Workflow is not initialized.' or throw $e;
155+
}
156+
}
157+
158+
#[WorkflowMethod(name: "Extra_Interceptors_Context_Readonly")]
159+
public function handle()
160+
{
161+
return $this->uuid === null;
162+
}
163+
}
164+
134165
#[Activity\ActivityInterface(prefix: 'Extra_Interceptors_Context.')]
135166
class TestActivity
136167
{

0 commit comments

Comments
 (0)