Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
51d492c
Env config
THardy98 Aug 12, 2025
5665732
remove merge conflicts
THardy98 Aug 26, 2025
b7536f2
feat: Update bridge integration to use new synchronous C API
THardy98 Sep 12, 2025
e22dde7
Convert ClientConfig classes to records and improve immutability
THardy98 Sep 12, 2025
baf24c0
Remove CLAUDE files
THardy98 Sep 15, 2025
535b8a0
Remove useless disableFile parameter when loading ClientConfig. Parse…
THardy98 Sep 15, 2025
8c80846
Tests formatting
THardy98 Sep 16, 2025
3284607
Address most PR feedback
THardy98 Sep 16, 2025
58f06b7
Use scope.ByteArray in favor of sbyte*
THardy98 Sep 17, 2025
049b3d0
Deserialize JSON from core using JSON DTO objects
THardy98 Sep 17, 2025
8ba428c
Clean up - renaming and using shorthand returns
THardy98 Sep 17, 2025
33aadd9
Use renamed core methods with Env prefix before Config. Use tri-state…
THardy98 Sep 19, 2025
05d7cf6
Rename ConfigProfile -> Profile, with suppression of build warning
THardy98 Sep 19, 2025
28eb602
TlsRecord & ProfileRecord removed, in favor of to/fromDictionary meth…
THardy98 Sep 19, 2025
9afb69b
Make to/from dictionary conversion non-null. Minor style improvements
THardy98 Sep 22, 2025
0cb850b
Remove runtime usage
THardy98 Sep 22, 2025
99ca3e8
Update submodule with merged commit
THardy98 Sep 22, 2025
4a621e1
Merge branch 'main' into env_config
THardy98 Sep 22, 2025
dd51f40
Formatting
THardy98 Sep 22, 2025
a8b4305
Fix interop conflicts
THardy98 Sep 22, 2025
f563daa
update test file paths for windows
THardy98 Sep 22, 2025
28a93d8
Merge branch 'main' into env_config
THardy98 Sep 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,003 changes: 4,003 additions & 0 deletions src/Temporalio/Bridge/Cargo.lock

Large diffs are not rendered by default.

416 changes: 416 additions & 0 deletions src/Temporalio/Bridge/EnvConfig.cs

Large diffs are not rendered by default.

57 changes: 38 additions & 19 deletions src/Temporalio/Bridge/Interop/Interop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

