diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index 29cf6ce4..fdae7573 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -1178,6 +1178,7 @@
+ currentDetails = &$context->currentDetails]]>
trace = &$context->trace]]>
diff --git a/src/DataConverter/ProtoJsonConverter.php b/src/DataConverter/ProtoJsonConverter.php
index 34daf659..493f1dde 100644
--- a/src/DataConverter/ProtoJsonConverter.php
+++ b/src/DataConverter/ProtoJsonConverter.php
@@ -50,7 +50,13 @@ public function toPayload($value): ?Payload
public function fromPayload(Payload $payload, Type $type)
{
if (!$type->isClass()) {
- throw new DataConverterException('Unable to decode value using protobuf converter - ');
+ throw new DataConverterException(
+ \sprintf(
+ 'Unable to decode value using "%s" encoding converter: resulting type must be a class, "%s" given',
+ $this->getEncodingType(),
+ $type->getName(),
+ ),
+ );
}
try {
diff --git a/src/Internal/Transport/Router/InvokeQuery.php b/src/Internal/Transport/Router/InvokeQuery.php
index 30ba6b96..b19580b7 100644
--- a/src/Internal/Transport/Router/InvokeQuery.php
+++ b/src/Internal/Transport/Router/InvokeQuery.php
@@ -122,12 +122,14 @@ private function workflowMetadata(Deferred $resolver, WorkflowContext $context):
static function () use ($resolver, $context): void {
try {
$result = EncodedValues::fromValues([
- (new WorkflowMetadata())->setDefinition(
- (new WorkflowDefinition())
- ->setQueryDefinitions($context->getQueryDispatcher()->getQueryHandlers())
- ->setSignalDefinitions($context->getSignalDispatcher()->getSignalHandlers())
- ->setUpdateDefinitions($context->getUpdateDispatcher()->getUpdateHandlers()),
- ),
+ (new WorkflowMetadata())
+ ->setDefinition(
+ (new WorkflowDefinition())
+ ->setQueryDefinitions($context->getQueryDispatcher()->getQueryHandlers())
+ ->setSignalDefinitions($context->getSignalDispatcher()->getSignalHandlers())
+ ->setUpdateDefinitions($context->getUpdateDispatcher()->getUpdateHandlers()),
+ )
+ ->setCurrentDetails((string) $context->getCurrentDetails()),
]);
$resolver->resolve($result);
diff --git a/src/Internal/Workflow/ScopeContext.php b/src/Internal/Workflow/ScopeContext.php
index bff6743a..b9a3ebab 100644
--- a/src/Internal/Workflow/ScopeContext.php
+++ b/src/Internal/Workflow/ScopeContext.php
@@ -57,6 +57,7 @@ public static function fromWorkflowContext(
$ctx->readonly = $context->readonly;
$ctx->continueAsNew = $context->continueAsNew;
$ctx->trace = &$context->trace;
+ $ctx->currentDetails = &$context->currentDetails;
return $ctx;
}
diff --git a/src/Internal/Workflow/WorkflowContext.php b/src/Internal/Workflow/WorkflowContext.php
index 26e8fb84..5fc887cb 100644
--- a/src/Internal/Workflow/WorkflowContext.php
+++ b/src/Internal/Workflow/WorkflowContext.php
@@ -99,6 +99,7 @@ class WorkflowContext implements WorkflowContextInterface, HeaderCarrier, Destro
protected array $trace = [];
protected bool $continueAsNew = false;
protected bool $readonly = true;
+ protected ?string $currentDetails = null;
/** @var Pipeline */
private Pipeline $requestInterceptor;
@@ -723,6 +724,22 @@ public function getUpdateDispatcher(): UpdateDispatcher
return $this->updateDispatcher;
}
+ /**
+ * Get the current details of the workflow execution.
+ */
+ public function getCurrentDetails(): ?string
+ {
+ return $this->currentDetails;
+ }
+
+ /**
+ * Set the current details of the workflow execution.
+ */
+ public function setCurrentDetails(?string $details): void
+ {
+ $this->currentDetails = $details;
+ }
+
protected function awaitRequest(callable|Mutex|PromiseInterface ...$conditions): PromiseInterface
{
$result = [];
diff --git a/src/Workflow.php b/src/Workflow.php
index 5712ef60..e8927f88 100644
--- a/src/Workflow.php
+++ b/src/Workflow.php
@@ -604,6 +604,22 @@ public static function timer($interval, ?TimerOptions $options = null): PromiseI
return self::getCurrentContext()->timer($interval, $options);
}
+ /**
+ * Get the current details of the workflow execution.
+ */
+ public static function getCurrentDetails(): ?string
+ {
+ return self::getCurrentContext()->getCurrentDetails();
+ }
+
+ /**
+ * Set the current details of the workflow execution.
+ */
+ public static function setCurrentDetails(?string $details): void
+ {
+ self::getCurrentContext()->setCurrentDetails($details);
+ }
+
/**
* Completes the current workflow execution atomically and starts a new execution with the same Workflow Id.
*
diff --git a/src/Workflow/WorkflowContextInterface.php b/src/Workflow/WorkflowContextInterface.php
index 945eda1c..30548a8f 100644
--- a/src/Workflow/WorkflowContextInterface.php
+++ b/src/Workflow/WorkflowContextInterface.php
@@ -445,4 +445,14 @@ public function getLogger(): LoggerInterface;
* Get the currently running Workflow instance.
*/
public function getInstance(): object;
+
+ /**
+ * Get the current details of the workflow execution.
+ */
+ public function getCurrentDetails(): ?string;
+
+ /**
+ * Set the current details of the workflow execution.
+ */
+ public function setCurrentDetails(?string $details): void;
}
diff --git a/tests/Acceptance/Extra/Workflow/WorkflowMetadataTest.php b/tests/Acceptance/Extra/Workflow/WorkflowMetadataTest.php
new file mode 100644
index 00000000..4a90e47b
--- /dev/null
+++ b/tests/Acceptance/Extra/Workflow/WorkflowMetadataTest.php
@@ -0,0 +1,60 @@
+query('__temporal_workflow_metadata');
+ /**
+ * @var WorkflowMetadata|null $metadata
+ */
+ $metadata = $values->getValue(0, WorkflowMetadata::class);
+
+ $stub->signal('exit');
+ $this->assertSame("Cooking workflow from test", $metadata->getCurrentDetails());
+ }
+}
+
+#[WorkflowInterface]
+class TestWorkflow
+{
+ private bool $exit = false;
+
+ #[WorkflowMethod(name: "Extra_Workflow_WorkflowMetadata")]
+ public function handle(string $payload)
+ {
+ Workflow::setCurrentDetails("Cooking workflow " . $payload);
+
+ yield Workflow::await(fn() => $this->exit);
+ }
+
+ /**
+ * @return null|non-empty-string
+ */
+ #[Workflow\QueryMethod]
+ public function getCurrentDetails(): ?string
+ {
+ return Workflow::getCurrentDetails();
+ }
+
+ #[Workflow\SignalMethod]
+ public function exit(): void
+ {
+ $this->exit = true;
+ }
+}