Skip to content

Commit 6278e51

Browse files
committed
refactor(Spanner): Calculating ProcessId for RequestId is lightly more efficient.
1 parent c3b5a40 commit 6278e51

File tree

1 file changed

+26
-28
lines changed

1 file changed

+26
-28
lines changed

apis/Google.Cloud.Spanner.V1/Google.Cloud.Spanner.V1/SpannerClientPartial.ProcessId.cs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,46 +21,44 @@ namespace Google.Cloud.Spanner.V1;
2121
public partial class SpannerClientImpl
2222
{
2323
/// <summary>
24-
/// The process ID.
24+
/// The process ID. Can be set only once and before any Spanner request has been executed.
2525
/// </summary>
2626
/// <exception cref="InvalidOperationException">The process ID has already been set.</exception>
2727
internal static ulong ProcessId
2828
{
29-
set => ProcessIdSource.Set(value);
30-
}
31-
32-
private static class ProcessIdSource
33-
{
34-
private static string s_value;
35-
internal static string Value
29+
set
3630
{
37-
get
31+
if (!ProcessIdSource.TrySetProcessId(value))
3832
{
39-
// If not set, attempt to set it with a new random value.
40-
// (It's okay if multiple threads generate a value; only the first one wins).
41-
if (s_value == null)
42-
{
43-
Interlocked.CompareExchange(ref s_value, GenerateId(), null);
44-
}
45-
return s_value;
33+
throw new InvalidOperationException("The Process ID was already set and cannot be overwritten now.");
4634
}
4735
}
36+
}
4837

49-
internal static void Set(ulong id)
38+
private static class ProcessIdSource
39+
{
40+
private static string s_explicitvalue;
41+
private static readonly Lazy<string> ProcessIdCache = new Lazy<string>(ProcessIdUncached, LazyThreadSafetyMode.ExecutionAndPublication);
42+
43+
internal static string Value => ProcessIdCache.Value;
44+
45+
internal static bool TrySetProcessId(ulong id) =>
46+
Interlocked.CompareExchange(ref s_explicitvalue, id.ToString(), null) != null;
47+
48+
private static string ProcessIdUncached()
5049
{
51-
// Atomically set the value. If it was already set (i.e. returns non-null), throw.
52-
if (Interlocked.CompareExchange(ref s_value, id.ToString(), null) != null)
50+
// ProcessId had not been explicitly set, we need to generate one.
51+
// And it's perfectly fine that we left it set to zero,
52+
// that's enough to make it fail if someone tries to change it,
53+
// and we won't use that value anymore.
54+
if (TrySetProcessId(0))
5355
{
54-
throw new InvalidOperationException("The Process ID was already set and cannot be overwritten now.");
56+
var random = new Random();
57+
var buffer = new byte[sizeof(ulong)];
58+
random.NextBytes(buffer);
59+
return BitConverter.ToUInt64(buffer, 0).ToString();
5560
}
56-
}
57-
58-
private static string GenerateId()
59-
{
60-
var random = new Random();
61-
var buffer = new byte[sizeof(ulong)];
62-
random.NextBytes(buffer);
63-
return BitConverter.ToUInt64(buffer, 0).ToString();
61+
return s_explicitvalue;
6462
}
6563
}
6664
}

0 commit comments

Comments
 (0)