Skip to content

Commit 5afd747

Browse files
feat: removed external dependencies (VPN, mutagen) connection management (#111)
Closes: #68 --------- Co-authored-by: Dean Sheather <dean@deansheather.com>
1 parent 22c9bcd commit 5afd747

File tree

6 files changed

+62
-22
lines changed

6 files changed

+62
-22
lines changed

App/App.xaml.cs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,20 +165,22 @@ protected override void OnLaunched(LaunchActivatedEventArgs args)
165165
}, CancellationToken.None);
166166

167167
// Initialize file sync.
168-
var syncSessionCts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
169-
var syncSessionController = _services.GetRequiredService<ISyncSessionController>();
170-
_ = syncSessionController.RefreshState(syncSessionCts.Token).ContinueWith(t =>
171-
{
172-
if (t.IsCanceled || t.Exception != null)
173-
{
174-
_logger.LogError(t.Exception, "failed to refresh sync state (canceled = {canceled})", t.IsCanceled);
175-
#if DEBUG
176-
Debugger.Break();
177-
#endif
178-
}
168+
// We're adding a 5s delay here to avoid race conditions when loading the mutagen binary.
179169

180-
syncSessionCts.Dispose();
181-
}, CancellationToken.None);
170+
_ = Task.Delay(5000).ContinueWith((_) =>
171+
{
172+
var syncSessionCts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
173+
var syncSessionController = _services.GetRequiredService<ISyncSessionController>();
174+
syncSessionController.RefreshState(syncSessionCts.Token).ContinueWith(
175+
t =>
176+
{
177+
if (t.IsCanceled || t.Exception != null)
178+
{
179+
_logger.LogError(t.Exception, "failed to refresh sync state (canceled = {canceled})", t.IsCanceled);
180+
}
181+
syncSessionCts.Dispose();
182+
}, CancellationToken.None);
183+
});
182184

183185
// Prevent the TrayWindow from closing, just hide it.
184186
var trayWindow = _services.GetRequiredService<TrayWindow>();

App/Services/RpcController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ private void SpeakerOnError(Exception e)
313313
Debug.WriteLine($"Error: {e}");
314314
try
315315
{
316-
Reconnect(CancellationToken.None).Wait();
316+
using var _ = Reconnect(CancellationToken.None);
317317
}
318318
catch
319319
{

App/ViewModels/FileSyncListViewModel.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,9 @@ public void Initialize(Window window, DispatcherQueue dispatcherQueue)
143143

144144
var rpcModel = _rpcController.GetState();
145145
var credentialModel = _credentialManager.GetCachedCredentials();
146-
MaybeSetUnavailableMessage(rpcModel, credentialModel);
147146
var syncSessionState = _syncSessionController.GetState();
148147
UpdateSyncSessionState(syncSessionState);
148+
MaybeSetUnavailableMessage(rpcModel, credentialModel, syncSessionState);
149149
}
150150

151151
private void RpcControllerStateChanged(object? sender, RpcModel rpcModel)
@@ -159,7 +159,8 @@ private void RpcControllerStateChanged(object? sender, RpcModel rpcModel)
159159
}
160160

161161
var credentialModel = _credentialManager.GetCachedCredentials();
162-
MaybeSetUnavailableMessage(rpcModel, credentialModel);
162+
var syncSessionState = _syncSessionController.GetState();
163+
MaybeSetUnavailableMessage(rpcModel, credentialModel, syncSessionState);
163164
}
164165

165166
private void CredentialManagerCredentialsChanged(object? sender, CredentialModel credentialModel)
@@ -173,7 +174,8 @@ private void CredentialManagerCredentialsChanged(object? sender, CredentialModel
173174
}
174175

175176
var rpcModel = _rpcController.GetState();
176-
MaybeSetUnavailableMessage(rpcModel, credentialModel);
177+
var syncSessionState = _syncSessionController.GetState();
178+
MaybeSetUnavailableMessage(rpcModel, credentialModel, syncSessionState);
177179
}
178180

179181
private void SyncSessionStateChanged(object? sender, SyncSessionControllerStateModel syncSessionState)
@@ -189,7 +191,7 @@ private void SyncSessionStateChanged(object? sender, SyncSessionControllerStateM
189191
UpdateSyncSessionState(syncSessionState);
190192
}
191193

