Example #1
0
        public async Task TimeoutsAfterMultipleRetries()
        {
            var address = NetworkAddress.Parse("127.0.0.1:11001");

            using var _ = HConsole.Capture(consoleOptions => consoleOptions
                                           .ClearAll()
                                           .Configure().SetMaxLevel()
                                           .Configure(this).SetPrefix("TEST")
                                           .Configure <AsyncContext>().SetMinLevel()
                                           .Configure <SocketConnectionBase>().SetIndent(1).SetLevel(0).SetPrefix("SOCKET"));

            HConsole.WriteLine(this, "Begin");

            HConsole.WriteLine(this, "Start server");
            await using var server = new Server(address, async(xsvr, xconn, xmsg)
                                                => await HandleAsync(xsvr, xconn, xmsg, async(svr, conn, msg) =>
            {
                HConsole.WriteLine(svr, "Handle request (wait...)");
                await Task.Delay(500).CfAwait();

                HConsole.WriteLine(svr, "Respond with error.");
                var response = ErrorsServerCodec.EncodeResponse(new[]
                {
                    // make sure the error is retryable
                    new ErrorHolder(RemoteError.RetryableHazelcast, "classname", "message", Enumerable.Empty <StackTraceElement>())
                });

                //HConsole.WriteLine(svr, "Respond with success.");
                //var response = ClientPingServerCodec.EncodeResponse();

                response.CorrelationId = msg.CorrelationId;
                await conn.SendAsync(response).CfAwait();
            }), LoggerFactory);
            await server.StartAsync().CfAwait();

            HConsole.WriteLine(this, "Start client");
            var options = HazelcastOptions.Build(configure: (configuration, options) =>
            {
                options.Networking.Addresses.Add("127.0.0.1:11001");
                options.Messaging.RetryTimeoutSeconds = 3; // default value is 120s
            });

            await using var client = (HazelcastClient) await HazelcastClientFactory.StartNewClientAsync(options);

            HConsole.WriteLine(this, "Send message");
            var message = ClientPingServerCodec.EncodeRequest();

            // note: the error only happens *after* the server has responded
            // we could wait for the response for ever
            await AssertEx.ThrowsAsync <TaskTimeoutException>(async() =>
            {
                // server will respond w/ error every 500ms and client will retry
                // until the 3s retry timeout (options above) is reached
                await client.Cluster.Messaging.SendAsync(message).CfAwait();
            });

            await server.StopAsync().CfAwait();
        }
