public void InvocationShouldAlwaysTriggerLaunchWhenMethodLaunchModeSetToAlways()
        {
            Task <GreetingResponse> HandleAsync(GreetingRequest greetingRequest, MethodCallContext context)
            {
                return(Task.FromResult(new GreetingResponse {
                    Greeting = greetingRequest.Name
                }));
            }

            RunWith10SecTimeout(async() =>
            {
                var serverCreatedCount = 0;
                var echoServerFactory  = new TestClientFactory(
                    (broker, id) =>
                {
                    var optionsBuilder = new ClientOptionsBuilder()
                                         .WithBrokerWorkingDir(_testBrokerFixture.SharedInstance.WorkingDir)
                                         .WithAppInstanceId(id)
                                         .WithApplicationId(EchoServerClient.Id)
                                         .WithDefaultConfiguration()
                                         .WithProvidedService(
                        GreetingService.Id,
                        "AlwaysLaunchGreetingService",
                        x => x.WithUnaryMethod <GreetingRequest, GreetingResponse>("Hello", HandleAsync));

                    serverCreatedCount++;

                    return(Task.FromResult(ClientFactory.Instance.Create(optionsBuilder.Build())));
                });

                var appLauncher = RegisterDisposable(
                    new TestAppLauncher(
                        _testBrokerFixture.SharedInstance,
                        new Dictionary <string, TestClientFactory>
                {
                    { EchoServerClient.Id, echoServerFactory }
                }
                        )
                    );
                await appLauncher.StartAsync();
                ConnectEchoServer();
                var client = new EchoClient(s => s.WithBrokerWorkingDir(_testBrokerFixture.SharedInstance.WorkingDir));
                client.ConnectAsync().ShouldCompleteIn(Timeout5Sec);
                var callDescriptor = new MethodCallDescriptor(
                    ProvidedMethodReference.Create(GreetingService.Id, "AlwaysLaunchGreetingService", "Hello", EchoServerClient.Id));
                await client.CallInvoker.CallUnary(callDescriptor, new GreetingRequest {
                    Name = "Test"
                });
                await client.CallInvoker.CallUnary(callDescriptor, new GreetingRequest {
                    Name = "Test"
                });
                serverCreatedCount.ShouldBe(2);
            });
        }
        public void InvokeTargetUsingConnectionIdWithoutAppId()
        {
            RunWith10SecTimeout(async() =>
            {
                var server1RequestCount = 0;
                var server1             = ConnectEchoServer((request, context) =>
                {
                    server1RequestCount++;
                    return(Task.FromResult(new GreetingResponse {
                        Greeting = "FromServer1"
                    }));
                });

                var server2RequestCount = 0;
                var server2             = ConnectEchoServer((request, context) =>
                {
                    server2RequestCount++;
                    return(Task.FromResult(new GreetingResponse {
                        Greeting = "FromServer2"
                    }));
                });

                var client = CreateClient <EchoClient>();
                await client.ConnectAsync();

                server1RequestCount.ShouldBe(0);
                server2RequestCount.ShouldBe(0);

                var providedMethodReference = ProvidedMethodReference.CreateWithConnectionId(GreetingService.Id,
                                                                                             GreetingService.HelloMethodId, server1.ConnectionId);
                var methodCallDescriptor = new MethodCallDescriptor(providedMethodReference);
                var greetingRequest      = new GreetingRequest {
                    Name = "Client"
                };
                var response =
                    await client.CallInvoker.CallUnary <GreetingRequest, GreetingResponse>(methodCallDescriptor,
                                                                                           greetingRequest);

                response.Greeting.ShouldBe("FromServer1");
                server1RequestCount.ShouldBe(1);
                server2RequestCount.ShouldBe(0);

                providedMethodReference = ProvidedMethodReference.CreateWithConnectionId(GreetingService.Id,
                                                                                         GreetingService.HelloMethodId, server2.ConnectionId);
                methodCallDescriptor = new MethodCallDescriptor(providedMethodReference);
                response             = await client.CallInvoker.CallUnary <GreetingRequest, GreetingResponse>(methodCallDescriptor,
                                                                                                              greetingRequest);

                response.Greeting.ShouldBe("FromServer2");
                server1RequestCount.ShouldBe(1);
                server2RequestCount.ShouldBe(1);
            });
        }
 internal DiscoveredMethod(
     ProvidedMethodReference providedMethod,
     Maybe <string> title,
     string inputMessageId,
     string outputMessageId,
     MethodType type,
     MethodCallDescriptor callDescriptor,
     IReadOnlyCollection <Option> options)
 {
     ProvidedMethod  = providedMethod;
     Title           = title;
     InputMessageId  = inputMessageId;
     OutputMessageId = outputMessageId;
     Type            = type;
     CallDescriptor  = callDescriptor;
     Options         = options;
 }
 internal DiscoveredMethod(
     ProvidedMethodReference providedMethod,
     Maybe <string> title,
     string inputMessageId,
     string outputMessageId,
     MethodType type,
     IReadOnlyCollection <Option> options)
     : this(
         providedMethod,
         title,
         inputMessageId,
         outputMessageId,
         type,
         new MethodCallDescriptor(providedMethod),
         options)
 {
 }
 internal DiscoveredOnlineMethod(
     ProvidedMethodReference providedMethod,
     Maybe <string> title,
     string inputMessageId,
     string outputMessageId,
     MethodType type,
     IReadOnlyCollection <Option> options)
     : base(
         providedMethod,
         title,
         inputMessageId,
         outputMessageId,
         type,
         options)
 {
     ProviderConnectionId = providedMethod.ProvidedService.ConnectionId.Value;
 }
        public void InvokeApplicationBeforeItsConnection()
        {
            RunWith10SecTimeout(async() =>
            {
                Task <GreetingResponse> HandleAsync(GreetingRequest request, MethodCallContext context)
                {
                    return(Task.FromResult(new GreetingResponse {
                        Greeting = request.Name + "1"
                    }));
                }

                var brokerInstance      = _testBrokerFixture.SharedInstance;
                var createdServersCount = 0;
                var createdServerClient = new TaskCompletionSource <IClient>();
                var echoServerFactory   = new TestClientFactory(
                    (broker, id) =>
                {
                    var optionsBuilder = new ClientOptionsBuilder()
                                         .WithBrokerWorkingDir(brokerInstance.WorkingDir)
                                         .WithAppInstanceId(id)
                                         .WithApplicationId(EchoServerClient.Id)
                                         .WithDefaultConfiguration()
                                         .WithProvidedService(
                        GreetingService.Id,
                        x => x.WithUnaryMethod <GreetingRequest, GreetingResponse>(GreetingService.HelloMethodId,
                                                                                   HandleAsync));
                    var serverClient = ClientFactory.Instance.Create(optionsBuilder.Build());
                    createdServerClient.SetResult(serverClient);
                    createdServersCount++;
                    return(Task.FromResult(serverClient));
                });

                var appLauncher = RegisterDisposable(
                    new TestAppLauncher(
                        brokerInstance,
                        new Dictionary <string, TestClientFactory>
                {
                    { EchoServerClient.Id, echoServerFactory }
                },
                        false
                        )
                    );
                await appLauncher.StartAsync();

                var client1 = CreateClient <EchoClient>();
                await client1.ConnectAsync();

                var client2 = CreateClient <EchoClient>();
                await client2.ConnectAsync();

                var helloTask = client1.GreetingService.Hello(new GreetingRequest {
                    Name = "Test1"
                }).ResponseAsync;
                var callUnconnectedServerTask = createdServerClient.Task.ContinueWith(async task =>
                {
                    var serverClient = task.Result;
                    await Task.Delay(TimeSpan.FromSeconds(1));
                    var providedMethodReference = ProvidedMethodReference.CreateWithAppInstanceId(GreetingService.Id,
                                                                                                  GreetingService.HelloMethodId, EchoServerClient.Id, serverClient.ApplicationInstanceId);
                    var methodCallDescriptor = new MethodCallDescriptor(providedMethodReference);
                    await client2.CallInvoker.CallUnary <GreetingRequest, GreetingResponse>(methodCallDescriptor,
                                                                                            new GreetingRequest()
                    {
                        Name = "Test2"
                    });
                }).Unwrap();

                var connectedServerAfterDelayTask = createdServerClient.Task.ContinueWith(async task =>
                {
                    var serverClient = task.Result;

                    await Task.Delay(TimeSpan.FromSeconds(3));

                    serverClient.ConnectionId.ShouldBe(UniqueId.Empty);
                    var onlineConnectionsResponse =
                        await client1.AppLifecycleService.GetConnections(new GetConnectionsRequest
                    {
                        AppInstanceId = serverClient.ApplicationInstanceId
                    });
                    onlineConnectionsResponse.Connections.Count.ShouldBe(0);

                    await serverClient.ConnectAsync();
                }).Unwrap();

                await Task.WhenAll(helloTask, callUnconnectedServerTask, connectedServerAfterDelayTask);

                createdServersCount.ShouldBe(1);
            });
        }
        public void InvocationShouldTriggerLaunchWithSingleInstanceModeByDefault()
        {
            var serverInvokedCount = 0;

            Task <GreetingResponse> HandleAsync(GreetingRequest greetingRequest, MethodCallContext context)
            {
                Interlocked.Increment(ref serverInvokedCount);
                return(Task.FromResult(new GreetingResponse {
                    Greeting = greetingRequest.Name
                }));
            }

            RunWith10SecTimeout(async() =>
            {
                var serverCreatedCount = 0;
                var echoServerFactory  = new TestClientFactory(
                    (broker, id) =>
                {
                    WriteLog("Launching server on demand");

                    var optionsBuilder = new ClientOptionsBuilder()
                                         .WithBrokerWorkingDir(_testBrokerFixture.SharedInstance.WorkingDir)
                                         .WithAppInstanceId(id)
                                         .WithApplicationId(EchoServerClient.Id)
                                         .WithDefaultConfiguration()
                                         .WithProvidedService(
                        GreetingService.Id,
                        x => x.WithUnaryMethod <GreetingRequest, GreetingResponse>("Hello", HandleAsync));

                    serverCreatedCount++;

                    return(ClientFactory.Instance.Create(optionsBuilder.Build()));
                });

                var appLauncher = RegisterDisposable(
                    new TestAppLauncher(
                        _testBrokerFixture.SharedInstance,
                        new Dictionary <string, TestClientFactory>
                {
                    { EchoServerClient.Id, echoServerFactory }
                }
                        )
                    );
                await appLauncher.StartAsync();
                var client = new EchoClient(s => s.WithBrokerWorkingDir(_testBrokerFixture.SharedInstance.WorkingDir));
                client.ConnectAsync().ShouldCompleteIn(Timeout5Sec);
                var callDescriptor = new MethodCallDescriptor(
                    ProvidedMethodReference.Create(GreetingService.Id, "Hello", EchoServerClient.Id));
                var call1 = client.CallInvoker.CallUnary(callDescriptor, new GreetingRequest {
                    Name = "Test"
                });
                var call2 = client.CallInvoker.CallUnary(callDescriptor, new GreetingRequest {
                    Name = "Test"
                });
                await Task.WhenAny(call1.AsTask(), call2.AsTask());
                WriteLog("Call 1 completed");
                await Task.WhenAll(call1.AsTask(), call2.AsTask());
                WriteLog("Call 2 completed");
                serverCreatedCount.ShouldBe(1);
                serverInvokedCount.ShouldBe(2);
            });
        }