Skip to content

Commit 668f66a

Browse files
committed
Fix
1 parent 43a6b90 commit 668f66a

File tree

4 files changed

+54
-69
lines changed

4 files changed

+54
-69
lines changed

src/BuiltInTools/HotReloadClient/DefaultHotReloadClient.cs

Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,6 @@ internal sealed class DefaultHotReloadClient(ILogger logger, ILogger agentLogger
2828
private NamedPipeServerStream? _pipe;
2929
private bool _managedCodeUpdateFailedOrCancelled;
3030

31-
private int _updateBatchId;
32-
33-
/// <summary>
34-
/// Updates that were sent over to the agent while the process has been suspended.
35-
/// </summary>
36-
private readonly object _pendingUpdatesGate = new();
37-
private Task _pendingUpdates = Task.CompletedTask;
38-
3931
public override void Dispose()
4032
{
4133
DisposePipe();
@@ -48,10 +40,6 @@ private void DisposePipe()
4840
_pipe = null;
4941
}
5042

51-
// for testing
52-
internal Task PendingUpdates
53-
=> _pendingUpdates;
54-
5543
// for testing
5644
internal string NamedPipeName
5745
=> _namedPipeName;
@@ -225,31 +213,17 @@ public async override Task<ApplyStatus> ApplyStaticAssetUpdatesAsync(ImmutableAr
225213
(appliedUpdateCount < updates.Length) ? ApplyStatus.SomeChangesApplied : ApplyStatus.AllChangesApplied;
226214
}
227215

228-
private async ValueTask<bool> SendAndReceiveUpdateAsync<TRequest>(TRequest request, bool isProcessSuspended, CancellationToken cancellationToken)
216+
private ValueTask<bool> SendAndReceiveUpdateAsync<TRequest>(TRequest request, bool isProcessSuspended, CancellationToken cancellationToken)
229217
where TRequest : IUpdateRequest
230218
{
231219
// Should not be disposed:
232220
Debug.Assert(_pipe != null);
233221

234-
var batchId = _updateBatchId++;
235-
236-
if (!isProcessSuspended)
237-
{
238-
return await SendAndReceiveAsync(batchId, cancellationToken);
239-
}
240-
241-
lock (_pendingUpdatesGate)
242-
{
243-
var previous = _pendingUpdates;
244-
245-
_pendingUpdates = Task.Run(async () =>
246-
{
247-
await previous;
248-
await SendAndReceiveAsync(batchId, cancellationToken);
249-
}, cancellationToken);
250-
}
251-
252-
return true;
222+
return SendAndReceiveUpdateAsync(
223+
send: SendAndReceiveAsync,
224+
isProcessSuspended,
225+
suspendedResult: true,
226+
cancellationToken);
253227

254228
async ValueTask<bool> SendAndReceiveAsync(int batchId, CancellationToken cancellationToken)
255229
{

src/BuiltInTools/HotReloadClient/HotReloadClient.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ internal abstract class HotReloadClient(ILogger logger, ILogger agentLogger) : I
2424
public readonly ILogger Logger = logger;
2525
public readonly ILogger AgentLogger = agentLogger;
2626

27+
private int _updateBatchId;
28+
29+
/// <summary>
30+
/// Updates that were sent over to the agent while the process has been suspended.
31+
/// </summary>
32+
private readonly object _pendingUpdatesGate = new();
33+
private Task _pendingUpdates = Task.CompletedTask;
34+
35+
// for testing
36+
internal Task PendingUpdates
37+
=> _pendingUpdates;
38+
2739
public abstract void ConfigureLaunchEnvironment(IDictionary<string, string> environmentBuilder);
2840

2941
/// <summary>
@@ -86,4 +98,34 @@ public async Task<IReadOnlyList<HotReloadManagedCodeUpdate>> FilterApplicableUpd
8698

8799
return applicableUpdates;
88100
}
101+
102+
protected async ValueTask<TResult> SendAndReceiveUpdateAsync<TResult>(
103+
Func<int, CancellationToken, ValueTask<TResult>> send,
104+
bool isProcessSuspended,
105+
TResult suspendedResult,
106+
CancellationToken cancellationToken)
107+
where TResult : struct
108+
{
109+
var batchId = _updateBatchId++;
110+
111+
Task previous;
112+
lock (_pendingUpdatesGate)
113+
{
114+
previous = _pendingUpdates;
115+
116+
if (isProcessSuspended)
117+
{
118+
_pendingUpdates = Task.Run(async () =>
119+
{
120+
await previous;
121+
_ = await send(batchId, cancellationToken);
122+
}, cancellationToken);
123+
124+
return suspendedResult;
125+
}
126+
}
127+
128+
await previous;
129+
return await send(batchId, cancellationToken);
130+
}
89131
}

src/BuiltInTools/HotReloadClient/Utilities/EnvironmentUtilities.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ internal static class EnvironmentUtilities
1212
{
1313
public static void InsertListItem(this IDictionary<string, string> environment, string key, string value, char separator)
1414
{
15-
if (!environment.TryGetValue(key, out var existingValue))
15+
if (!environment.TryGetValue(key, out var existingValue) || existingValue is "")
1616
{
1717
environment[key] = value;
1818
}

src/BuiltInTools/HotReloadClient/Web/WebAssemblyHotReloadClient.cs

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,6 @@ internal sealed class WebAssemblyHotReloadClient(
3737
private static readonly ImmutableArray<string> s_defaultCapabilities90 =
3838
s_defaultCapabilities80;
3939

40-
private int _updateBatchId;
41-
42-
/// <summary>
43-
/// Updates that were sent over to the agent while the process has been suspended.
44-
/// </summary>
45-
private readonly object _pendingUpdatesGate = new();
46-
private Task _pendingUpdates = Task.CompletedTask;
47-
4840
private readonly ImmutableArray<string> _capabilities = GetUpdateCapabilities(logger, projectHotReloadCapabilities, projectTargetFrameworkVersion);
4941

5042
private static ImmutableArray<string> GetUpdateCapabilities(ILogger logger, ImmutableArray<string> projectHotReloadCapabilities, Version projectTargetFrameworkVersion)
@@ -77,10 +69,6 @@ public override void Dispose()
7769
// Do nothing.
7870
}
7971

80-
// for testing
81-
internal Task PendingUpdates
82-
=> _pendingUpdates;
83-
8472
public override void ConfigureLaunchEnvironment(IDictionary<string, string> environmentBuilder)
8573
{
8674
// the environment is configued via browser refesh server
@@ -123,7 +111,11 @@ public override async Task<ApplyStatus> ApplyManagedCodeUpdatesAsync(ImmutableAr
123111

124112
var loggingLevel = Logger.IsEnabled(LogLevel.Debug) ? ResponseLoggingLevel.Verbose : ResponseLoggingLevel.WarningsAndErrors;
125113

126-
var (anySuccess, anyFailure) = await SendAndReceiveUpdateAsync(deltas, loggingLevel, isProcessSuspended, cancellationToken);
114+
var (anySuccess, anyFailure) = await SendAndReceiveUpdateAsync(
115+
send: SendAndReceiveAsync,
116+
isProcessSuspended,
117+
suspendedResult: (anySuccess: true, anyFailure: false),
118+
cancellationToken);
127119

128120
// If no browser is connected we assume the changes have been applied.
129121
// If at least one browser suceeds we consider the changes successfully applied.
@@ -132,29 +124,6 @@ public override async Task<ApplyStatus> ApplyManagedCodeUpdatesAsync(ImmutableAr
132124
// Currently the changes are remembered on the dev server and sent over there from the browser.
133125
// If no browser is connected the changes are not sent though.
134126
return (!anySuccess && anyFailure) ? ApplyStatus.Failed : (applicableUpdates.Count < updates.Length) ? ApplyStatus.SomeChangesApplied : ApplyStatus.AllChangesApplied;
135-
}
136-
137-
private async ValueTask<(bool anySuccess, bool anyFailure)> SendAndReceiveUpdateAsync(JsonDelta[] deltas, ResponseLoggingLevel loggingLevel, bool isProcessSuspended, CancellationToken cancellationToken)
138-
{
139-
var batchId = _updateBatchId++;
140-
141-
if (!isProcessSuspended)
142-
{
143-
return await SendAndReceiveAsync(batchId, cancellationToken);
144-
}
145-
146-
lock (_pendingUpdatesGate)
147-
{
148-
var previous = _pendingUpdates;
149-
150-
_pendingUpdates = Task.Run(async () =>
151-
{
152-
await previous;
153-
await SendAndReceiveAsync(batchId, cancellationToken);
154-
}, cancellationToken);
155-
}
156-
157-
return (anySuccess: true, anyFailure: false);
158127

159128
async ValueTask<(bool anySuccess, bool anyFailure)> SendAndReceiveAsync(int batchId, CancellationToken cancellationToken)
160129
{

0 commit comments

Comments
 (0)