Skip to content

Commit f2ba7dd

Browse files
authored
Reserve __temporal prefix (#410)
1 parent 2b97703 commit f2ba7dd

15 files changed

+145
-23
lines changed

.editorconfig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ dotnet_diagnostic.CA2237.severity = none
4747
# Warn on unused imports
4848
dotnet_diagnostic.IDE0005.severity = warning
4949

50+
# Don't warn on using var
51+
dotnet_diagnostic.IDE0008.severity = none
52+
5053
# Cannot use range operator on older versions
5154
dotnet_diagnostic.IDE0057.severity = none
5255

@@ -186,4 +189,4 @@ dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggest
186189
#Style - Pattern matching
187190

188191
#prefer pattern matching instead of is expression with type casts
189-
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
192+
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion

omnisharp.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
{
22
"FormattingOptions": {
33
"EnableEditorConfigSupport": true
4+
},
5+
"RoslynExtensionsOptions": {
6+
"enableAnalyzersSupport": true
47
}
58
}

src/Temporalio/Activities/ActivityDefinition.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Reflection;
55
using System.Runtime.ExceptionServices;
66
using System.Threading.Tasks;
7+
using Temporalio.Runtime;
78

89
namespace Temporalio.Activities
910
{
@@ -293,6 +294,11 @@ private static ActivityDefinition Create(
293294
Func<object?[], object?> invoker,
294295
MethodInfo? methodInfo)
295296
{
297+
if (name != null && name.StartsWith(TemporalRuntime.ReservedNamePrefix))
298+
{
299+
throw new ArgumentException(
300+
$"Activity name {name} cannot start with {TemporalRuntime.ReservedNamePrefix}");
301+
}
296302
// If there is a null name, which means dynamic, there must only be one parameter type
297303
// and it must be varargs IRawValue
298304
if (name == null && (
@@ -320,4 +326,4 @@ private static ActivityDefinition Create(
320326
return new(name, returnType, parameterTypes, requiredParameterCount, invoker, methodInfo);
321327
}
322328
}
323-
}
329+
}

src/Temporalio/Runtime/TemporalRuntime.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ namespace Temporalio.Runtime
1313
/// </remarks>
1414
public sealed class TemporalRuntime
1515
{
16+
/// <summary>
17+
/// Prefix for reserved handler and definition names.
18+
/// </summary>
19+
internal const string ReservedNamePrefix = "__temporal";
20+
1621
private static readonly Lazy<TemporalRuntime> LazyDefault =
1722
new(() => new TemporalRuntime(new TemporalRuntimeOptions()));
1823

src/Temporalio/Worker/ActivityWorker.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -722,4 +722,4 @@ public override void Heartbeat(HeartbeatInput input)
722722
}
723723
}
724724
}
725-
}
725+
}

src/Temporalio/Worker/TemporalWorkerOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,4 +424,4 @@ internal void OnTaskCompleted(WorkflowInstance instance, Exception? failureExcep
424424
}
425425
}
426426
}
427-
}
427+
}

src/Temporalio/Worker/WorkflowInstance.cs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using Temporalio.Common;
2121
using Temporalio.Converters;
2222
using Temporalio.Exceptions;
23+
using Temporalio.Runtime;
2324
using Temporalio.Worker.Interceptors;
2425
using Temporalio.Workflows;
2526

