Skip to content

Commit b5ca854

Browse files
authored
Accept search attributes for dev server (#289)
Fixes #282
1 parent 3dd6cca commit b5ca854

File tree

5 files changed

+74
-4
lines changed

5 files changed

+74
-4
lines changed

src/Temporalio/Bridge/EphemeralServer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ private unsafe EphemeralServer(
4040
public bool HasTestService { get; private init; }
4141

4242
/// <summary>
43-
/// Start Temporalite.
43+
/// Start dev server.
4444
/// </summary>
4545
/// <param name="runtime">Runtime to use.</param>
4646
/// <param name="options">Options to use.</param>
4747
/// <returns>Started server.</returns>
48-
public static async Task<EphemeralServer> StartTemporaliteAsync(
48+
public static async Task<EphemeralServer> StartDevServerAsync(
4949
Runtime runtime,
5050
Testing.WorkflowEnvironmentStartLocalOptions options)
5151
{

src/Temporalio/Bridge/OptionsExtensions.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,17 @@ public static unsafe Interop.DevServerOptions ToInteropOptions(
352352
// Use TargetHost to get IP + Port
353353
options.ParseTargetHost(out string? ip, out int? port);
354354
ip ??= "127.0.0.1";
355+
356+
// If there are search attributes, prepend them to the args
357+
var args = options.DevServerOptions.ExtraArgs;
358+
if (options.SearchAttributes is { } attrs && attrs.Count > 0)
359+
{
360+
args = attrs.
361+
SelectMany(v => new[] { "--search-attribute", $"{v.Name}={v.ValueType}" }).
362+
Concat(args ?? Enumerable.Empty<string>()).
363+
ToArray();
364+
}
365+
355366
return new Interop.DevServerOptions()
356367
{
357368
test_server = scope.Pointer(
@@ -363,7 +374,7 @@ public static unsafe Interop.DevServerOptions ToInteropOptions(
363374
download_version = scope.ByteArray(options.DevServerOptions.DownloadVersion),
364375
download_dest_dir = scope.ByteArray(options.DownloadDirectory),
365376
port = (ushort)(port ?? 0),
366-
extra_args = scope.NewlineDelimited(options.DevServerOptions.ExtraArgs),
377+
extra_args = scope.NewlineDelimited(args),
367378
}),
368379
namespace_ = scope.ByteArray(options.Namespace),
369380
ip = scope.ByteArray(ip),

src/Temporalio/Testing/WorkflowEnvironment.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public static async Task<WorkflowEnvironment> StartLocalAsync(
6767
{
6868
options ??= new();
6969
var runtime = options.Runtime ?? TemporalRuntime.Default;
70-
var server = await Bridge.EphemeralServer.StartTemporaliteAsync(
70+
var server = await Bridge.EphemeralServer.StartDevServerAsync(
7171
runtime.Runtime,
7272
options).ConfigureAwait(false);
7373
return await StartEphemeralAsync(server, options).ConfigureAwait(false);

src/Temporalio/Testing/WorkflowEnvironmentStartLocalOptions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
using System.Collections.Generic;
2+
using Temporalio.Common;
3+
14
namespace Temporalio.Testing
25
{
36
/// <summary>
@@ -18,6 +21,11 @@ public class WorkflowEnvironmentStartLocalOptions : Client.TemporalClientConnect
1821
/// </summary>
1922
public bool UI { get; set; }
2023

24+
/// <summary>
25+
/// Gets or sets search attributes registered on the dev server on start.
26+
/// </summary>
27+
public IReadOnlyCollection<SearchAttributeKey>? SearchAttributes { get; set; }
28+
2129
/// <summary>
2230
/// Gets or sets <b>unstable</b> dev server options.
2331
/// </summary>

tests/Temporalio.Tests/Testing/WorkflowEnvironmentTests.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace Temporalio.Tests.Testing;
77
using Temporalio.Activities;
88
using Temporalio.Api.Enums.V1;
99
using Temporalio.Client;
10+
using Temporalio.Common;
1011
using Temporalio.Exceptions;
1112
using Temporalio.Testing;
1213
using Temporalio.Worker;
@@ -199,4 +200,54 @@ await env.Client.ExecuteWorkflowAsync(
199200
});
200201
});
201202
}
203+
204+
[Fact]
205+
public async Task StartLocal_SearchAttributes_ProperlyRegistered()
206+
{
207+
// Prepare attrs
208+
var attrBool = SearchAttributeKey.CreateBool("DotNetTemporalTestBool");
209+
var attrDateTime = SearchAttributeKey.CreateDateTimeOffset("DotNetTemporalTestDateTime");
210+
var attrDouble = SearchAttributeKey.CreateDouble("DotNetTemporalTestDouble");
211+
var attrKeyword = SearchAttributeKey.CreateKeyword("DotNetTemporalTestKeyword");
212+
var attrKeywordList = SearchAttributeKey.CreateKeywordList("DotNetTemporalTestKeywordList");
213+
var attrLong = SearchAttributeKey.CreateLong("DotNetTemporalTestLong");
214+
var attrText = SearchAttributeKey.CreateText("DotNetTemporalTestText");
215+
var attrVals = new SearchAttributeCollection.Builder().
216+
Set(attrBool, true).
217+
Set(attrDateTime, new DateTimeOffset(2001, 1, 1, 0, 0, 0, TimeSpan.Zero)).
218+
Set(attrDouble, 123.45).
219+
Set(attrKeyword, "SomeKeyword").
220+
Set(attrKeywordList, new[] { "SomeKeyword1", "SomeKeyword2" }).
221+
Set(attrLong, 678).
222+
Set(attrText, "SomeText").
223+
ToSearchAttributeCollection();
224+
var attrs = new SearchAttributeKey[]
225+
{
226+
attrBool, attrDateTime, attrDouble, attrKeyword, attrKeywordList, attrLong, attrText,
227+
};
228+
229+
// Confirm that when used in env without SAs it fails
230+
await using var env1 = await WorkflowEnvironment.StartLocalAsync();
231+
var exc = await Assert.ThrowsAsync<RpcException>(
232+
() => env1.Client.StartWorkflowAsync(
233+
"my-workflow",
234+
Array.Empty<object?>(),
235+
new(id: $"wf-{Guid.NewGuid()}", taskQueue: $"tq-{Guid.NewGuid()}")
236+
{
237+
TypedSearchAttributes = attrVals,
238+
}));
239+
Assert.Contains("no mapping defined", exc.Message);
240+
241+
// Confirm that when used in env with SAs it succeeds
242+
await using var env2 = await WorkflowEnvironment.StartLocalAsync(
243+
new() { SearchAttributes = attrs });
244+
var handle = await env2.Client.StartWorkflowAsync(
245+
"my-workflow",
246+
Array.Empty<object?>(),
247+
new(id: $"wf-{Guid.NewGuid()}", taskQueue: $"tq-{Guid.NewGuid()}")
248+
{
249+
TypedSearchAttributes = attrVals,
250+
});
251+
Assert.Equal(attrVals, (await handle.DescribeAsync()).TypedSearchAttributes);
252+
}
202253
}

0 commit comments

Comments
 (0)