namespace Temporalio.Bridge.Interop
{
internal enum TemporalCoreForwardedLogLevel
[NativeTypeName("unsigned int")]
internal enum TemporalCoreForwardedLogLevel : uint
{
Trace = 0,
Debug,
Expand All @@ -12,15 +13,17 @@ internal enum TemporalCoreForwardedLogLevel
Error,
}

internal enum TemporalCoreMetricAttributeValueType
[NativeTypeName("unsigned int")]
internal enum TemporalCoreMetricAttributeValueType : uint
{
String = 1,
Int,
Float,
Bool,
}

internal enum TemporalCoreMetricKind
[NativeTypeName("unsigned int")]
internal enum TemporalCoreMetricKind : uint
{
CounterInteger = 1,
HistogramInteger,
Expand All @@ -30,19 +33,22 @@ internal enum TemporalCoreMetricKind
GaugeFloat,
}

internal enum TemporalCoreOpenTelemetryMetricTemporality
[NativeTypeName("unsigned int")]
internal enum TemporalCoreOpenTelemetryMetricTemporality : uint
{
Cumulative = 1,
Delta,
}

internal enum TemporalCoreOpenTelemetryProtocol
[NativeTypeName("unsigned int")]
internal enum TemporalCoreOpenTelemetryProtocol : uint
{
Grpc = 1,
Http,
}

internal enum TemporalCoreRpcService
[NativeTypeName("unsigned int")]
internal enum TemporalCoreRpcService : uint
{
Workflow = 1,
Operator,
Expand All @@ -51,7 +57,8 @@ internal enum TemporalCoreRpcService
Health,
}

internal enum TemporalCoreSlotKindType
[NativeTypeName("unsigned int")]
internal enum TemporalCoreSlotKindType : uint
{
WorkflowSlotKindType,
ActivitySlotKindType,
Expand Down Expand Up @@ -275,6 +282,9 @@ internal unsafe partial struct TemporalCoreRpcCallOptions
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal unsafe delegate void TemporalCoreClientRpcCallCallback(void* user_data, [NativeTypeName("const struct TemporalCoreByteArray *")] TemporalCoreByteArray* success, [NativeTypeName("uint32_t")] uint status_code, [NativeTypeName("const struct TemporalCoreByteArray *")] TemporalCoreByteArray* failure_message, [NativeTypeName("const struct TemporalCoreByteArray *")] TemporalCoreByteArray* failure_details);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal unsafe delegate void TemporalCoreClientConfigCallback(void* user_data, [NativeTypeName("const struct TemporalCoreByteArray *")] TemporalCoreByteArray* success, [NativeTypeName("const struct TemporalCoreByteArray *")] TemporalCoreByteArray* fail);

[StructLayout(LayoutKind.Explicit)]
internal partial struct TemporalCoreMetricAttributeValue
{
Expand Down Expand Up @@ -615,7 +625,8 @@ internal partial struct TemporalCoreLegacyBuildIdBasedStrategy
public TemporalCoreByteArrayRef build_id;
}

internal enum TemporalCoreWorkerVersioningStrategy_Tag
[NativeTypeName("unsigned int")]
internal enum TemporalCoreWorkerVersioningStrategy_Tag : uint
{
None,
DeploymentBased,
Expand All @@ -626,7 +637,7 @@ internal unsafe partial struct TemporalCoreWorkerVersioningStrategy
{
public TemporalCoreWorkerVersioningStrategy_Tag tag;

[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L491_C3")]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L431_C3")]
public _Anonymous_e__Union Anonymous;

internal ref TemporalCoreWorkerVersioningNone none
Expand Down Expand Up @@ -666,15 +677,15 @@ internal ref TemporalCoreLegacyBuildIdBasedStrategy legacy_build_id_based
internal unsafe partial struct _Anonymous_e__Union
{
[FieldOffset(0)]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L492_C5")]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L432_C5")]
public _Anonymous1_1_e__Struct Anonymous1_1;

[FieldOffset(0)]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L495_C5")]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L435_C5")]
public _Anonymous2_1_e__Struct Anonymous2_1;

[FieldOffset(0)]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L498_C5")]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L438_C5")]
public _Anonymous3_1_e__Struct Anonymous3_1;

internal partial struct _Anonymous1_1_e__Struct
Expand Down Expand Up @@ -755,7 +766,8 @@ internal unsafe partial struct TemporalCoreSlotReserveCtx
[return: NativeTypeName("uintptr_t")]
internal unsafe delegate UIntPtr TemporalCoreCustomTryReserveSlotCallback([NativeTypeName("const struct TemporalCoreSlotReserveCtx *")] TemporalCoreSlotReserveCtx* ctx);

internal enum TemporalCoreSlotInfo_Tag
[NativeTypeName("unsigned int")]
internal enum TemporalCoreSlotInfo_Tag : uint
{
WorkflowSlotInfo,
ActivitySlotInfo,
Expand Down Expand Up @@ -797,7 +809,7 @@ internal unsafe partial struct TemporalCoreSlotInfo
{
public TemporalCoreSlotInfo_Tag tag;

[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L566_C3")]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L506_C3")]
public _Anonymous_e__Union Anonymous;

internal ref TemporalCoreWorkflowSlotInfo_Body workflow_slot_info
Expand Down Expand Up @@ -915,7 +927,8 @@ internal unsafe partial struct TemporalCoreCustomSlotSupplierCallbacksImpl
public TemporalCoreCustomSlotSupplierCallbacks* _0;
}

internal enum TemporalCoreSlotSupplier_Tag
[NativeTypeName("unsigned int")]
internal enum TemporalCoreSlotSupplier_Tag : uint
{
FixedSize,
ResourceBased,
Expand All @@ -926,7 +939,7 @@ internal unsafe partial struct TemporalCoreSlotSupplier
{
public TemporalCoreSlotSupplier_Tag tag;

[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L617_C3")]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L557_C3")]
public _Anonymous_e__Union Anonymous;

internal ref TemporalCoreFixedSizeSlotSupplier fixed_size
Expand Down Expand Up @@ -966,15 +979,15 @@ internal ref TemporalCoreCustomSlotSupplierCallbacksImpl custom
internal unsafe partial struct _Anonymous_e__Union
{
[FieldOffset(0)]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L618_C5")]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L558_C5")]
public _Anonymous1_1_e__Struct Anonymous1_1;