192-
private void MaybeSetUnavailableMessage(RpcModel rpcModel, CredentialModel credentialModel)
194+
private void MaybeSetUnavailableMessage(RpcModel rpcModel, CredentialModel credentialModel, SyncSessionControllerStateModel syncSessionState)
193195
{
194196
var oldMessage = UnavailableMessage;
195197
if (rpcModel.RpcLifecycle != RpcLifecycle.Connected)
@@ -205,6 +207,10 @@ private void MaybeSetUnavailableMessage(RpcModel rpcModel, CredentialModel crede
205207
{
206208
UnavailableMessage = "Please start Coder Connect from the tray window to access file sync.";
207209
}
210+
else if (syncSessionState.Lifecycle == SyncSessionControllerLifecycle.Uninitialized)
211+
{
212+
UnavailableMessage = "Sync session controller is not initialized. Please wait...";
213+
}
208214
else
209215
{
210216
UnavailableMessage = null;
@@ -219,6 +225,13 @@ private void MaybeSetUnavailableMessage(RpcModel rpcModel, CredentialModel crede
219225

220226
private void UpdateSyncSessionState(SyncSessionControllerStateModel syncSessionState)
221227
{
228+
// This should never happen.
229+
if (syncSessionState == null)
230+
return;
231+
if (syncSessionState.Lifecycle == SyncSessionControllerLifecycle.Uninitialized)
232+
{
233+
MaybeSetUnavailableMessage(_rpcController.GetState(), _credentialManager.GetCachedCredentials(), syncSessionState);
234+
}
222235
Error = syncSessionState.DaemonError;
223236
Sessions = syncSessionState.SyncSessions.Select(s => new SyncSessionViewModel(this, s)).ToList();
224237
}

App/ViewModels/TrayWindowDisconnectedViewModel.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
using System.Threading.Tasks;
21
using Coder.Desktop.App.Models;
32
using Coder.Desktop.App.Services;
43
using CommunityToolkit.Mvvm.ComponentModel;
54
using CommunityToolkit.Mvvm.Input;
5+
using System;
6+
using System.Threading.Tasks;
67

78
namespace Coder.Desktop.App.ViewModels;
89

@@ -11,6 +12,8 @@ public partial class TrayWindowDisconnectedViewModel : ObservableObject
1112
private readonly IRpcController _rpcController;
1213

1314
[ObservableProperty] public partial bool ReconnectButtonEnabled { get; set; } = true;
15+
[ObservableProperty] public partial string ErrorMessage { get; set; } = string.Empty;
16+
[ObservableProperty] public partial bool ReconnectFailed { get; set; } = false;
1417

1518
public TrayWindowDisconnectedViewModel(IRpcController rpcController)
1619
{
@@ -26,6 +29,16 @@ private void UpdateFromRpcModel(RpcModel rpcModel)
2629
[RelayCommand]
2730
public async Task Reconnect()
2831
{
29-
await _rpcController.Reconnect();
32+
try
33+
{
34+
ReconnectFailed = false;
35+
ErrorMessage = string.Empty;
36+
await _rpcController.Reconnect();
37+
}
38+
catch (Exception ex)
39+
{
40+
ErrorMessage = ex.Message;
41+
ReconnectFailed = true;
42+
}
3043
}
3144
}

App/Views/Pages/TrayWindowDisconnectedPage.xaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@
3030

3131
<controls:HorizontalRule />
3232

33+
<TextBlock FontWeight="semibold"
34+
TextWrapping="Wrap"
35+
Foreground="Red"
36+
Visibility="{x:Bind ViewModel.ReconnectFailed, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}"
37+
Text="Reconnect failed"/>
38+
39+
<TextBlock
40+
TextWrapping="Wrap"
41+
Margin="0,0,0,10"
42+
Foreground="Red"
43+
Visibility="{x:Bind ViewModel.ReconnectFailed, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}"
44+
Text="{x:Bind ViewModel.ErrorMessage, Mode=OneWay}" />
45+
3346
<HyperlinkButton
3447
HorizontalContentAlignment="Left"
3548
HorizontalAlignment="Stretch"

App/Views/TrayWindow.xaml.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,7 @@ public TrayWindow(IRpcController rpcController, ICredentialManager credentialMan
122122
private void SetPageByState(RpcModel rpcModel, CredentialModel credentialModel,
123123
SyncSessionControllerStateModel syncSessionModel)
124124
{
125-
if (credentialModel.State == CredentialState.Unknown ||
126-
syncSessionModel.Lifecycle == SyncSessionControllerLifecycle.Uninitialized)
125+
if (credentialModel.State == CredentialState.Unknown)
127126
{
128127
SetRootFrame(_loadingPage);
129128
return;

0 commit comments

Comments
 (0)