Skip to content

Commit 7da468b

Browse files
committed
Avoid double Client SafeHandle implementation
1 parent 3ab0a73 commit 7da468b

5 files changed

Lines changed: 58 additions & 28 deletions

File tree

src/Temporalio/Bridge/Client.cs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Runtime.InteropServices;
43
using System.Threading.Tasks;
54
using Google.Protobuf;
65

@@ -9,18 +8,16 @@ namespace Temporalio.Bridge
98
/// <summary>
109
/// Core-owned Temporal client.
1110
/// </summary>
12-
internal class Client : SafeHandle
11+
internal class Client : IDisposable
1312
{
13+
private readonly SafeClientHandle handle;
14+
1415
private unsafe Client(Runtime runtime, Interop.TemporalCoreClient* ptr)
15-
: base((IntPtr)ptr, true)
1616
{
1717
Runtime = runtime;
18-
Handle = new SafeClientHandle(ptr);
18+
handle = new SafeClientHandle(ptr);
1919
}
2020

21-
/// <inheritdoc />
22-
public override bool IsInvalid => Handle.IsInvalid;
23-
2421
/// <summary>
2522
/// Gets the runtime associated with this client.
2623
/// </summary>
@@ -29,7 +26,7 @@ private unsafe Client(Runtime runtime, Interop.TemporalCoreClient* ptr)
2926
/// <summary>
3027
/// Gets the safe handle for the client.
3128
/// </summary>
32-
internal SafeClientHandle Handle { get; private init; }
29+
internal SafeClientHandle Handle => handle;
3330

3431
/// <summary>
3532
/// Connect to Temporal.
@@ -211,10 +208,9 @@ public async Task<T> CallAsync<T>(
211208
}
212209

213210
/// <inheritdoc />
214-
protected override unsafe bool ReleaseHandle()
211+
public void Dispose()
215212
{
216-
Handle.Dispose();
217-
return true;
213+
handle.Dispose();
218214
}
219215
}
220216
}

src/Temporalio/Bridge/Worker.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ internal class Worker : IDisposable
1616
/// <summary>
1717
/// Initializes a new instance of the <see cref="Worker"/> class.
1818
/// </summary>
19-
/// <param name="client">Client for the worker.</param>
19+
/// <param name="runtime">Runtime for the worker.</param>
20+
/// <param name="clientHandle">Client handle for the worker.</param>
2021
/// <param name="namespace">Namespace for the worker.</param>
2122
/// <param name="options">Options for the worker.</param>
2223
/// <param name="loggerFactory">Logger factory, used instead of the one in options by
@@ -26,12 +27,13 @@ internal class Worker : IDisposable
2627
/// If any of the options are invalid including improperly defined workflows/activities.
2728
/// </exception>
2829
public Worker(
29-
Client client,
30+
Runtime runtime,
31+
SafeClientHandle clientHandle,
3032
string @namespace,
3133
Temporalio.Worker.TemporalWorkerOptions options,
3234
ILoggerFactory loggerFactory,
3335
IReadOnlyCollection<Temporalio.Client.ITemporalClientPlugin>? clientPlugins = null)
34-
: this(client.Runtime, CreateWorkerHandle(client, @namespace, options, loggerFactory, clientPlugins))
36+
: this(runtime, CreateWorkerHandle(runtime, clientHandle, @namespace, options, loggerFactory, clientPlugins))
3537
{
3638
}
3739

@@ -98,16 +100,16 @@ public async Task ValidateAsync()
98100
/// <summary>
99101
/// Replace the client.
100102
/// </summary>
101-
/// <param name="client">New client.</param>
102-
public void ReplaceClient(Client client)
103+
/// <param name="clientHandle">New client handle.</param>
104+
public void ReplaceClient(SafeClientHandle clientHandle)
103105
{
104106
using (var scope = new Scope())
105107
{
106108
unsafe
107109
{
108110
Interop.Methods.temporal_core_worker_replace_client(
109111
scope.Pointer(Handle),
110-
scope.Pointer(client.Handle));
112+
scope.Pointer(clientHandle));
111113
}
112114
}
113115
}
@@ -434,7 +436,8 @@ public void Dispose()
434436
}
435437