Example #2
0
        private ClientMessage CreateErrorMessage(RemoteError error)
        {
            // can we prepare server messages?
            var errorHolders = new List <ErrorHolder>
            {
                new ErrorHolder(error, "className", "message", Enumerable.Empty <StackTraceElement>())
            };

            return(ErrorsServerCodec.EncodeResponse(errorHolders));
        }
        private async ValueTask ServerHandler(Server s, ClientMessageConnection conn, ClientMessage msg)
        {
            async Task SendResponseAsync(ClientMessage response)
            {
                response.CorrelationId = msg.CorrelationId;
                response.Flags        |= ClientMessageFlags.BeginFragment | ClientMessageFlags.EndFragment;
                await conn.SendAsync(response).CfAwait();
            }

            async Task SendEventAsync(ClientMessage eventMessage, long correlationId)
            {
                eventMessage.CorrelationId = correlationId;
                eventMessage.Flags        |= ClientMessageFlags.BeginFragment | ClientMessageFlags.EndFragment;
                await conn.SendAsync(eventMessage).CfAwait();
            }

            async Task SendErrorAsync(RemoteError error, string message)
            {
                var errorHolders = new List <ErrorHolder>
                {
                    new ErrorHolder(error, "?", message, Enumerable.Empty <StackTraceElement>())
                };
                var response = ErrorsServerCodec.EncodeResponse(errorHolders);

                await SendResponseAsync(response).CfAwait();
            }

            var state   = (ServerState)s.State;
            var address = s.Address;

            const int partitionsCount = 2;

            switch (msg.MessageType)
            {
            // must handle auth
            case ClientAuthenticationServerCodec.RequestMessageType:
            {
                HConsole.WriteLine(this, $"(server{state.Id}) Authentication");
                var authRequest  = ClientAuthenticationServerCodec.DecodeRequest(msg);
                var authResponse = ClientAuthenticationServerCodec.EncodeResponse(
                    0, address, s.MemberId, SerializationService.SerializerVersion,
                    "4.0", partitionsCount, s.ClusterId, false);
                await SendResponseAsync(authResponse).CfAwait();

                break;
            }

            // must handle events
            case ClientAddClusterViewListenerServerCodec.RequestMessageType:
            {
                HConsole.WriteLine(this, $"(server{state.Id}) AddClusterViewListener");
                var addRequest  = ClientAddClusterViewListenerServerCodec.DecodeRequest(msg);
                var addResponse = ClientAddClusterViewListenerServerCodec.EncodeResponse();
                await SendResponseAsync(addResponse).CfAwait();

                _ = Task.Run(async() =>
                    {
                        await Task.Delay(500).CfAwait();

                        const int membersVersion = 1;
                        var memberVersion        = new MemberVersion(4, 0, 0);
                        var memberAttributes     = new Dictionary <string, string>();
                        var membersEventMessage  = ClientAddClusterViewListenerServerCodec.EncodeMembersViewEvent(membersVersion, new[]
                        {
                            new MemberInfo(state.MemberIds[0], state.Addresses[0], memberVersion, false, memberAttributes),
                            new MemberInfo(state.MemberIds[1], state.Addresses[1], memberVersion, false, memberAttributes),
                        });
                        await SendEventAsync(membersEventMessage, msg.CorrelationId).CfAwait();

                        await Task.Delay(500).CfAwait();

                        const int partitionsVersion = 1;
                        var partitionsEventMessage  = ClientAddClusterViewListenerServerCodec.EncodePartitionsViewEvent(partitionsVersion, new[]
                        {
                            new KeyValuePair <Guid, IList <int> >(state.MemberIds[0], new List <int> {
                                0
                            }),
                            new KeyValuePair <Guid, IList <int> >(state.MemberIds[1], new List <int> {
                                1
                            }),
                        });
                        await SendEventAsync(partitionsEventMessage, msg.CorrelationId).CfAwait();
                    });

                break;
            }

            // create object
            case ClientCreateProxyServerCodec.RequestMessageType:
            {
                HConsole.WriteLine(this, $"(server{state.Id}) CreateProxy");
                var createRequest  = ClientCreateProxyServerCodec.DecodeRequest(msg);
                var createResponse = ClientCreateProxiesServerCodec.EncodeResponse();
                await SendResponseAsync(createResponse).CfAwait();

                break;
            }

            // subscribe
            case MapAddEntryListenerServerCodec.RequestMessageType:
            {
                HConsole.WriteLine(this, $"(server{state.Id}) AddEntryListener");
                var addRequest = MapAddEntryListenerServerCodec.DecodeRequest(msg);
                state.Subscribed = true;
                state.SubscriptionCorrelationId = msg.CorrelationId;
                var addResponse = MapAddEntryListenerServerCodec.EncodeResponse(state.SubscriptionId);
                await SendResponseAsync(addResponse).CfAwait();

                break;
            }

            // unsubscribe
            // server 1 removes on first try, server 2 removes on later tries
            case MapRemoveEntryListenerServerCodec.RequestMessageType:
            {
                HConsole.WriteLine(this, $"(server{state.Id}) RemoveEntryListener");
                var removeRequest = MapRemoveEntryListenerServerCodec.DecodeRequest(msg);
                var removed       = state.Subscribed && removeRequest.RegistrationId == state.SubscriptionId;
                removed &= state.Id == 0 || state.UnsubscribeCount++ > 0;
                if (removed)
                {
                    state.Subscribed = false;
                }
                HConsole.WriteLine(this, $"(server{state.Id}) Subscribed={state.Subscribed}");
                var removeResponse = MapRemoveEntryListenerServerCodec.EncodeResponse(removed);
                await SendResponseAsync(removeResponse).CfAwait();

                break;
            }

            // add to map & trigger event
            case MapSetServerCodec.RequestMessageType:
            {
                HConsole.WriteLine(this, $"(server{state.Id}) Set");
                var setRequest  = MapSetServerCodec.DecodeRequest(msg);
                var setResponse = MapSetServerCodec.EncodeResponse();
                await SendResponseAsync(setResponse).CfAwait();

                HConsole.WriteLine(this, $"(server{state.Id}) Subscribed={state.Subscribed}");

                if (state.Subscribed)
                {
                    HConsole.WriteLine(this, $"(server{state.Id}) Trigger event");
                    var key        = setRequest.Key;
                    var value      = setRequest.Value;
                    var addedEvent = MapAddEntryListenerServerCodec.EncodeEntryEvent(key, value, value, value, (int)MapEventTypes.Added, state.SubscriptionId, 1);
                    await SendEventAsync(addedEvent, state.SubscriptionCorrelationId).CfAwait();
                }
                break;
            }

            // unexpected message = error
            default:
            {
                // RemoteError.Hazelcast or RemoteError.RetryableHazelcast
                var messageName = MessageTypeConstants.GetMessageTypeName(msg.MessageType);
                await SendErrorAsync(RemoteError.Hazelcast, $"MessageType {messageName} (0x{msg.MessageType:X}) not implemented.").CfAwait();

                break;
            }
            }
        }