Accept zero payloads when decoding a Void input#152
Conversation
3cd2553 to
3f136ad
Compare
The Swift SDK encodes a `Void` input as a single empty payload, whereas the other SDKs send zero payloads for no input. In one place, `UpdateWithStart`, the Swift SDK does the right thing and sends zero payloads. But on decode the worker rejects zero payloads for `Void.self`: `convertPayloads(as: Void.self)` requires exactly one. So a `Void` update sent via `UpdateWithStart` is rejected before acceptance, and the client sees `notFound` even though the workflow runs fine. Making the encode consistently send zero payloads would break older workers that still expect the payload, so it is left as a separate change. In `PayloadConverter.convertPayloads`, treat a single `Void` as carrying no payload and ignore the input payload count, matching the other SDKs, which ignore extra input payloads.
3f136ad to
50c6540
Compare
| // Older Swift clients / workers incorrectly send `Void` input as a JSON payload in certain | ||
| // cases; like the other SDKs, ignore extra input payloads for a lone `Void`. |
There was a problem hiding this comment.
Can you link where the other SDKs are ignoring single payloads? Also do I understand this correct that in the current SDK this is not a problem but when decoding workflows started by older SDKs?
There was a problem hiding this comment.
They aren't ignoring single payloads per-se. They ignore any extra payloads delivered beyond what they are decoding for and only error when not enough were delivered.
In addition we are incorrectly encoding Void as a payload, when it is sent as zero payloads by other SDKs. I.e. Void / () is overloaded in Swift to mean the absence of a type, so it should be encoded as zero payloads, but we encode it as a single zero-byte payload.
It is intentional that we discard extra input arguments that the signature doesn't accept.
We want to discard extra arguments if we can.
The change in this PR only fixes the Void sent as empty / zero-byte payload case but I can adjust to be general instead if we want to match all SDKs now in that regard. It would be moving towards leniency at least so not so breaking of a change.
Motivation
The Swift SDK encodes a
Voidinput as a single empty payload, whereas the other SDKs send zero payloads for no input. In one place,UpdateWithStart, the Swift SDK does the right thing and sends zero payloads. But on decode the worker rejects zero payloads forVoid.self:convertPayloads(as: Void.self)requires exactly one. So aVoidupdate sent viaUpdateWithStartis rejected before acceptance, and the client seesnotFoundeven though the workflow runs fine.Making the encode consistently send zero payloads would break older workers that still expect the payload, so it is left as a separate change.
Modifications
In
PayloadConverter.convertPayloads, treat a singleVoidas carrying no payload and ignore the input payload count, matching the other SDKs, which ignore extra input payloads.Result
A
Voidupdate, signal, or query sent with zero payloads is accepted instead of dropped. The encode is unchanged, so it is safe to roll out in any client / worker order.Other Issues (will file separately)
notFound, which does not match the other SDKs / APIs that return the conversion failure; the real error is lost.UpdateWithStartclient does not use the update outcome returned in the firstExecuteMultiOperationresponse; it discards it and makes an extraPollWorkflowExecutionUpdatecall. The other SDKs reuse the first response.Voidas zero payloads, matching the other SDKs, instead of a single empty payload. This is a breaking wire change because older workers require the payload, so it needs its own change and a version bump.Test Plan
updateWithStartVoidInputandupdateWithStartVoidInputZeroPayloadsinWorkflowUpdateTests.swift;swift testpasses.