protected override void Cleanup() { ConsumedService.GetValueOrDefault()?.Dispose(); ConsumedService = default; DiscoveryMode = default; ContextLinkageOptions = default; }
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 IServiceDiscoveryRequest CreateServiceDiscoveryRequest( Maybe <IConsumedServiceReference> consumedService, DiscoveryMode mode, IContextLinkageOptions contextLinkageOptions) { var obj = ServiceDiscoveryRequest.Rent(); obj.ConsumedService = consumedService; obj.DiscoveryMode = mode; obj.ContextLinkageOptions = contextLinkageOptions; return(obj); }
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]); } }
public IMethodDiscoveryRequest CreateMethodDiscoveryRequest( Maybe <string> inputMessageId, Maybe <string> outputMessageId, Maybe <IConsumedMethodReference> method, DiscoveryMode discoveryMode, IContextLinkageOptions contextLinkageOptions) { var obj = MethodDiscoveryRequest.Rent(); obj.InputMessageId = inputMessageId; obj.OutputMessageId = outputMessageId; obj.ConsumedMethod = method; obj.DiscoveryMode = discoveryMode; obj.ContextLinkageOptions = contextLinkageOptions; return(obj); }
private ContextLinkageOptions ConvertToProto(IContextLinkageOptions obj) { var proto = ContextLinkageOptions.Rent(); if (obj != null) { switch (obj.Mode) { case ContextLinkageDiscoveryMode.None: proto.ClearMode(); break; case ContextLinkageDiscoveryMode.SpecificContext: proto.SpecificContextId = obj.SpecificContext.Value; break; case ContextLinkageDiscoveryMode.CurrentContext: proto.CurrentContext = Empty.Instance; break; } } return(proto); }
public IInvocationStart CreateInvocationStartRequest(IInvocationTarget target, IContextLinkageOptions contextLinkageOptions) { var obj = InvocationStart.Rent(); obj.Target = target; obj.ContextLinkageOptions = contextLinkageOptions ?? CreateContextLinkageOptions(ContextLinkageDiscoveryMode.None); return(obj); }
private async ValueTask <IAppConnection> ResolveTargetConnectionAsync( IConsumedMethodReference method, IAppConnection source, IContextLinkageOptions contextLinkageOptions) { 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 (_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}}}", 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 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}}}"); } 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 .LaunchAndConnectAsync(appId, resolveMode, source.Info) .ConfigureAwait(false); return(resolvedConnection.AppConnection); }
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 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 bool IsContextShouldBeConsidered(IContextLinkageOptions contextLinkageOptions, IAppConnection sourceConnection) { return(contextLinkageOptions != null && contextLinkageOptions.Mode != ContextLinkageDiscoveryMode.None && GetApplicationContexts(contextLinkageOptions, sourceConnection).Any()); }