@@ -939,7 +940,11 @@ private Task ApplyDoUpdateAsync(DoUpdate update)
939940
var updates = mutableUpdates.IsValueCreated ? mutableUpdates.Value : Definition.Updates;
940941
if (!updates.TryGetValue(update.Name, out var updateDefn))
941942
{
942-
updateDefn = DynamicUpdate;
943+
// Do not fall back onto dynamic update if using the reserved prefix
944+
if (!update.Name.StartsWith(TemporalRuntime.ReservedNamePrefix))
945+
{
946+
updateDefn = DynamicUpdate;
947+
}
943948
if (updateDefn == null)
944949
{
945950
var knownUpdates = updates.Keys.OrderBy(k => k);
@@ -1136,26 +1141,27 @@ private void ApplyQueryWorkflow(QueryWorkflow query)
11361141
try
11371142
{
11381143
WorkflowQueryDefinition? queryDefn;
1139-
// If it's a stack trace query, create definition
1144+
object? resultObj;
1145+
11401146
if (query.QueryType == "__stack_trace")
11411147
{
1142-
Func<string> getter = GetStackTrace;
1143-
queryDefn = WorkflowQueryDefinition.CreateWithoutAttribute(
1144-
"__stack_trace", getter);
1148+
resultObj = GetStackTrace();
11451149
}
11461150
else if (query.QueryType == "__temporal_workflow_metadata")
11471151
{
1148-
Func<Api.Sdk.V1.WorkflowMetadata> getter = GetWorkflowMetadata;
1149-
queryDefn = WorkflowQueryDefinition.CreateWithoutAttribute(
1150-
"__temporal_workflow_metadata", getter);
1152+
resultObj = GetWorkflowMetadata();
11511153
}
11521154
else
11531155
{
11541156
// Find definition or fail
11551157
var queries = mutableQueries.IsValueCreated ? mutableQueries.Value : Definition.Queries;
11561158
if (!queries.TryGetValue(query.QueryType, out queryDefn))
11571159
{
1158-
queryDefn = DynamicQuery;
1160+
// Do not fall back onto dynamic query if using the reserved prefix
1161+
if (!query.QueryType.StartsWith(TemporalRuntime.ReservedNamePrefix))
1162+
{
1163+
queryDefn = DynamicQuery;
1164+
}
11591165
if (queryDefn == null)
11601166
{
11611167
var knownQueries = queries.Keys.OrderBy(k => k);
@@ -1164,8 +1170,7 @@ private void ApplyQueryWorkflow(QueryWorkflow query)
11641170
$"known queries: [{string.Join(" ", knownQueries)}]");
11651171
}
11661172
}
1167-
}
1168-
var resultObj = inbound.Value.HandleQuery(new(
1173+
resultObj = inbound.Value.HandleQuery(new(
11691174
Id: query.QueryId,
11701175
Query: query.QueryType,
11711176
Definition: queryDefn,
@@ -1176,6 +1181,7 @@ private void ApplyQueryWorkflow(QueryWorkflow query)
11761181
dynamic: queryDefn.Dynamic,
11771182
dynamicArgPrepend: query.QueryType),
11781183
Headers: query.Headers));
1184+
}
11791185
AddCommand(new()
11801186
{
11811187
RespondToQuery = new()
@@ -1267,7 +1273,11 @@ private void ApplySignalWorkflow(SignalWorkflow signal)
12671273
var signals = mutableSignals.IsValueCreated ? mutableSignals.Value : Definition.Signals;
12681274
if (!signals.TryGetValue(signal.SignalName, out var signalDefn))
12691275
{
1270-
signalDefn = DynamicSignal;
1276+
// Do not fall back onto dynamic signal if using the reserved prefix
1277+
if (!signal.SignalName.StartsWith(TemporalRuntime.ReservedNamePrefix))
1278+
{
1279+
signalDefn = DynamicSignal;
1280+
}
12711281
if (signalDefn == null)
12721282
{
12731283
// No definition found, buffer

src/Temporalio/Workflows/Workflow.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1339,4 +1339,4 @@ public static class Unsafe
13391339
public static bool IsReplaying => Context.IsReplaying;
13401340
}
13411341
}
1342-
}
1342+
}

src/Temporalio/Workflows/WorkflowDefinition.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Linq;
55
using System.Reflection;
66
using System.Threading.Tasks;
7+
using Temporalio.Runtime;
78

89
namespace Temporalio.Workflows
910
{
@@ -427,6 +428,12 @@ public static WorkflowDefinition Create(
427428
}
428429
}
429430

431+
// Verify that registered names to not use our reserved prefix
432+
if (name != null && name.StartsWith(TemporalRuntime.ReservedNamePrefix))
433+
{
434+
errs.Add($"Workflow name {name} cannot start with {TemporalRuntime.ReservedNamePrefix}");
435+
}
436+
430437
// If there are any errors, throw
431438
if (errs.Count > 0)
432439
{
@@ -525,4 +532,4 @@ private static bool IsDefinedOnBase<T>(MethodInfo method)
525532
}
526533
}
527534
}
528-
}
535+
}

src/Temporalio/Workflows/WorkflowQueryDefinition.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
22
using System.Collections.Concurrent;
3+
using System.Linq;
34
using System.Reflection;
45
using System.Threading.Tasks;
6+
using Temporalio.Runtime;
57

68
namespace Temporalio.Workflows
79
{
@@ -10,11 +12,26 @@ namespace Temporalio.Workflows
1012
/// </summary>
1113
public class WorkflowQueryDefinition
1214
{
15+
private static readonly string[] ReservedQueryHandlerPrefixes =
16+
{
17+
TemporalRuntime.ReservedNamePrefix,
18+
"__stack_trace",
19+
"__enhanced_stack_trace",
20+
};
21+
1322
private static readonly ConcurrentDictionary<MethodInfo, WorkflowQueryDefinition> MethodDefinitions = new();
1423
private static readonly ConcurrentDictionary<PropertyInfo, WorkflowQueryDefinition> PropertyDefinitions = new();
1524

1625
private WorkflowQueryDefinition(string? name, string? description, MethodInfo? method, Delegate? del)
1726
{
27+
if (name != null)
28+
{
29+
var reservedQ = ReservedQueryHandlerPrefixes.FirstOrDefault(p => name.StartsWith(p));
30+
if (!string.IsNullOrEmpty(reservedQ))
31+
{
32+
throw new ArgumentException($"Query handler name {name} cannot start with {reservedQ}");
33+
}
34+
}
1835
Name = name;
1936
Description = description;
2037
Method = method;
@@ -168,4 +185,4 @@ private static void AssertValid(MethodInfo method, bool dynamic)
168185
}
169186
}
170187
}
171-
}
188+
}

0 commit comments

Comments
 (0)