temporalio / roadrunner-temporal

Temporal PHP-SDK Host Process plugin for Roadrunner
MIT License
22 stars 8 forks source link

[🐛 BUG]: proto_codec_parse_message Empty searchAttributes child workflow #566

Closed root-aza closed 2 weeks ago

root-aza commented 2 weeks ago

No duplicates 🥲.

What happened?

Repoduce code:

#[WorkflowInterface]
final class AWorkflow
{
    #[WorkflowMethod]
    public function start(bool $child = false): \Generator
    {
        if ($child){
            return;
        }

        yield Workflow::newChildWorkflowStub(
            self::class,
            ChildWorkflowOptions::new()
                ->withSearchAttributes([]) // bang 💥
        )->start(true);
    }
}

Version

version rr: 2024.2.1 version sdk: 2.11

Relevant log output

{
  "message": "proto_codec_parse_message: expected { character for map value",
  "source": "GoSDK",
  "stackTrace": "process event for default [panic]:\ngithub.com/temporalio/roadrunner-temporal/v5/aggregatedpool.(*Workflow).OnWorkflowTaskStarted(0x4000e9e460, 0x3?)\n\tgithub.com/temporalio/roadrunner-temporal/v5@v5.1.1/aggregatedpool/workflow.go:194 +0x360\ngo.temporal.io/sdk/internal.(*workflowExecutionEventHandlerImpl).ProcessEvent(0x4000e80be8, 0x4000cb33b0, 0x20?, 0x1)\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_event_handlers.go:1208 +0x1f0\ngo.temporal.io/sdk/internal.(*workflowExecutionContextImpl).ProcessWorkflowTask(0x4000c49400, 0x40008f6a20)\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_task_handlers.go:1152 +0x13f0\ngo.temporal.io/sdk/internal.(*workflowTaskHandlerImpl).ProcessWorkflowTask(0x4000e98b60, 0x40008f6a20, 0x4000c49400, 0x40005f1b30)\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_task_handlers.go:917 +0x2b8\ngo.temporal.io/sdk/internal.(*workflowTaskPoller).processWorkflowTask(0x4000e8e900, 0x40008f6a20)\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_task_pollers.go:363 +0x334\ngo.temporal.io/sdk/internal.(*workflowTaskPoller).ProcessTask(0x4000e8e900, {0x17926a0, 0x40008f6a20})\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_task_pollers.go:325 +0x70\ngo.temporal.io/sdk/internal.(*baseWorker).processTaskAsync.func1()\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_worker_base.go:444 +0x104\ncreated by go.temporal.io/sdk/internal.(*baseWorker).processTaskAsync in goroutine 45\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_worker_base.go:423 +0x90",
  "encodedAttributes": null,
  "cause": null,
  "applicationFailureInfo": {
    "type": "PanicError",
    "nonRetryable": true,
    "details": null
  }
Workflow events ```json { "events": [ { "eventId": "1", "eventTime": "2024-10-05T19:01:43.920084426Z", "eventType": "WorkflowExecutionStarted", "version": "0", "taskId": "1048647", "workerMayIgnore": false, "workflowExecutionStartedEventAttributes": { "workflowType": { "name": "ActivityRetry.greet" }, "parentWorkflowNamespace": "", "parentWorkflowNamespaceId": "", "parentWorkflowExecution": null, "parentInitiatedEventId": "0", "taskQueue": { "name": "default", "kind": "Normal", "normalName": "" }, "input": { "payloads": [ { "metadata": { "encoding": "anNvbi9wbGFpbg==" }, "data": "IkFudG9ueSI=" } ] }, "workflowExecutionTimeout": "60s", "workflowRunTimeout": "60s", "workflowTaskTimeout": "10s", "continuedExecutionRunId": "", "initiator": "Unspecified", "continuedFailure": null, "lastCompletionResult": null, "originalExecutionRunId": "2f36f4fc-035d-47d1-8526-90bc35c70b48", "identity": "88@28ca3010650c", "firstExecutionRunId": "2f36f4fc-035d-47d1-8526-90bc35c70b48", "retryPolicy": null, "attempt": 1, "workflowExecutionExpirationTime": "2024-10-05T19:02:43.920Z", "cronSchedule": "", "firstWorkflowTaskBackoff": "0s", "memo": null, "searchAttributes": { "indexedFields": {} }, "prevAutoResetPoints": null, "header": { "fields": {} }, "parentInitiatedEventVersion": "0", "workflowId": "dba488dc-d4e2-4f7c-8d0b-8f85b857b834", "sourceVersionStamp": null } }, { "eventId": "2", "eventTime": "2024-10-05T19:01:43.920196051Z", "eventType": "WorkflowTaskScheduled", "version": "0", "taskId": "1048648", "workerMayIgnore": false, "workflowTaskScheduledEventAttributes": { "taskQueue": { "name": "default", "kind": "Normal", "normalName": "" }, "startToCloseTimeout": "10s", "attempt": 1 } }, { "eventId": "3", "eventTime": "2024-10-05T19:01:43.927352301Z", "eventType": "WorkflowTaskStarted", "version": "0", "taskId": "1048654", "workerMayIgnore": false, "workflowTaskStartedEventAttributes": { "scheduledEventId": "2", "identity": "default:a2ba3d21-00b5-44c1-bfef-1700289170ab", "requestId": "6c1d2a10-b8d8-400e-8e0d-59d1cdf4671b", "suggestContinueAsNew": false, "historySizeBytes": "319" } }, { "eventId": "4", "eventTime": "2024-10-05T19:01:43.952319551Z", "eventType": "WorkflowTaskFailed", "version": "0", "taskId": "1048658", "workerMayIgnore": false, "workflowTaskFailedEventAttributes": { "scheduledEventId": "2", "startedEventId": "3", "cause": "WorkflowWorkerUnhandledFailure", "failure": { "message": "proto_codec_parse_message: expected { character for map value", "source": "GoSDK", "stackTrace": "process event for default [panic]:\ngithub.com/temporalio/roadrunner-temporal/v5/aggregatedpool.(*Workflow).OnWorkflowTaskStarted(0x4000e9e460, 0x3?)\n\tgithub.com/temporalio/roadrunner-temporal/v5@v5.1.1/aggregatedpool/workflow.go:194 +0x360\ngo.temporal.io/sdk/internal.(*workflowExecutionEventHandlerImpl).ProcessEvent(0x4000e80be8, 0x4000cb33b0, 0x20?, 0x1)\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_event_handlers.go:1208 +0x1f0\ngo.temporal.io/sdk/internal.(*workflowExecutionContextImpl).ProcessWorkflowTask(0x4000c49400, 0x40008f6a20)\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_task_handlers.go:1152 +0x13f0\ngo.temporal.io/sdk/internal.(*workflowTaskHandlerImpl).ProcessWorkflowTask(0x4000e98b60, 0x40008f6a20, 0x4000c49400, 0x40005f1b30)\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_task_handlers.go:917 +0x2b8\ngo.temporal.io/sdk/internal.(*workflowTaskPoller).processWorkflowTask(0x4000e8e900, 0x40008f6a20)\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_task_pollers.go:363 +0x334\ngo.temporal.io/sdk/internal.(*workflowTaskPoller).ProcessTask(0x4000e8e900, {0x17926a0, 0x40008f6a20})\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_task_pollers.go:325 +0x70\ngo.temporal.io/sdk/internal.(*baseWorker).processTaskAsync.func1()\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_worker_base.go:444 +0x104\ncreated by go.temporal.io/sdk/internal.(*baseWorker).processTaskAsync in goroutine 45\n\tgo.temporal.io/sdk@v1.29.1/internal/internal_worker_base.go:423 +0x90", "encodedAttributes": null, "cause": null, "applicationFailureInfo": { "type": "PanicError", "nonRetryable": true, "details": null } }, "identity": "default:a2ba3d21-00b5-44c1-bfef-1700289170ab", "baseRunId": "", "newRunId": "", "forkEventVersion": "0", "binaryChecksum": "", "workerVersion": null } }, { "eventId": "5", "eventTime": "2024-10-05T19:02:43.923306759Z", "eventType": "WorkflowExecutionTimedOut", "version": "0", "taskId": "1048675", "workerMayIgnore": false, "workflowExecutionTimedOutEventAttributes": { "retryState": "Timeout", "newExecutionRunId": "" } } ] } ```
rustatian commented 2 weeks ago

Hey @root-aza 👋 I guess this is because [] is not a valid value for Go. Is it working with an empty, but not [] value?

root-aza commented 2 weeks ago

Hey @root-aza 👋

I guess this is because [] is not a valid value for Go. Is it working with an empty, but not [] value?

null - ok.

if you run a workflow not child with an empty array, then everything is ok.

This behavior is only in child workflow

rustatian commented 2 weeks ago

Yeah, this is a well-known PHP<->Go incompatibility, this should be fixed in SDK-PHP I suppose, but need to double-check. Panic here is just a way to propagate an exception, so, nothing actually breaking.

rustatian commented 2 weeks ago

I mean, [] is a valid JSON from the PHP side, but not from Go. Go expects only {} as an empty JSON. I'm not a PHP dev, but I remember an option, smt like JSON_FORCE_OBJECT, but I'm not sure for the naming. All empty values should be passed with this option rather than []. I'll double check that and if true, the issue should be redirected to SDK-PHP.

rustatian commented 2 weeks ago

This behavior is only in child workflow

This is because ChildWorkflow executed via different handler rather than the regular Workflow.

rustatian commented 2 weeks ago

Yes, this is because [] -> "SearchAttributes\":[] <-----, should be null or {}:

image

Please, recreate the issue in the SDK-PHP with the reference on this discussion. Thanks.