[FieldOffset(0)]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L621_C5")]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L561_C5")]
public _Anonymous2_1_e__Struct Anonymous2_1;

[FieldOffset(0)]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L624_C5")]
[NativeTypeName("__AnonymousRecord_temporal-sdk-core-c-bridge_L564_C5")]
public _Anonymous3_1_e__Struct Anonymous3_1;

internal partial struct _Anonymous1_1_e__Struct
Expand Down Expand Up @@ -1169,6 +1182,12 @@ internal static unsafe partial class Methods
[DllImport("temporal_sdk_core_c_bridge", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void temporal_core_client_rpc_call([NativeTypeName("struct TemporalCoreClient *")] TemporalCoreClient* client, [NativeTypeName("const struct TemporalCoreRpcCallOptions *")] TemporalCoreRpcCallOptions* options, void* user_data, [NativeTypeName("TemporalCoreClientRpcCallCallback")] IntPtr callback);

[DllImport("temporal_sdk_core_c_bridge", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void temporal_core_client_config_load([NativeTypeName("const char *")] sbyte* path, [NativeTypeName("struct TemporalCoreByteArrayRef")] TemporalCoreByteArrayRef data, [NativeTypeName("bool")] byte disable_file, [NativeTypeName("bool")] byte config_file_strict, [NativeTypeName("struct TemporalCoreByteArrayRef")] TemporalCoreByteArrayRef env_vars, void* user_data, [NativeTypeName("TemporalCoreClientConfigCallback")] IntPtr callback);

[DllImport("temporal_sdk_core_c_bridge", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void temporal_core_client_config_profile_load([NativeTypeName("const char *")] sbyte* profile, [NativeTypeName("const char *")] sbyte* path, [NativeTypeName("struct TemporalCoreByteArrayRef")] TemporalCoreByteArrayRef data, [NativeTypeName("bool")] byte disable_file, [NativeTypeName("bool")] byte disable_env, [NativeTypeName("bool")] byte config_file_strict, [NativeTypeName("struct TemporalCoreByteArrayRef")] TemporalCoreByteArrayRef env_vars, void* user_data, [NativeTypeName("TemporalCoreClientConfigCallback")] IntPtr callback);

[DllImport("temporal_sdk_core_c_bridge", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: NativeTypeName("struct TemporalCoreMetricMeter *")]
public static extern TemporalCoreMetricMeter* temporal_core_metric_meter_new([NativeTypeName("struct TemporalCoreRuntime *")] TemporalCoreRuntime* runtime);
Expand Down
2 changes: 1 addition & 1 deletion src/Temporalio/Bridge/sdk-core
124 changes: 124 additions & 0 deletions src/Temporalio/Client/Configuration/ClientConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
using System.Linq;

Check failure on line 3 in src/Temporalio/Client/Configuration/ClientConfig.cs

View workflow job for this annotation

GitHub Actions / build-lint-test (windows-latest)

Using directive is unnecessary.

Check failure on line 3 in src/Temporalio/Client/Configuration/ClientConfig.cs

View workflow job for this annotation

GitHub Actions / build-lint-test (windows-latest)

Using directive is unnecessary.

Check failure on line 3 in src/Temporalio/Client/Configuration/ClientConfig.cs

View workflow job for this annotation

GitHub Actions / build-lint-test (windows-latest)

Using directive is unnecessary.
using System.Text.Json;

namespace Temporalio.Client.Configuration
Comment thread
THardy98 marked this conversation as resolved.
Outdated
{
/// <summary>
/// Represents the overall client configuration.
/// </summary>
public sealed class ClientConfig : ICloneable
Comment thread
THardy98 marked this conversation as resolved.
Outdated
{
/// <summary>
/// Initializes a new instance of the <see cref="ClientConfig"/> class.
/// </summary>
/// <param name="profiles">The configuration profiles.</param>
public ClientConfig(IReadOnlyDictionary<string, ClientConfigProfile> profiles)
{
Profiles = profiles ?? new Dictionary<string, ClientConfigProfile>();
}

/// <summary>
/// Gets the configuration profiles.
/// </summary>
public IReadOnlyDictionary<string, ClientConfigProfile> Profiles { get; private set; }
Comment thread
THardy98 marked this conversation as resolved.
Outdated

/// <summary>
/// Load client configuration from environment variables and configuration files.
/// </summary>
/// <param name="configSource">The data source to load from.</param>
/// <param name="disableFile">If true, do not load from file (only from environment).</param>
/// <param name="configFileStrict">If true, fail if configuration file is invalid.</param>
/// <param name="overrideEnvVars">Environment variables to use, or null to use system environment.</param>
/// <returns>Loaded configuration data.</returns>
public static ClientConfig Load(
DataSource? configSource = null,
bool disableFile = false,
bool configFileStrict = false,
Dictionary<string, string>? overrideEnvVars = null)
Comment thread
THardy98 marked this conversation as resolved.
Outdated
{
var runtime = Runtime.TemporalRuntime.Default.Runtime;
var profiles = Bridge.EnvConfig.LoadClientConfig(
runtime,
configSource ?? DataSource.FromDefault(),
disableFile,
configFileStrict,
overrideEnvVars);
return new ClientConfig(profiles);
}

/// <summary>
/// Load client connection options directly from configuration.
/// </summary>
/// <param name="profile">Name of the profile to load. If null, "default" is used.</param>
/// <param name="configSource">The data source to load from.</param>
/// <param name="disableFile">If true, do not load from file (only from environment).</param>
/// <param name="disableEnv">If true, disable environment variable overrides.</param>
/// <param name="configFileStrict">If true, fail if configuration file is invalid.</param>
/// <param name="overrideEnvVars">Environment variables to use, or null to use system environment.</param>
/// <returns>Client connection options.</returns>
public static TemporalClientConnectOptions LoadClientConnectOptions(
string? profile = null,
DataSource? configSource = null,
bool disableFile = false,
bool disableEnv = false,
bool configFileStrict = false,
Dictionary<string, string>? overrideEnvVars = null)
{
var profileName = profile ?? "default";
var clientProfile = ClientConfigProfile.Load(
profileName,
configSource,
disableFile,
disableEnv,
configFileStrict,
overrideEnvVars);
return clientProfile.ToConnectionOptions();
}

/// <summary>
/// Deserialize client configuration from JSON.
/// </summary>
/// <param name="json">JSON string to deserialize.</param>
/// <param name="options">Optional JSON serializer options.</param>
/// <returns>Client configuration instance.</returns>
public static ClientConfig FromJson(string json, JsonSerializerOptions? options = null)
Comment thread
THardy98 marked this conversation as resolved.
Outdated
{
return JsonSerializer.Deserialize<ClientConfig>(json, options ?? GetDefaultJsonOptions())
?? throw new JsonException("Failed to deserialize ClientConfig from JSON.");
}

/// <summary>
/// Serialize this client configuration to JSON.
/// </summary>
/// <param name="options">Optional JSON serializer options.</param>
/// <returns>JSON string representation.</returns>
public string ToJson(JsonSerializerOptions? options = null)
{
return JsonSerializer.Serialize(this, options ?? GetDefaultJsonOptions());
}
Comment thread
THardy98 marked this conversation as resolved.
Outdated

/// <inheritdoc />
public object Clone()
{
var newConfig = (ClientConfig)MemberwiseClone();
var clonedProfiles = new Dictionary<string, ClientConfigProfile>();
foreach (var kvp in Profiles)
{
clonedProfiles[kvp.Key] = (ClientConfigProfile)kvp.Value.Clone();
}
newConfig.Profiles = clonedProfiles;
return newConfig;
}

private static JsonSerializerOptions GetDefaultJsonOptions()
Comment thread
THardy98 marked this conversation as resolved.
Outdated
{
return new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true,
};
}
}
}
Loading
Loading