public bool TryGetOnlineConnection(UniqueId id, out IAppConnection connection) { lock (_connections) { return(_connections.TryGetValue(id, out connection)); } }
public AppConnectionProcessor(IAppConnection connection, IClientRequestHandler clientRequestHandler) { _connection = connection; Id = _connection.Id; _log = LogManager.GetLogger <AppConnectionProcessor>(Id.ToString()); _clientRequestHandler = clientRequestHandler; }
private async ValueTask <IAppConnection> ResolveTargetConnectionAsync( IConsumedMethodReference method, IAppConnection source) { Log.Debug("Resolving target connection for call {{{0}}} from {{{1}}}", method, source); string appId; ResolveMode resolveMode; var targetMethods = _registryService.GetMatchingProvidedMethods(source.Info.ApplicationId, method); var onlineProvidedMethods = _appLifecycleManager .GetOnlineConnections() .Where(x => !x.Id.Equals(source.Id)) .Join( targetMethods.Where(x => GetLaunchMode(x) != LaunchMode.MultiInstance), x => x.Info.ApplicationId, y => y.ProvidedService.Application.Id, (x, y) => (Method: y, AppConnection: x)) .ToArray(); if (onlineProvidedMethods.Any()) { var connection = onlineProvidedMethods.First().AppConnection; Log.Debug("Resolved target connection for call {{{0}}} from {{{1}}} to online connection: {{{2}}}", method, source, connection); return(connection); } lock (_resolveConnectionSync) { Log.Debug("Resolving target connection for call {{{0}}} from {{{1}}} to offline connection", method, source); var appIds = _appLifecycleManager.FilterCanBeLaunched( targetMethods.Select(x => x.ProvidedService.Application.Id).Distinct()); targetMethods = targetMethods.Join(appIds, x => x.ProvidedService.Application.Id, y => y, (x, y) => x).ToArray(); var singleInstanceMethods = targetMethods .Where(x => GetLaunchMode(x) == LaunchMode.SingleInstance) .ToArray(); var candidate = singleInstanceMethods.FirstOrDefault(x => !x.ProvidedService.Application.Id.Equals(source.Info.ApplicationId)); resolveMode = ResolveMode.SingleInstance; if (candidate == null) { candidate = singleInstanceMethods.FirstOrDefault(); resolveMode = ResolveMode.SingleInstance; } if (candidate == null) { candidate = targetMethods.FirstOrDefault(x => GetLaunchMode(x) == LaunchMode.MultiInstance); resolveMode = ResolveMode.MultiInstance; } if (candidate == null) { throw new InvalidOperationException($"Cannot resolve target for invocation {{{method}}} from {{{source}}}"); } Log.Debug("Resolved target connection for call {{{0}}} from {{{1}}} to provided method {{{2}}}", method, source, candidate); appId = candidate.ProvidedService.Application.Id; } var resolvedConnection = await _appLifecycleManager .ResolveConnectionAsync(appId, resolveMode, source.Info) .ConfigureAwait(false); return(resolvedConnection.AppConnection); }
public AppConnectionProcessor(IAppConnection connection, IClientRequestHandler clientRequestHandler) { _connection = connection; Id = _connection.Id; _log = LogManager.GetLogger <AppConnectionProcessor>(Id.ToString()); _clientRequestHandler = clientRequestHandler; Completion = TaskRunner.RunInBackground(ProcessAsync); }
private async ValueTask <IAppConnection> ResolveTargetConnectionAsync( IProvidedMethodReference methodReference, IAppConnection source, IContextLinkageOptions contextLinkageOptions) { var method = _registryService.GetProvidedMethod(methodReference); var launchMode = GetLaunchMode(method); var appId = methodReference.ProvidedService.ApplicationId; if (methodReference.ProvidedService.ConnectionId.HasValue) { var connectionId = methodReference.ProvidedService.ConnectionId.Value; if (!_appLifecycleManager.TryGetOnlineConnection(connectionId, out var connection)) { throw new InvalidOperationException($"The requested app {appId} connection {connectionId} is not online"); } return(connection); } Task <ResolvedConnection> resolveTask; lock (_resolveConnectionSync) { if (launchMode != LaunchMode.MultiInstance) { var onlineConnections = _appLifecycleManager .GetOnlineConnections() .Where(x => x.Info.ApplicationId.Equals(appId) && !x.Id.Equals(source.Id)).ToArray(); if (_contextLinkageManager.IsContextShouldBeConsidered(contextLinkageOptions, source)) { onlineConnections = _contextLinkageManager .GetAppsInContexts(contextLinkageOptions, source, true) .Join(onlineConnections, x => x.ConnectionId.Value, y => y.Id, (x, y) => y) .ToArray(); } if (onlineConnections.Any()) { return(onlineConnections.First()); } } if (launchMode == LaunchMode.None || !_appLifecycleManager.CanBeLaunched(appId)) { throw new InvalidOperationException( $"The requested app {appId} is not online and cannot be launched"); } var resolveMode = ConvertToResolveMode(launchMode); resolveTask = _appLifecycleManager.LaunchAndConnectAsync(appId, resolveMode, source.Info); } var resolvedConnection = await resolveTask.ConfigureAwait(false); return(resolvedConnection.AppConnection); }
public async Task HandleAsync( IMethodDiscoveryRequest request, IAppConnection sourceConnection, ITransportChannel sourceChannel) { Log.Info("Handling method discovery request {{{0}}} from {{{1}}}", request, sourceConnection); var appId = sourceConnection.Info.ApplicationId; IEnumerable <IProvidedMethod> matchingProvidedMethods = request.ConsumedMethod.HasValue ? _registryService.GetMatchingProvidedMethods(appId, request.ConsumedMethod.Value) : _registryService.GetMatchingProvidedMethods(appId); if (request.InputMessageId.HasValue) { matchingProvidedMethods = matchingProvidedMethods .Where(x => string.Equals(x.Method.InputMessage.Id, request.InputMessageId.Value)); } if (request.OutputMessageId.HasValue) { matchingProvidedMethods = matchingProvidedMethods .Where(x => string.Equals(x.Method.OutputMessage.Id, request.OutputMessageId.Value)); } IEnumerable <IDiscoveredMethod> discoveredMethods; if (request.DiscoveryMode == DiscoveryMode.Online) { var onlineConnections = _connectionTracker.GetOnlineConnections(); discoveredMethods = matchingProvidedMethods .Join( onlineConnections, x => x.ProvidedService.Application.Id, y => y.Info.ApplicationId, (method, connection) => (method, connection)) .Select(pm => Convert(pm.method, pm.connection.Id)); } else { discoveredMethods = matchingProvidedMethods .Select(pm => Convert(pm, Maybe <UniqueId> .Nothing)); } using (var response = _protocol.MessageFactory.CreateMethodDiscoveryResponse(discoveredMethods.ToList())) { Log.Info("Completed method discovery request {{{0}}} from {{{1}}}: {2}", request, sourceConnection, response); var serializedResponse = _protocol.Serializer.Serialize(response); try { await sourceChannel.Out .WriteAsync(new TransportMessageFrame(serializedResponse)) .ConfigureAwait(false); } catch { serializedResponse.Dispose(); throw; } } }
private ValueTask <IAppConnection> ResolveTargetConnectionAsync( IConsumedMethodReference method, IAppConnection source) { var targetMethods = _registryService.GetMatchingProvidedMethods(source.Info.ApplicationId, method); var targetApps = targetMethods.Select(x => x.ProvidedService.Application.Id).ToList(); return(_appLifecycleManager.GetOrSpawnConnectionAsync(targetApps)); }
private ValueTask <IAppConnection> ResolveTargetConnectionAsync( IProvidedMethodReference method, IAppConnection source) { if (method.ProvidedService.ConnectionId.HasValue) { var connectionId = method.ProvidedService.ConnectionId.Value; if (!_appLifecycleManager.TryGetOnlineConnection(connectionId, out var connection)) { throw new InvalidOperationException($"The requested connection {connectionId} is not online"); } return(new ValueTask <IAppConnection>(connection)); } return(_appLifecycleManager.GetOrSpawnConnectionAsync(new[] { method.ProvidedService.ApplicationId })); }
private async ValueTask <IAppConnection> ResolveTargetConnectionAsync( IConsumedMethodReference method, IAppConnection source, ITransportChannel sourceChannel, IContextLinkageOptions contextLinkageOptions) { Log.Debug("Resolving target connection for call {{{0}}} from {{{1}}} for {2} invocation", method, source, sourceChannel.Id); string appId; ResolveMode resolveMode; var targetMethods = _registryService.GetMatchingProvidedMethods(source.Info.ApplicationId, method); var onlineProvidedMethods = _appLifecycleManager .GetOnlineConnections() .Where(x => !x.Id.Equals(source.Id)) .Join( targetMethods.Where(x => GetLaunchMode(x) != LaunchMode.MultiInstance), x => x.Info.ApplicationId, y => y.ProvidedService.Application.Id, (x, y) => (Method: y, AppConnection: x)) .ToArray(); if (_contextLinkageManager.IsContextShouldBeConsidered(contextLinkageOptions, source)) { onlineProvidedMethods = _contextLinkageManager.GetAppsInContexts(contextLinkageOptions, source, true) .Join(onlineProvidedMethods, x => x.ConnectionId.Value, y => y.AppConnection.Id, (x, y) => y).ToArray(); } if (onlineProvidedMethods.Any()) { var connection = onlineProvidedMethods.First().AppConnection; Log.Debug("Resolved target connection for call {{{0}}} from {{{1}}} to online connection {{{2}}} for {3} invocation", method, source, connection, sourceChannel.Id); return(connection); } lock (_resolveConnectionSync) { Log.Debug("Resolving target connection for call {{{0}}} (invocation {2}) from {{{1}}} to offline connection", method, source, sourceChannel.Id); var appIds = _appLifecycleManager.FilterCanBeLaunched( targetMethods.Select(x => x.ProvidedService.Application.Id).Distinct()); targetMethods = targetMethods.Join(appIds, x => x.ProvidedService.Application.Id, y => y, (x, y) => x).ToArray(); var singleInstanceMethods = targetMethods.Where(x => GetLaunchMode(x) == LaunchMode.SingleInstance).ToArray(); var onlineConnections = new HashSet <string>(_appLifecycleManager.GetOnlineConnections().Select(connection => connection.Info.ApplicationId)); var candidate = singleInstanceMethods.FirstOrDefault(x => !x.ProvidedService.Application.Id.Equals(source.Info.ApplicationId) && !onlineConnections.Contains(x.ProvidedService.Application.Id)); resolveMode = ResolveMode.SingleInstance; if (candidate == null) { candidate = singleInstanceMethods.FirstOrDefault(x => !onlineConnections.Contains(x.ProvidedService.Application.Id)); resolveMode = ResolveMode.SingleInstance; } if (candidate == null) { candidate = targetMethods.FirstOrDefault(x => GetLaunchMode(x) == LaunchMode.MultiInstance); resolveMode = ResolveMode.MultiInstance; } if (candidate == null) { candidate = targetMethods.FirstOrDefault(x => GetLaunchMode(x) != LaunchMode.None); resolveMode = ResolveMode.MultiInstance; } if (candidate == null) { throw new InvalidOperationException($"Cannot resolve target for invocation {{{method}}} from {{{source}}} for {sourceChannel.Id} invocation"); } Log.Debug("Resolved target connection for call {{{0}}} from {{{1}}} to provided method {{{2}}} for {3} invocation", method, source, candidate, sourceChannel.Id); appId = candidate.ProvidedService.Application.Id; } var launchAppTask = _appLifecycleManager.LaunchAndConnectAsync(appId, resolveMode, source.Info); var completedTask = await Task.WhenAny(launchAppTask, source.IncomingChannels.Completion).ConfigureAwait(false); if (completedTask == launchAppTask) { var resolvedConnection = await launchAppTask.ConfigureAwait(false); return(resolvedConnection.AppConnection); } throw new TaskCanceledException($"Launch of application {appId} canceled because source connection {source.Info} is completed"); }
private async ValueTask <IAppConnection> ResolveTargetConnectionAsync( IProvidedMethodReference methodReference, IAppConnection source, ITransportChannel sourceChannel, IContextLinkageOptions contextLinkageOptions) { if (methodReference.ProvidedService.ConnectionId.HasValue) { var connectionId = methodReference.ProvidedService.ConnectionId.Value; if (!_appLifecycleManager.TryGetOnlineConnection(connectionId, out var connection)) { throw new InvalidOperationException($"The requested connection {connectionId} is not online"); } return(connection); } var appId = methodReference.ProvidedService.ApplicationId; if (methodReference.ProvidedService.ApplicationInstanceId.HasValue) { var appInstanceId = methodReference.ProvidedService.ApplicationInstanceId.Value; if (appId.HasValue && _appLifecycleManager.TryGetConnectionInProgress(appInstanceId, appId.Value, out var connectionInProgress)) { return(await connectionInProgress); } var connections = _appLifecycleManager.GetAppInstanceConnections(appInstanceId).ToList(); if (connections.Count == 0) { throw new InvalidOperationException($"App instance {appInstanceId} is doesn't have online connections"); } if (appId.HasValue) { var connection = connections.FirstOrDefault(c => c.Info.ApplicationId.Equals(appId.Value)); if (connection == null) { throw new InvalidOperationException($"App instance {appInstanceId} is doesn't have connection with {appId.Value} application id"); } return(connection); } if (connections.Count == 1) { return(connections.Single()); } throw new InvalidOperationException($"App instance {appInstanceId} has several connections, you need to specify ApplicationId to make call to specific connection"); } if (!appId.HasValue) { throw new InvalidOperationException($"AppId is required to resolve target connection for {methodReference} provided method reference"); } var appIdValue = appId.Value; var method = _registryService.GetProvidedMethod(methodReference); var launchMode = GetLaunchMode(method); Task <ResolvedConnection> resolveTask; lock (_resolveConnectionSync) { if (launchMode != LaunchMode.MultiInstance) { var onlineConnections = _appLifecycleManager .GetOnlineConnections() .Where(x => x.Info.ApplicationId.Equals(appIdValue) && !x.Id.Equals(source.Id)).ToArray(); if (_contextLinkageManager.IsContextShouldBeConsidered(contextLinkageOptions, source)) { onlineConnections = _contextLinkageManager .GetAppsInContexts(contextLinkageOptions, source, true) .Join(onlineConnections, x => x.ConnectionId.Value, y => y.Id, (x, y) => y) .ToArray(); } if (onlineConnections.Any()) { return(onlineConnections.First()); } } if (launchMode == LaunchMode.None || !_appLifecycleManager.CanBeLaunched(appIdValue)) { throw new InvalidOperationException( $"The requested app {appIdValue} is not online and cannot be launched"); } var resolveMode = ConvertToResolveMode(launchMode); resolveTask = _appLifecycleManager.LaunchAndConnectAsync(appIdValue, resolveMode, source.Info); } var resolvedConnection = await resolveTask.ConfigureAwait(false); return(resolvedConnection.AppConnection); }
public async Task HandleAsync(IInvocationStart request, IAppConnection sourceConnection, ITransportChannel sourceChannel) { IAppConnection targetConnection = null; ITransportChannel targetChannel = null; try { Log.Info("Handling invocation {0} from {{{1}}}: {{{2}}}", sourceChannel.Id, sourceConnection, request); targetConnection = await request.Target.Handle(_resolveTargetConnectionHandler, sourceConnection).ConfigureAwait(false); targetChannel = await targetConnection.CreateChannelAsync().ConfigureAwait(false); Log.Debug("Created channel {0} for invocation {1} from {{{2}}} to {{{3}}}: {{{4}}}", targetChannel.Id, sourceChannel.Id, sourceConnection, targetConnection, request); using (var invocationStarting = _protocolMessageFactory.CreateInvocationStarting()) { var serialized = _protocolSerializer.Serialize(invocationStarting); try { await sourceChannel.Out.WriteAsync(new TransportMessageFrame(serialized)).ConfigureAwait(false); Log.Trace("Sent starting event for invocation {0}", sourceChannel.Id); } catch { serialized.Dispose(); throw; } } using (var invocationRequested = request.Target.Handle(_createRequestHandler, sourceConnection)) { var serialized = _protocolSerializer.Serialize(invocationRequested); try { await targetChannel.Out.WriteAsync(new TransportMessageFrame(serialized)).ConfigureAwait(false); Log.Trace("Sent requested event for invocation {0} to {1}", targetChannel.Id, targetConnection); } catch { serialized.Dispose(); throw; } } var propagateTask1 = TaskRunner.RunInBackground(() => PropagateAsync(sourceChannel.In, targetChannel.Out)); var propagateTask2 = TaskRunner.RunInBackground(() => PropagateAsync(targetChannel.In, sourceChannel.Out)); await Task.WhenAll(propagateTask1, propagateTask2).ConfigureAwait(false); } catch (Exception ex) { sourceChannel.Out.TryTerminate(ex); targetChannel?.Out.TryTerminate(ex); throw; } finally { try { await Task .WhenAll( targetChannel?.In.ConsumeAsync((Action <TransportMessageFrame>)DisposeFrame).IgnoreExceptions() ?? TaskConstants.Completed, sourceChannel.In.ConsumeAsync((Action <TransportMessageFrame>)DisposeFrame).IgnoreExceptions(), targetChannel?.Completion ?? TaskConstants.Completed, sourceChannel.Completion) .ConfigureAwait(false); Log.Info("Completed invocation {0} from {{{1}}} to {{{2}}}: {{{3}}}", sourceChannel.Id, sourceConnection, targetConnection, request); } catch (OperationCanceledException) { Log.Info("Canceled invocation {0} from {{{1}}} to {{{2}}}: {{{3}}}", sourceChannel.Id, sourceConnection, targetConnection, request); throw; } catch (Exception ex) { Log.Warn("Failed invocation {0} from {{{1}}} to {{{2}}}: {{{3}}}. Error: {4}", sourceChannel.Id, sourceConnection, targetConnection, request, ex.FormatTypeAndMessage()); throw; } } }
public bool IsContextShouldBeConsidered(IContextLinkageOptions contextLinkageOptions, IAppConnection sourceConnection) { return(contextLinkageOptions != null && contextLinkageOptions.Mode != ContextLinkageDiscoveryMode.None && GetApplicationContexts(contextLinkageOptions, sourceConnection).Any()); }
public ResolvedConnection(IAppConnection appConnection, bool isNewInstance) { AppConnection = appConnection; IsNewInstance = isNewInstance; }
public async Task HandleAsync( IServiceDiscoveryRequest request, IAppConnection sourceConnection, ITransportChannel sourceChannel) { IReadOnlyCollection <(IConsumedMethod Consumed, IProvidedMethod Provided)> methodMatches; if (request.ConsumedService.HasValue) { methodMatches = _registryService.GetMethodMatches( sourceConnection.Info.ApplicationId, request.ConsumedService.Value); } else { methodMatches = _registryService.GetMethodMatches(sourceConnection.Info.ApplicationId); } IEnumerable <IGrouping <(IConsumedService ConsumedService, IProvidedService ProvidedService, Maybe <UniqueId> ConnectionId, Maybe <UniqueId> ApplicationInstanceId), IProvidedMethod> > groupedMethods; var online = request.DiscoveryMode == DiscoveryMode.Online; if (_contextLinkageManager.IsContextShouldBeConsidered(request.ContextLinkageOptions, sourceConnection)) { groupedMethods = _contextLinkageManager.GetAppsInContexts(request.ContextLinkageOptions, sourceConnection, online) .Join(methodMatches, x => x.AppId, y => y.Provided.ProvidedService.Service.Id, (x, y) => (y.Consumed, y.Provided, x.AppInstanceId, x.ConnectionId)) .GroupBy(x => (x.Consumed.ConsumedService, x.Provided.ProvidedService, x.ConnectionId, new Maybe <UniqueId>(x.AppInstanceId)), x => x.Provided); } else { if (online) { var onlineConnections = _appLifecycleManager.GetOnlineConnections(); groupedMethods = methodMatches .Join(onlineConnections, x => x.Provided.ProvidedService.Application.Id, y => y.Info.ApplicationId, (x, y) => (Match: x, ConnectionId: y.Id, y.Info.ApplicationInstanceId)) .GroupBy( x => ( x.Match.Consumed.ConsumedService, x.Match.Provided.ProvidedService, new Maybe <UniqueId>(x.ConnectionId), new Maybe <UniqueId>(x.ApplicationInstanceId)), x => x.Match.Provided); } else { var providerApps = methodMatches.Select(x => x.Provided.ProvidedService.Application.Id).Distinct() .ToArray(); var availableProviderApps = FilterAvailableApps(providerApps); groupedMethods = methodMatches .Join( availableProviderApps, x => x.Provided.ProvidedService.Application.Id, y => y, (x, y) => x) .GroupBy( x => ( x.Consumed.ConsumedService, x.Provided.ProvidedService, ConnectionId: Maybe <UniqueId> .Nothing, ApplicationInstanceId: Maybe <UniqueId> .Nothing), x => x.Provided); } } var discoveredServices = from s in groupedMethods let consumedService = s.Key.ConsumedService let providedService = s.Key.ProvidedService let connectionId = s.Key.ConnectionId let applicationInstanceId = s.Key.ApplicationInstanceId select _protocol.MessageFactory.CreateDiscoveredService( _protocol.MessageFactory.CreateConsumedServiceReference( consumedService.Service.Id, consumedService.Alias), _protocol.MessageFactory.CreateProvidedServiceReference( providedService.Service.Id, providedService.Alias, providedService.Application.Id, connectionId, applicationInstanceId), s.Key.ProvidedService.Title, s.Select(m => _protocol.MessageFactory.CreateDiscoveredServiceMethod( m.Method.Name, m.Title, m.Method.InputMessage.Id, m.Method.OutputMessage.Id, Convert(m.Method.Type), m.Options.Select(o => _protocol.MessageFactory.CreateOption(o.Id, o.Value)).ToList())) .ToList()); using (var response = _protocol.MessageFactory.CreateServiceDiscoveryResponse(discoveredServices.ToList())) { Log.Info("Completed service discovery request {{{0}}} from {{{1}}}: {2}", request, sourceConnection, response); var serializedResponse = _protocol.Serializer.Serialize(response); try { await sourceChannel.Out .WriteAsync(new TransportMessageFrame(serializedResponse)) .ConfigureAwait(false); } catch { serializedResponse.Dispose(); throw; } } }
public async Task HandleAsync( IMethodDiscoveryRequest request, IAppConnection sourceConnection, ITransportChannel sourceChannel) { Log.Info("Handling method discovery request {{{0}}} from {{{1}}}", request, sourceConnection); var appId = sourceConnection.Info.ApplicationId; IEnumerable <IProvidedMethod> matchingProvidedMethods = request.ConsumedMethod.HasValue ? _registryService.GetMatchingProvidedMethods(appId, request.ConsumedMethod.Value) : _registryService.GetMatchingProvidedMethods(appId); if (request.InputMessageId.HasValue) { matchingProvidedMethods = matchingProvidedMethods .Where(x => string.Equals(x.Method.InputMessage.Id, request.InputMessageId.Value)); } if (request.OutputMessageId.HasValue) { matchingProvidedMethods = matchingProvidedMethods .Where(x => string.Equals(x.Method.OutputMessage.Id, request.OutputMessageId.Value)); } IEnumerable <IDiscoveredMethod> discoveredMethods; bool online = request.DiscoveryMode == DiscoveryMode.Online; if (_contextLinkageManager.IsContextShouldBeConsidered(request.ContextLinkageOptions, sourceConnection)) { discoveredMethods = _contextLinkageManager.GetAppsInContexts(request.ContextLinkageOptions, sourceConnection, online) .Join(matchingProvidedMethods, x => x.AppId, y => y.ProvidedService.Application.Id, (connection, method) => (method, connection)) .Select(pm => Convert(pm.method, pm.connection.ConnectionId, new Maybe <UniqueId>(pm.connection.AppInstanceId))); } else { if (online) { var onlineConnections = _appLifecycleManager.GetOnlineConnections(); discoveredMethods = matchingProvidedMethods .Join( onlineConnections, x => x.ProvidedService.Application.Id, y => y.Info.ApplicationId, (method, connection) => (method, connection)) .Select(pm => Convert(pm.method, pm.connection.Id, pm.connection.Info.ApplicationInstanceId)); } else { var providedMethods = matchingProvidedMethods.ToArray(); var providerApps = providedMethods.Select(x => x.ProvidedService.Application.Id).Distinct().ToArray(); var availableProviderApps = FilterAvailableApps(providerApps); discoveredMethods = providedMethods .Join(availableProviderApps, x => x.ProvidedService.Application.Id, y => y, (x, y) => x) .Select(pm => Convert(pm, Maybe <UniqueId> .Nothing, Maybe <UniqueId> .Nothing)); } } using (var response = _protocol.MessageFactory.CreateMethodDiscoveryResponse(discoveredMethods.ToList())) { Log.Info("Completed method discovery request {{{0}}} from {{{1}}}: {2}", request, sourceConnection, response); var serializedResponse = _protocol.Serializer.Serialize(response); try { await sourceChannel.Out .WriteAsync(new TransportMessageFrame(serializedResponse)) .ConfigureAwait(false); } catch { serializedResponse.Dispose(); throw; } } }
private IInvocationStartRequested CreateInvocationTarget(IConsumedMethodReference reference, IAppConnection sourceConnection) { return(_protocolMessageFactory.CreateInvocationStartRequested( reference.ConsumedService.ServiceId, reference.MethodId, reference.ConsumedService.ServiceAlias, sourceConnection.Info.ApplicationId, sourceConnection.Info.ApplicationInstanceId, sourceConnection.Id)); }
public async Task HandleAsync(IInvocationStart request, IAppConnection sourceConnection, ITransportChannel sourceChannel) { IAppConnection targetConnection = null; ITransportChannel targetChannel = null; InvocationDescriptor callDescriptor = null; var startMs = _stopwatch.ElapsedMilliseconds; try { Log.Info("Handling invocation {0} from {{{1}}}: {{{2}}}", sourceChannel.Id, sourceConnection, request); targetConnection = await request.Target.Handle(_resolveTargetConnectionHandler, sourceConnection).ConfigureAwait(false); targetChannel = await targetConnection.CreateChannelAsync().ConfigureAwait(false); Log.Debug("Created channel {0} for invocation {1} from {{{2}}} to {{{3}}}: {{{4}}}", targetChannel.Id, sourceChannel.Id, sourceConnection, targetConnection, request); using (var invocationStarting = _protocolMessageFactory.CreateInvocationStarting()) { var serialized = _protocolSerializer.Serialize(invocationStarting); try { await sourceChannel.Out.WriteAsync(new TransportMessageFrame(serialized)).ConfigureAwait(false); Log.Trace("Sent starting event for invocation {0}", sourceChannel.Id); } catch { serialized.Dispose(); throw; } } using (var invocationRequested = request.Target.Handle(_createRequestHandler, sourceConnection)) { startMs = _stopwatch.ElapsedMilliseconds; callDescriptor = new InvocationDescriptor( sourceConnection.Info, targetConnection.Info, invocationRequested.ServiceId, invocationRequested.ServiceAlias.GetValueOrDefault(), invocationRequested.MethodId); _appLifecycleManager.OnInvocationStarted(new InvocationStartedEventDescriptor(callDescriptor)); var serialized = _protocolSerializer.Serialize(invocationRequested); try { await targetChannel.Out.WriteAsync(new TransportMessageFrame(serialized)).ConfigureAwait(false); Log.Trace("Sent requested event for invocation {0} to {1}", targetChannel.Id, targetConnection); } catch { serialized.Dispose(); throw; } } var propagateTask1 = TaskRunner.RunInBackground(() => PropagateAsync(sourceChannel.In, targetChannel.Out)); var propagateTask2 = TaskRunner.RunInBackground(() => PropagateAsync(targetChannel.In, sourceChannel.Out)); await Task.WhenAll(propagateTask1, propagateTask2).ConfigureAwait(false); } catch (Exception ex) { sourceChannel.Out.TryTerminate(ex); targetChannel?.Out.TryTerminate(ex); throw; } finally { try { await Task .WhenAll( targetChannel?.In.ConsumeAsync((Action <TransportMessageFrame>)DisposeFrame).IgnoreExceptions() ?? TaskConstants.Completed, sourceChannel.In.ConsumeAsync((Action <TransportMessageFrame>)DisposeFrame).IgnoreExceptions(), targetChannel?.Completion ?? TaskConstants.Completed, sourceChannel.Completion) .ConfigureAwait(false); Log.Info("Completed invocation {0} from {{{1}}} to {{{2}}}: {{{3}}}", sourceChannel.Id, sourceConnection, targetConnection, request); OnActionFinished(callDescriptor, InvocationResult.Succeeded, startMs); } catch (OperationCanceledException) { Log.Info("Canceled invocation {0} from {{{1}}} to {{{2}}}: {{{3}}}", sourceChannel.Id, sourceConnection, targetConnection, request); OnActionFinished(callDescriptor, InvocationResult.Canceled, startMs); throw; } catch (Exception ex) { Log.Warn("Failed invocation {0} from {{{1}}} to {{{2}}}: {{{3}}}. Error: {4}", sourceChannel.Id, sourceConnection, targetConnection, request, ex.FormatTypeAndMessage()); OnActionFinished(callDescriptor, InvocationResult.Failed, startMs); throw; } } }
public IReadOnlyCollection <(UniqueId AppInstanceId, string AppId, Maybe <UniqueId> ConnectionId)> GetAppsInContexts(IContextLinkageOptions contextLinkageOptions, IAppConnection sourceConnection, bool online) { return(GetApplicationContexts(contextLinkageOptions, sourceConnection) .Select(id => _contextsSet.GetContext(id)) .Where(context => context != null) .SelectMany(context => context.GetAppsInContext(online)) .Distinct().ToArray()); }
public async Task HandleAsync( IServiceDiscoveryRequest request, IAppConnection sourceConnection, ITransportChannel sourceChannel) { IReadOnlyCollection <(IConsumedMethod Consumed, IProvidedMethod Provided)> methodMatches; if (request.ConsumedService.HasValue) { methodMatches = _registryService.GetMethodMatches( sourceConnection.Info.ApplicationId, request.ConsumedService.Value); } else { methodMatches = _registryService.GetMethodMatches(sourceConnection.Info.ApplicationId); } IEnumerable <IGrouping <(IConsumedService ConsumedService, IProvidedService ProvidedService, Maybe <UniqueId> ConnectionId), IProvidedMethod> > groupedMethods; if (request.DiscoveryMode == DiscoveryMode.Offline) { groupedMethods = methodMatches .GroupBy( x => ( x.Consumed.ConsumedService, x.Provided.ProvidedService, ConnectionId: Maybe <UniqueId> .Nothing), x => x.Provided); } else { var onlineConnections = _connectionTracker.GetOnlineConnections(); groupedMethods = methodMatches .Join(onlineConnections, x => x.Provided.ProvidedService.Application.Id, y => y.Info.ApplicationId, (x, y) => (Match: x, ConnectionId: y.Id)) .GroupBy( x => ( x.Match.Consumed.ConsumedService, x.Match.Provided.ProvidedService, new Maybe <UniqueId>(x.ConnectionId)), x => x.Match.Provided); } var discoveredServices = from s in groupedMethods let consumedService = s.Key.ConsumedService let providedService = s.Key.ProvidedService let connectionId = s.Key.ConnectionId select _protocol.MessageFactory.CreateDiscoveredService( _protocol.MessageFactory.CreateConsumedServiceReference( consumedService.Service.Id, consumedService.Alias), _protocol.MessageFactory.CreateProvidedServiceReference( providedService.Service.Id, providedService.Alias, providedService.Application.Id, connectionId), s.Key.ProvidedService.Title, s.Select(m => _protocol.MessageFactory.CreateDiscoveredServiceMethod( m.Method.Name, m.Title, m.Method.InputMessage.Id, m.Method.OutputMessage.Id, Convert(m.Method.Type))).ToList()); using (var response = _protocol.MessageFactory.CreateServiceDiscoveryResponse(discoveredServices.ToList())) { Log.Info("Completed service discovery request {{{0}}} from {{{1}}}: {2}", request, sourceConnection, response); var serializedResponse = _protocol.Serializer.Serialize(response); try { await sourceChannel.Out .WriteAsync(new TransportMessageFrame(serializedResponse)) .ConfigureAwait(false); } catch { serializedResponse.Dispose(); throw; } } }
private IReadOnlyCollection <string> GetApplicationContexts(IContextLinkageOptions contextLinkageOptions, IAppConnection sourceConnection) { switch (contextLinkageOptions.Mode) { case ContextLinkageDiscoveryMode.CurrentContext: return(_contextsSet.GetContextsOf(sourceConnection.Info.ApplicationInstanceId) .Select(context => context.Id).ToArray()); case ContextLinkageDiscoveryMode.SpecificContext when contextLinkageOptions.SpecificContext.HasValue: return(new[] { contextLinkageOptions.SpecificContext.Value }); default: return(new string[0]); } }