From 49d04e385773466b30f945136febdc62dc1217ce Mon Sep 17 00:00:00 2001 From: Chad Retz Date: Mon, 3 Feb 2025 13:14:18 -0600 Subject: [PATCH] Fix issue where null timer summary breaks codec Fixes #400 --- src/Temporalio/Worker/WorkflowCodecHelper.cs | 5 ++++- .../Worker/WorkflowCodecHelperTests.cs | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Temporalio/Worker/WorkflowCodecHelper.cs b/src/Temporalio/Worker/WorkflowCodecHelper.cs index bdc782c1..9fbde27e 100644 --- a/src/Temporalio/Worker/WorkflowCodecHelper.cs +++ b/src/Temporalio/Worker/WorkflowCodecHelper.cs @@ -193,7 +193,10 @@ await EncodeAsync( } break; case WorkflowCommand.VariantOneofCase.StartTimer: - await EncodeAsync(codec, cmd.StartTimer.Summary).ConfigureAwait(false); + if (cmd.StartTimer.Summary != null) + { + await EncodeAsync(codec, cmd.StartTimer.Summary).ConfigureAwait(false); + } break; case WorkflowCommand.VariantOneofCase.UpdateResponse: if (cmd.UpdateResponse.Completed is { } updateCompleted) diff --git a/tests/Temporalio.Tests/Worker/WorkflowCodecHelperTests.cs b/tests/Temporalio.Tests/Worker/WorkflowCodecHelperTests.cs index df041c77..228814f8 100644 --- a/tests/Temporalio.Tests/Worker/WorkflowCodecHelperTests.cs +++ b/tests/Temporalio.Tests/Worker/WorkflowCodecHelperTests.cs @@ -78,6 +78,26 @@ await CreateAndVisitPayload(new(), act, async (ctx, payload) => }); } + [Fact] + public async Task EncodeAsync_AllPayloads_WorksWithNull() + { + // For every singular Payload field, we are going to set it to null and ensure it can still + // encode. This is to prevent regression since we missed that sometimes we are not checking + // for null in WorkflowCodecHelper. + var comp = new WorkflowActivationCompletion(); + var codec = new MarkerPayloadCodec(); + await CreateAndVisitPayload(new(), comp, async (ctx, payload) => + { + var (msg, prop) = ctx.PropertyPath.Last(); + var propInfo = msg.GetType().GetProperty(prop); + if (propInfo?.PropertyType == typeof(Payload)) + { + propInfo.SetValue(msg, null); + await WorkflowCodecHelper.EncodeAsync(codec, comp); + } + }); + } + // Creates payloads as needed, null context if already seen private static async Task CreateAndVisitPayload( PayloadVisitContext ctx, IMessage current, Func, Task> visitor)