private async Task HandleAsync(Server server, ClientMessageConnection connection, ClientMessage requestMessage, Func <Server, ClientMessageConnection, ClientMessage, ValueTask> handler) { var correlationId = requestMessage.CorrelationId; async Task SendResponseAsync(ClientMessage response) { response.CorrelationId = requestMessage.CorrelationId; response.Flags |= ClientMessageFlags.BeginFragment | ClientMessageFlags.EndFragment; await connection.SendAsync(response).CfAwait(); } async Task SendEventAsync(ClientMessage eventMessage, long correlationId) { eventMessage.CorrelationId = correlationId; eventMessage.Flags |= ClientMessageFlags.BeginFragment | ClientMessageFlags.EndFragment; await connection.SendAsync(eventMessage).CfAwait(); } switch (requestMessage.MessageType) { // handle authentication case ClientAuthenticationServerCodec.RequestMessageType: { var request = ClientAuthenticationServerCodec.DecodeRequest(requestMessage); var responseMessage = ClientAuthenticationServerCodec.EncodeResponse( 0, server.Address, server.MemberId, SerializationService.SerializerVersion, "4.0", 1, server.ClusterId, false); await SendResponseAsync(responseMessage).CfAwait(); break; } // handle events case ClientAddClusterViewListenerServerCodec.RequestMessageType: { var request = ClientAddClusterViewListenerServerCodec.DecodeRequest(requestMessage); var responseMessage = ClientAddClusterViewListenerServerCodec.EncodeResponse(); await SendResponseAsync(responseMessage).CfAwait(); _ = Task.Run(async() => { await Task.Delay(500).CfAwait(); var eventMessage = ClientAddClusterViewListenerServerCodec.EncodeMembersViewEvent(1, new[] { new MemberInfo(server.MemberId, server.Address, new MemberVersion(4, 0, 0), false, new Dictionary <string, string>()), }); await SendEventAsync(eventMessage, correlationId).CfAwait(); }); break; } // handle others default: await handler(server, connection, requestMessage).CfAwait(); break; } }
private async Task ReceiveMessageAsync(ClientMessageConnection connection, ClientMessage requestMessage) { var correlationId = requestMessage.CorrelationId; switch (requestMessage.MessageType) { // handle authentication case ClientAuthenticationServerCodec.RequestMessageType: { var request = ClientAuthenticationServerCodec.DecodeRequest(requestMessage); var responseMessage = ClientAuthenticationServerCodec.EncodeResponse( 0, _address, _memberId, SerializationService.SerializerVersion, "4.0", 1, _clusterId, false); await SendAsync(connection, responseMessage, correlationId).CAF(); break; } // handle events case ClientAddClusterViewListenerServerCodec.RequestMessageType: { var request = ClientAddClusterViewListenerServerCodec.DecodeRequest(requestMessage); var responseMessage = ClientAddClusterViewListenerServerCodec.EncodeResponse(); await SendAsync(connection, responseMessage, correlationId).CAF(); _ = Task.Run(async() => { await Task.Delay(500).CAF(); var eventMessage = ClientAddClusterViewListenerServerCodec.EncodeMembersViewEvent(1, new[] { new MemberInfo(_memberId, _address, new MemberVersion(4, 0, 0), false, new Dictionary <string, string>()), }); await SendAsync(connection, eventMessage, correlationId).CAF(); }); break; } // handle others default: await _handler(this, connection, requestMessage).CAF(); break; } }
public async Task CanRetryAndTimeout() { var address = NetworkAddress.Parse("127.0.0.1:11001"); HConsole.Configure(x => x.Configure(this).SetIndent(0).SetPrefix("TEST")); 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) => { async Task ResponseAsync(ClientMessage response) { response.CorrelationId = msg.CorrelationId; response.Flags |= ClientMessageFlags.BeginFragment | ClientMessageFlags.EndFragment; await conn.SendAsync(response).CfAwait(); } async Task EventAsync(ClientMessage eventMessage) { eventMessage.CorrelationId = msg.CorrelationId; eventMessage.Flags |= ClientMessageFlags.BeginFragment | ClientMessageFlags.EndFragment; await conn.SendAsync(eventMessage).CfAwait(); } switch (msg.MessageType) { // must handle auth case ClientAuthenticationServerCodec.RequestMessageType: var authRequest = ClientAuthenticationServerCodec.DecodeRequest(msg); var authResponse = ClientAuthenticationServerCodec.EncodeResponse( 0, address, Guid.NewGuid(), SerializationService.SerializerVersion, "4.0", 1, Guid.NewGuid(), false); await ResponseAsync(authResponse).CfAwait(); break; // must handle events case ClientAddClusterViewListenerServerCodec.RequestMessageType: var addRequest = ClientAddClusterViewListenerServerCodec.DecodeRequest(msg); var addResponse = ClientAddClusterViewListenerServerCodec.EncodeResponse(); await ResponseAsync(addResponse).CfAwait(); _ = Task.Run(async() => { await Task.Delay(500).CfAwait(); var eventMessage = ClientAddClusterViewListenerServerCodec.EncodeMembersViewEvent(1, new[] { new MemberInfo(Guid.NewGuid(), address, new MemberVersion(4, 0, 0), false, new Dictionary <string, string>()), }); await EventAsync(eventMessage).CfAwait(); }); break; default: HConsole.WriteLine(svr, "Respond with error."); var response = CreateErrorMessage(RemoteError.RetryableHazelcast); await ResponseAsync(response).CfAwait(); break; } }), 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"); }); await using var client = (HazelcastClient) await HazelcastClientFactory.StartNewClientAsync(options); HConsole.WriteLine(this, "Send message"); var message = ClientPingServerCodec.EncodeRequest(); var token = new CancellationTokenSource(3_000).Token; await AssertEx.ThrowsAsync <TaskCanceledException>(async() => await client.Cluster.Messaging.SendAsync(message, token).CfAwait()); // TODO dispose the client, the server await server.StopAsync().CfAwait(); }
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; } } }