436438
private static unsafe SafeHandleReference<SafeWorkerHandle> CreateWorkerHandle(
437-
Client client,
439+
Runtime runtime,
440+
SafeClientHandle clientHandle,
438441
string @namespace,
439442
Temporalio.Worker.TemporalWorkerOptions options,
440443
ILoggerFactory loggerFactory,
@@ -443,13 +446,13 @@ private static unsafe SafeHandleReference<SafeWorkerHandle> CreateWorkerHandle(
443446
using Scope scope = new();
444447

445448
var workerOrFail = Interop.Methods.temporal_core_worker_new(
446-
scope.Pointer(client.Handle),
449+
scope.Pointer(clientHandle),
447450
scope.Pointer(options.ToInteropOptions(scope, @namespace, loggerFactory, clientPlugins)));
448451

449452
if (workerOrFail.fail != null)
450453
{
451454
string failStr;
452-
using (var byteArray = new ByteArray(client.Runtime, workerOrFail.fail))
455+
using (var byteArray = new ByteArray(runtime, workerOrFail.fail))
453456
{
454457
failStr = byteArray.ToUTF8();
455458
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Temporalio.Client
2+
{
3+
/// <summary>
4+
/// Internal interface that provides access to bridge client and runtime.
5+
/// </summary>
6+
internal interface IBridgeClientProviderInternal : IBridgeClientProvider
7+
{
8+
/// <summary>
9+
/// Gets the safe client handle for internal bridge use.
10+
/// </summary>
11+
Bridge.SafeClientHandle? ClientHandle { get; }
12+
13+
/// <summary>
14+
/// Gets the runtime associated with the client.
15+
/// </summary>
16+
Bridge.Runtime? Runtime { get; }
17+
}
18+
}

src/Temporalio/Client/TemporalConnection.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace Temporalio.Client
1818
/// <remarks>
1919
/// Connections are thread-safe and are encouraged to be reused.
2020
/// </remarks>
21-
public sealed class TemporalConnection : ITemporalConnection
21+
public sealed class TemporalConnection : ITemporalConnection, IBridgeClientProviderInternal
2222
{
2323
// Not set if not lazy
2424
private readonly SemaphoreSlim? semaphoreForLazyClient;
@@ -177,7 +177,13 @@ public string? ApiKey
177177
public bool IsConnected => client != null;
178178

179179
/// <inheritdoc />
180-
public SafeHandle? BridgeClient => client;
180+
public SafeHandle? BridgeClient => client?.Handle;
181+
182+
/// <inheritdoc />
183+
Bridge.SafeClientHandle? IBridgeClientProviderInternal.ClientHandle => client?.Handle;
184+
185+
/// <inheritdoc />
186+
Bridge.Runtime? IBridgeClientProviderInternal.Runtime => client?.Runtime;
181187

182188
/// <summary>
183189
/// Connect to Temporal.

src/Temporalio/Worker/TemporalWorker.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,15 @@ public TemporalWorker(IWorkerClient client, TemporalWorkerOptions options)
6161
// Ensure later accesses use the modified version of options.
6262
options = Options;
6363

64-
var bridgeClient = client.BridgeClientProvider.BridgeClient ??
65-
throw new InvalidOperationException("Cannot use unconnected lazy client for worker");
64+
// Get runtime and client handle from bridge client provider
65+
var bridgeProvider = client.BridgeClientProvider as Client.IBridgeClientProviderInternal
66+
?? throw new InvalidOperationException("Client does not support internal bridge access");
67+
var runtime = bridgeProvider.Runtime ?? Runtime.TemporalRuntime.Default.Runtime;
68+
var clientHandle = bridgeProvider.ClientHandle
69+
?? throw new InvalidOperationException("Cannot use unconnected lazy client for worker");
6670
BridgeWorker = new(
67-
(Bridge.Client)bridgeClient,
71+
runtime,
72+
clientHandle,
6873
client.Options.Namespace,
6974
options,
7075
loggerFactory,
@@ -181,11 +186,13 @@ public IWorkerClient Client
181186

182187
set
183188
{
184-
var bridgeClient = value.BridgeClientProvider.BridgeClient ??
185-
throw new InvalidOperationException("Cannot use unconnected lazy client for worker");
189+
var bridgeProvider = value.BridgeClientProvider as Client.IBridgeClientProviderInternal
190+
?? throw new InvalidOperationException("Client does not support internal bridge access");
191+
var clientHandle = bridgeProvider.ClientHandle
192+
?? throw new InvalidOperationException("Cannot use unconnected lazy client for worker");
186193
lock (clientLock)
187194
{
188-
BridgeWorker.ReplaceClient((Bridge.Client)bridgeClient);
195+
BridgeWorker.ReplaceClient(clientHandle);
189196
client = value;
190197
}
191198
}

0 commit comments

Comments
 (0)