public static async Task <RemoteHostClient> CreateAsync( Workspace workspace, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.ServiceHubRemoteHostClient_CreateAsync, cancellationToken)) { // let each client to have unique id so that we can distinguish different clients when service is restarted var currentInstanceId = Interlocked.Add(ref s_instanceId, 1); var primary = new HubClient("ManagedLanguage.IDE.RemoteHostClient"); var current = $"VS ({Process.GetCurrentProcess().Id}) ({currentInstanceId})"; var hostGroup = new HostGroup(current); var timeout = TimeSpan.FromMilliseconds(workspace.Options.GetOption(RemoteHostOptions.RequestServiceTimeoutInMS)); var remoteHostStream = await RequestServiceAsync(primary, WellKnownRemoteHostServices.RemoteHostService, hostGroup, timeout, cancellationToken).ConfigureAwait(false); var remotableDataRpc = new RemotableDataJsonRpc(workspace, await RequestServiceAsync(primary, WellKnownServiceHubServices.SnapshotService, hostGroup, timeout, cancellationToken).ConfigureAwait(false)); var instance = new ServiceHubRemoteHostClient(workspace, primary, hostGroup, new ReferenceCountedDisposable <RemotableDataJsonRpc>(remotableDataRpc), remoteHostStream); // make sure connection is done right var host = await instance._rpc.InvokeAsync <string>(nameof(IRemoteHostService.Connect), current, TelemetryService.DefaultSession.SerializeSettings()).ConfigureAwait(false); // TODO: change this to non fatal watson and make VS to use inproc implementation Contract.ThrowIfFalse(host == current.ToString()); instance.Started(); // Create a workspace host to hear about workspace changes. We'll // remote those changes over to the remote side when they happen. await RegisterWorkspaceHostAsync(workspace, instance).ConfigureAwait(false); // return instance return(instance); } }
public static async Task <RemoteHostClient?> CreateAsync(Workspace workspace, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.ServiceHubRemoteHostClient_CreateAsync, cancellationToken)) { var enableConnectionPool = workspace.Options.GetOption(RemoteHostOptions.EnableConnectionPool); var maxConnection = workspace.Options.GetOption(RemoteHostOptions.MaxPoolConnection); // let each client to have unique id so that we can distinguish different clients when service is restarted var clientId = CreateClientId(Process.GetCurrentProcess().Id.ToString()); var hostGroup = new HostGroup(clientId); var hubClient = new HubClient("ManagedLanguage.IDE.RemoteHostClient"); // use the hub client logger for unexpected exceptions from devenv as well, so we have complete information in the log: WatsonReporter.InitializeLogger(hubClient.Logger); // Create the RemotableDataJsonRpc before we create the remote host: this call implicitly sets up the remote IExperimentationService so that will be available for later calls var snapshotServiceStream = await RequestServiceAsync(workspace, hubClient, WellKnownServiceHubServices.SnapshotService, hostGroup, cancellationToken).ConfigureAwait(false); var remoteHostStream = await RequestServiceAsync(workspace, hubClient, WellKnownRemoteHostServices.RemoteHostService, hostGroup, cancellationToken).ConfigureAwait(false); var remotableDataRpc = new RemotableDataJsonRpc(workspace, hubClient.Logger, snapshotServiceStream); var connectionManager = new ConnectionManager(workspace, hubClient, hostGroup, enableConnectionPool, maxConnection, new ReferenceCountedDisposable <RemotableDataJsonRpc>(remotableDataRpc)); var client = new ServiceHubRemoteHostClient(workspace, hubClient.Logger, connectionManager, remoteHostStream); var uiCultureLCID = CultureInfo.CurrentUICulture.LCID; var cultureLCID = CultureInfo.CurrentCulture.LCID; bool success = false; try { // initialize the remote service _ = await client._endPoint.InvokeAsync <string>( nameof(IRemoteHostService.Connect), new object[] { clientId, uiCultureLCID, cultureLCID, TelemetryService.DefaultSession.SerializeSettings() }, cancellationToken).ConfigureAwait(false); success = true; } finally { if (!success) { client.Dispose(); } } client.Started(); return(client); } }
public static async Task <RemoteHostClient> CreateAsync(HostWorkspaceServices services, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.ServiceHubRemoteHostClient_CreateAsync, KeyValueLogMessage.NoProperty, cancellationToken)) { Logger.Log(FunctionId.RemoteHost_Bitness, KeyValueLogMessage.Create(LogType.Trace, m => m["64bit"] = RemoteHostOptions.IsServiceHubProcess64Bit(services))); // let each client to have unique id so that we can distinguish different clients when service is restarted var clientId = $"VS ({Process.GetCurrentProcess().Id}) ({Guid.NewGuid()})"; var hostGroup = new HostGroup(clientId); var hubClient = new HubClient("ManagedLanguage.IDE.RemoteHostClient"); // use the hub client logger for unexpected exceptions from devenv as well, so we have complete information in the log: WatsonReporter.InitializeLogger(hubClient.Logger); var remoteHostStream = await RequestServiceAsync(services, hubClient, WellKnownServiceHubService.RemoteHost, hostGroup, cancellationToken).ConfigureAwait(false); var client = new ServiceHubRemoteHostClient(services, hubClient, hostGroup, remoteHostStream); var uiCultureLCID = CultureInfo.CurrentUICulture.LCID; var cultureLCID = CultureInfo.CurrentCulture.LCID; bool success = false; try { // initialize the remote service await client._endPoint.InvokeAsync <string>( nameof(IRemoteHostService.InitializeGlobalState), new object[] { clientId, uiCultureLCID, cultureLCID, TelemetryService.DefaultSession.SerializeSettings() }, cancellationToken).ConfigureAwait(false); success = true; } finally { if (!success) { client.Dispose(); } } client.Started(); return(client); } }
public static async Task <RemoteHostClient?> CreateAsync(Workspace workspace, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.ServiceHubRemoteHostClient_CreateAsync, cancellationToken)) { // let each client to have unique id so that we can distinguish different clients when service is restarted var clientId = CreateClientId(Process.GetCurrentProcess().Id.ToString()); var hostGroup = new HostGroup(clientId); var hubClient = new HubClient("ManagedLanguage.IDE.RemoteHostClient"); // use the hub client logger for unexpected exceptions from devenv as well, so we have complete information in the log: WatsonReporter.InitializeLogger(hubClient.Logger); var remoteHostStream = await RequestServiceAsync(workspace, hubClient, WellKnownServiceHubServices.RemoteHostService, hostGroup, cancellationToken).ConfigureAwait(false); var client = new ServiceHubRemoteHostClient(workspace, hubClient, hostGroup, remoteHostStream); var uiCultureLCID = CultureInfo.CurrentUICulture.LCID; var cultureLCID = CultureInfo.CurrentCulture.LCID; bool success = false; try { // initialize the remote service _ = await client._endPoint.InvokeAsync <string>( nameof(IRemoteHostService.Connect), new object[] { clientId, uiCultureLCID, cultureLCID, TelemetryService.DefaultSession.SerializeSettings() }, cancellationToken).ConfigureAwait(false); success = true; } finally { if (!success) { client.Dispose(); } } client.Started(); return(client); } }
public static async Task <RemoteHostClient?> CreateAsync(Workspace workspace, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.ServiceHubRemoteHostClient_CreateAsync, cancellationToken)) { var timeout = TimeSpan.FromMilliseconds(workspace.Options.GetOption(RemoteHostOptions.RequestServiceTimeoutInMS)); var enableConnectionPool = workspace.Options.GetOption(RemoteHostOptions.EnableConnectionPool); var maxConnection = workspace.Options.GetOption(RemoteHostOptions.MaxPoolConnection); // let each client to have unique id so that we can distinguish different clients when service is restarted var clientId = CreateClientId(Process.GetCurrentProcess().Id.ToString()); var hostGroup = new HostGroup(clientId); var primary = new HubClient("ManagedLanguage.IDE.RemoteHostClient"); ServiceHubRemoteHostClient?client = null; try { // Create the RemotableDataJsonRpc before we create the remote host: this call implicitly sets up the remote IExperimentationService so that will be available for later calls var snapshotServiceStream = await Connections.RequestServiceAsync(workspace, primary, WellKnownServiceHubServices.SnapshotService, hostGroup, timeout, cancellationToken).ConfigureAwait(false); var remoteHostStream = await Connections.RequestServiceAsync(workspace, primary, WellKnownRemoteHostServices.RemoteHostService, hostGroup, timeout, cancellationToken).ConfigureAwait(false); var remotableDataRpc = new RemotableDataJsonRpc(workspace, primary.Logger, snapshotServiceStream); var connectionManager = new ConnectionManager(primary, hostGroup, enableConnectionPool, maxConnection, timeout, new ReferenceCountedDisposable <RemotableDataJsonRpc>(remotableDataRpc)); client = new ServiceHubRemoteHostClient(workspace, primary.Logger, connectionManager, remoteHostStream); var uiCultureLCID = CultureInfo.CurrentUICulture.LCID; var cultureLCID = CultureInfo.CurrentCulture.LCID; // make sure connection is done right var host = await client._rpc.InvokeWithCancellationAsync <string>( nameof(IRemoteHostService.Connect), new object[] { clientId, uiCultureLCID, cultureLCID, TelemetryService.DefaultSession.SerializeSettings() }, cancellationToken).ConfigureAwait(false); client.Started(); return(client); } catch (ConnectionLostException ex) { RemoteHostCrashInfoBar.ShowInfoBar(workspace, ex); Shutdown(ex); // dont crash VS because OOP is failed to start. we will show info bar telling users to restart // but never physically crash VS. return(null); } catch (SoftCrashException ex) { Shutdown(ex); // at this point, we should have shown info bar (RemoteHostCrashInfoBar.ShowInfoBar) to users // returning null here will disable OOP for this VS session. // * Note * this is not trying to recover the exception. but giving users to time // to clean up before restart VS return(null); } catch (Exception ex) { Shutdown(ex); throw; } void Shutdown(Exception ex) { // make sure we shutdown client if initializing client has failed. client?.Shutdown(); // translate to our own cancellation if it is raised. cancellationToken.ThrowIfCancellationRequested(); // otherwise, report watson ex.ReportServiceHubNFW("ServiceHub creation failed"); } } }