public void ReadyMessagesShouldSerialize(
            uint version,
            ulong userId,
            int sequenceNumber
            )
        {
            var serializer     = CreateSerializer();
            var gatewayMessage = new GatewayMessage
            {
                OpCode         = GatewayOpCode.Dispatch,
                SequenceNumber = sequenceNumber,
                EventName      = "READY",
                Data           = new ReadyEvent
                {
                    GatewayVersion = version,
                    User           = new User
                    {
                        Id = userId,
                    },
                },
            };

            var result = serializer.Serialize(gatewayMessage);

            result.Should().MatchRegex("\"op\":[ ]?0", "Op Code should equal 0.");
            result.Should().MatchRegex($"\"s\":[ ]?{sequenceNumber}", $"Sequence number should equal {sequenceNumber}");
            result.Should().MatchRegex($"\"t\":[ ]?\"READY\"", $"Event name should equal READY");
            result.Should().MatchRegex($"\"d\":[ ]?{{(.*?)\"v\":[ ]?{version}(.*?)}}", $"Data should contain version of {version}");
            result.Should().MatchRegex($"\"d\":[ ]?{{(.*?)\"user\":[ ]?{{(.*?)\"id\":[ ]?\"{userId}\"(.*?)}}(.*?)}}", $"Data should contain userId of {userId}");
        }
示例#2
0
 public bool IsCommand(GatewayMessage message)
 {
     return(message.Content.Length > 0 &&
            message.Content.TrimStart()[0] == '?' &&
            message.Author.Id != _clientInfoRepository.GetClientInfo().User.Id);
     // Disable bot possibility to handle own commands
 }
示例#3
0
            public async Task RunShouldWaitUntilTheWebSocketIsOpen(
                int sequenceNumber,
                [Substitute] IClientWebSocket clientWebSocket,
                [Frozen, Substitute] IGatewayService gateway,
                [Frozen, Substitute] IChannel <GatewayMessage> channel,
                [Frozen, Substitute] IGatewayUtilsFactory factory,
                [Target] DefaultGatewayTxWorker worker
                )
            {
                var tries   = 0;
                var message = new GatewayMessage {
                    SequenceNumber = sequenceNumber
                };
                var cancellationToken = new CancellationToken(false);

                clientWebSocket.State.Returns(WebSocketState.Connecting);

                channel.Read(Any <CancellationToken>()).Returns(new ValueTask <GatewayMessage>(message));
                channel.WaitToRead(Any <CancellationToken>()).Returns(true);
                factory.CreateDelay(Any <uint>(), Any <CancellationToken>()).Returns(async x =>
                {
                    if (++tries == 2)
                    {
                        clientWebSocket.State.Returns(WebSocketState.Open);
                    }

                    await Task.CompletedTask;
                });

                await worker.Start(gateway, clientWebSocket);

                await worker.Run(cancellationToken);

                await factory.Received(2).CreateDelay(100, Is(cancellationToken));
            }
示例#4
0
            public async Task RunShouldReadFromChannelIfWaitToReadReturnsTrue(
                int sequenceNumber,
                [Substitute] IClientWebSocket clientWebSocket,
                [Frozen, Substitute] IGatewayService gateway,
                [Frozen, Substitute] IChannel <GatewayMessage> channel,
                [Frozen, Substitute] IGatewayUtilsFactory factory,
                [Target] DefaultGatewayTxWorker worker
                )
            {
                var message = new GatewayMessage {
                    SequenceNumber = sequenceNumber
                };
                var cancellationToken = new CancellationToken(false);

                channel.Read(Any <CancellationToken>()).Returns(new ValueTask <GatewayMessage>(message));

                clientWebSocket.State.Returns(WebSocketState.Open);
                await worker.Start(gateway, clientWebSocket);

                await worker.Run(cancellationToken);

                await channel.Received().WaitToRead(Is(cancellationToken));

                await channel.Received().Read(Is(cancellationToken));
            }
示例#5
0
    public static Metadata GetMeta(this GatewayMessage gatewayMessage, IMessageConsumeContext context)
    {
        var(_, _, metadata) = gatewayMessage;
        var meta = metadata == null ? new Metadata() : new Metadata(metadata);

        return(meta.WithCausationId(context.MessageId));
    }
示例#6
0
        public async Task Produce(GatewayMessage message)
        {
            using var producer = new ProducerBuilder <Null, string>(_config)
                                 .SetErrorHandler((_, e) =>
            {
                _logger.LogError($"Kafka Error {e.Code}: {e.Reason}");
            })
                                 .Build();

            try
            {
                var jsonMessage = JsonConvert.SerializeObject(message);

                var dr = await producer.ProduceAsync(
                    topic : _topic,
                    message : new Message <Null, string> {
                    Value = jsonMessage
                }
                    );

                _logger.LogInformation($"Delivered '{dr.Value}' to '{dr.TopicPartitionOffset}' with status {dr.Status.ToString()}");
            }
            catch (ProduceException <Null, string> e)
            {
                _logger.LogError($"Delivery failed: {e.Error.Reason}");
            }
            catch (Exception ex) {
                _logger.LogError($"Delivery failed: {ex.Message}");
            }
        }
示例#7
0
文件: Program.cs 项目: Mikibot/retsu
        private static Task OnPacketReceivedAsync(GatewayMessage arg)
        {
            if (arg.EventName == "READY")
            {
                var ready = JsonSerializer.Deserialize <GatewayReadyPacket>(
                    ((JsonElement)arg.Data).GetRawText(), options);
                Log.Message($"Shard {ready.CurrentShard} is connected");
            }

            if (config.IgnorePackets.Contains(arg.EventName))
            {
                return(Task.CompletedTask);
            }

            if (!queueSet.ContainsKey(arg.EventName))
            {
                var queue = GetQueueNameFromEventName(arg.EventName);
                pusherModel.QueueDeclare(queue, true, false, false);
                pusherModel.QueueBind(queue, "gateway", arg.EventName);
                queueSet.TryAdd(arg.EventName, null);
            }

            try
            {
                pusherModel.BasicPublish(
                    "gateway", arg.EventName, body: Encoding.UTF8.GetBytes(JsonSerializer.Serialize(arg)));
            }
            catch (AlreadyClosedException)
            {
                Log.Warning($"Event '{arg.EventName}' missed due to AMQP client closed.");
            }

            return(Task.CompletedTask);
        }
示例#8
0
            public async Task RunShouldRouteTheMessageIfEndOfMessageIsReached(
                byte[] bytes,
                uint interval,
                int sequenceNumber,
                [Frozen, Substitute] Stream stream,
                [Frozen, Substitute] IChannel <GatewayMessageChunk> channel,
                [Frozen, Substitute] IGatewayUtilsFactory factory,
                [Frozen, Substitute] IGatewayService gateway,
                [Frozen, Substitute] ISerializer serializer,
                [Frozen, Substitute] IEventRouter router,
                [Target] DefaultGatewayRxWorker worker
                )
            {
                var @event = new HelloEvent {
                    HeartbeatInterval = interval
                };
                var message = new GatewayMessage {
                    SequenceNumber = sequenceNumber, Data = @event
                };
                var cancellationToken = new CancellationToken(false);

                serializer.Deserialize <GatewayMessage>(Any <Stream>(), Any <CancellationToken>()).Returns(message);
                channel.Read(Any <CancellationToken>()).Returns(new GatewayMessageChunk(bytes, bytes.Length, true));

                await worker.Start(gateway);

                await worker.Run(cancellationToken);

                await router.Received().Route(Is(@event), Is(cancellationToken));
            }
示例#9
0
            public async Task RunShouldNotUpdateSequenceNumberIfEndOfMessageIsReachedButSequenceNumberIsNull(
                byte[] bytes,
                int sequenceNumber,
                [Frozen, Substitute] Stream stream,
                [Frozen, Substitute] IChannel <GatewayMessageChunk> channel,
                [Frozen, Substitute] IGatewayUtilsFactory factory,
                [Frozen, Substitute] IGatewayService gateway,
                [Frozen, Substitute] ISerializer serializer,
                [Target] DefaultGatewayRxWorker worker
                )
            {
                var message = new GatewayMessage {
                    SequenceNumber = null
                };

                serializer.Deserialize <GatewayMessage>(Any <Stream>(), Any <CancellationToken>()).Returns(message);
                channel.Read(Any <CancellationToken>()).Returns(new GatewayMessageChunk(bytes, bytes.Length, true));

                gateway.SequenceNumber = sequenceNumber;

                await worker.Start(gateway);

                await worker.Run();

                gateway.SequenceNumber.Should().Be(sequenceNumber);
            }
        public void ResumeMessagesShouldSerialize(
            string token,
            string sessionId,
            int sequenceNumber
            )
        {
            var serializer     = CreateSerializer();
            var gatewayMessage = new GatewayMessage
            {
                OpCode = GatewayOpCode.Resume,
                Data   = new ResumeEvent
                {
                    Token          = token,
                    SessionId      = sessionId,
                    SequenceNumber = sequenceNumber,
                },
            };

            var result = serializer.Serialize(gatewayMessage);

            result.Should().MatchRegex("\"op\":[ ]?6", "Op Code should equal 6.");
            result.Should().MatchRegex($"\"d\":[ ]?{{(.*?)\"token\":[ ]?\"{token}\"(.*?)}}", $"Data should contain the token.");
            result.Should().MatchRegex($"\"d\":[ ]?{{(.*?)\"session_id\":[ ]?\"{sessionId}\"(.*?)}}", $"Data should contain the session id.");
            result.Should().MatchRegex($"\"d\":[ ]?{{(.*?)\"seq\":[ ]?{sequenceNumber}(.*?)}}", $"Data should contain the sequence number.");
        }
示例#11
0
            public async Task RunShouldWriteBytesToWebSocket(
                int sequenceNumber,
                byte[] bytes,
                [Substitute] IClientWebSocket clientWebSocket,
                [Frozen, Substitute] IGatewayService gateway,
                [Frozen, Substitute] IChannel <GatewayMessage> channel,
                [Frozen, Substitute] ISerializer serializer,
                [Frozen, Substitute] IGatewayUtilsFactory factory,
                [Target] DefaultGatewayTxWorker worker
                )
            {
                var message = new GatewayMessage {
                    SequenceNumber = sequenceNumber
                };
                var cancellationToken = new CancellationToken(false);

                serializer.SerializeToBytes(Any <GatewayMessage>()).Returns(bytes);
                channel.Read(Any <CancellationToken>()).Returns(new ValueTask <GatewayMessage>(message));

                clientWebSocket.State.Returns(WebSocketState.Open);
                await worker.Start(gateway, clientWebSocket);

                await worker.Run(cancellationToken);

                await clientWebSocket.Received().Send(Is <ArraySegment <byte> >(bytes), Is(WebSocketMessageType.Text), Is(true), Is(cancellationToken));
            }
        protected sealed override async Task ProcessMessage(GatewayMessage message, CancellationToken cancellationToken)
        {
            try
            {
                switch (message.CommandName)
                {
                case nameof(GetAllProductsResponseCommand):
                {
                    var getAllProductsCommand = JsonConvert.DeserializeObject <GetAllProductsResponseCommand>(message.Command);
                    if (getAllProductsCommand != null)
                    {
                        await _mediator.Send(getAllProductsCommand, cancellationToken);
                    }
                    else
                    {
                        LogIncorrectCommandBody();
                    }

                    /* TODO: ---
                     * var requestHandler = new GetAllProductsResponseHandler(_productTaskKeeper);
                     * requestHandler.Handle(command, CancellationToken.None);
                     */
                    break;
                }

                case nameof(GetProductByIdResponseCommand):
                    var getProductByIdCommand = JsonConvert.DeserializeObject <GetProductByIdResponseCommand>(message.Command);
                    if (getProductByIdCommand != null)
                    {
                        await _mediator.Send(getProductByIdCommand, cancellationToken);
                    }
                    else
                    {
                        LogIncorrectCommandBody();
                    }
                    break;

                case nameof(CreateProductResponseCommand):
                    var createProductResponseCommand = JsonConvert.DeserializeObject <CreateProductResponseCommand>(message.Command);
                    if (createProductResponseCommand != null)
                    {
                        await _mediator.Send(createProductResponseCommand, cancellationToken);
                    }
                    else
                    {
                        LogIncorrectCommandBody();
                    }
                    break;

                default:
                    _logger.LogWarning($"Unhandled command: {message.CommandName}");
                    break;
                }
            }
            catch (Exception e)
            {
                _logger.LogError(e, $"Unhandled {nameof(ProcessMessage)} error");
            }
        }
示例#13
0
        public async Task Handle(GetAllProductsQuery command)
        {
            var products        = _repository.GetAll().ToList();
            var responseCommand = new GetAllProductsResponseCommand(products, command.CommandId);
            var gatewayMessage  = new GatewayMessage(responseCommand);

            await _producer.Produce(gatewayMessage);
        }
 /// <summary>
 /// Sends a Heartbeat through the gateway.
 /// </summary>
 /// <param name="cancellationToken">Token used to cancel the operation.</param>
 /// <returns>The resulting task.</returns>
 public async Task Heartbeat(CancellationToken cancellationToken)
 {
     cancellationToken.ThrowIfCancellationRequested();
     var message = new GatewayMessage {
         OpCode = GatewayOpCode.Heartbeat, Data = (HeartbeatEvent?)SequenceNumber
     };
     await txWorker.Emit(message, cancellationToken);
 }
示例#15
0
文件: Command.cs 项目: Serfin/Crabot
 public Command(GatewayMessage message)
 {
     Member            = message.Member;
     Author            = message.Author;
     Arguments         = message.Content.Split(' ', StringSplitOptions.RemoveEmptyEntries)[1..];
     CommandName       = message.Content.Split(' ')[0].ToLowerInvariant()[1..];
     CalledFromChannel = message.ChannelId;
     CalledFromGuild   = message.GuildId;
 }
        public async Task Handle(GetProductByIdQuery command)
        {
            var product = await _repository.GetProductByIdAsync(command.Id);

            var responseCommand = new GetProductByIdResponseCommand(product, command.CommandId);
            var gatewayMessage  = new GatewayMessage(responseCommand);

            await _producer.Produce(gatewayMessage);
        }
        protected sealed override async Task ProcessMessage(GatewayMessage message, CancellationToken cancellationToken)
        {
            switch (message.CommandName)
            {
            case nameof(GetAllProductsQuery):
            {
                var getAllProductsQuery = JsonConvert.DeserializeObject <GetAllProductsQuery>(message.Command);
                if (getAllProductsQuery != null)
                {
                    var requestHandler = new GetAllProductsRequestHandler(_productRepository, _producer);
                    await requestHandler.Handle(getAllProductsQuery);
                }
                else
                {
                    LogIncorrectCommandBody();
                }
                break;
            }

            case nameof(GetProductByIdQuery):
            {
                var getProductByIdQuery = JsonConvert.DeserializeObject <GetProductByIdQuery>(message.Command);
                if (getProductByIdQuery != null)
                {
                    var requestHandler = new GetProductByIdHandle(_productRepository, _producer);
                    await requestHandler.Handle(getProductByIdQuery);
                }
                else
                {
                    LogIncorrectCommandBody();
                }
                break;
            }

            case nameof(CreateProductRequestCommand):
            {
                var createProductRequestCommand = JsonConvert.DeserializeObject <CreateProductRequestCommand>(message.Command);
                if (createProductRequestCommand != null)
                {
                    var requestHandler = new CreateProductRequestHandler(_productRepository, _producer);
                    await requestHandler.Handle(createProductRequestCommand);
                }
                else
                {
                    LogIncorrectCommandBody();
                }
                break;
            }

            default:
                _logger.LogWarning($"Unhandled command: {message.CommandName}");
                break;
            }
        }
        public async Task Handle(CreateProductRequestCommand command)
        {
            var product = await _repository.AddAsync(new Product
            {
                Name           = command.Name,
                Price          = command.Price,
                ExpirationDate = command.ExpirationDate
            });

            var responseCommand = new CreateProductResponseCommand(product, command.CommandId);
            var gatewayMessage  = new GatewayMessage(responseCommand);

            await _producer.Produce(gatewayMessage);
        }
示例#19
0
        public void Bot_cannot_handle_its_own_commands()
        {
            var testCommand = new GatewayMessage
            {
                Content = "?test-command",
                Author  = new Author
                {
                    Id = crabotFakeAuthorId
                }
            };

            var validationResult = _commandValidator.IsCommand(testCommand);

            Assert.False(validationResult);
        }
示例#20
0
        public void Command_with_prefix_and_random_author_id_is_valid_command()
        {
            var testCommand = new GatewayMessage
            {
                Content = "?test-command",
                Author  = new Author
                {
                    Id = It.IsAny <string>()
                }
            };

            var validationResult = _commandValidator.IsCommand(testCommand);

            Assert.True(validationResult);
        }
示例#21
0
        public static CommandMessage FromGatewayMessage <T>(int shardId, GatewayMessage message)
            where T : class
        {
            if (message.OpCode == null)
            {
                return(null);
            }

            return(new CommandMessage
            {
                ShardId = shardId,
                Opcode = message.OpCode.Value,
                Data = message.Data as T
            });
        }
        public void HeartbeatMessagesShouldSerialize(
            int sequenceNumber
            )
        {
            var serializer     = CreateSerializer();
            var gatewayMessage = new GatewayMessage
            {
                OpCode = GatewayOpCode.Heartbeat,
                Data   = new HeartbeatEvent(sequenceNumber),
            };

            var result = serializer.Serialize(gatewayMessage);

            result.Should().MatchRegex("\"op\":[ ]?1", "Op Code should equal 1.");
            result.Should().MatchRegex($"\"d\":[ ]?{sequenceNumber}", $"Data should equal the sequence number ({sequenceNumber})");
        }
            public async Task SendShouldEmitTheMessageToTheTxWorker(
                int sequenceNumber,
                [Frozen, Substitute] IGatewayTxWorker txWorker,
                [Target] DefaultGatewayService gateway
                )
            {
                var message = new GatewayMessage {
                    SequenceNumber = sequenceNumber
                };
                var cancellationToken = new CancellationToken(false);

                await gateway.StartAsync();

                await gateway.Send(message, cancellationToken);

                await txWorker.Received().Emit(Is(message), Is(cancellationToken));
            }
            public async Task SendShouldThrowIfTheOperationWasCanceled(
                int sequenceNumber,
                [Frozen, Substitute] IGatewayTxWorker txWorker,
                [Target] DefaultGatewayService gateway
                )
            {
                var message = new GatewayMessage {
                    SequenceNumber = sequenceNumber
                };
                var cancellationToken = new CancellationToken(false);

                await gateway.StartAsync();

                var         operationCancellationToken = new CancellationToken(true);
                Func <Task> func = () => gateway.Send(message, operationCancellationToken);

                await func.Should().ThrowAsync <OperationCanceledException>();
            }
示例#25
0
            public async Task EmitShouldEmitTheMessageToTheChannel(
                int sequenceNumber,
                [Frozen, Substitute] IGatewayService gateway,
                [Frozen, Substitute] IClientWebSocket webSocket,
                [Frozen, Substitute] IChannel <GatewayMessage> channel,
                [Target] DefaultGatewayTxWorker worker
                )
            {
                var message = new GatewayMessage {
                    SequenceNumber = sequenceNumber
                };
                var cancellationToken = new CancellationToken(false);

                await worker.Start(gateway, webSocket);

                await worker.Emit(message, cancellationToken);

                await channel.Received().Write(Is(message), Is(cancellationToken));
            }
示例#26
0
            public async Task EmitShouldThrowIfTheOperationWasCanceled(
                int sequenceNumber,
                [Substitute] IClientWebSocket clientWebSocket,
                [Frozen, Substitute] IGatewayService gateway,
                [Target] DefaultGatewayTxWorker worker
                )
            {
                var message = new GatewayMessage {
                    SequenceNumber = sequenceNumber
                };
                var cancellationToken = new CancellationToken(false);

                await worker.Start(gateway, clientWebSocket);

                var         operationCancellationToken = new CancellationToken(true);
                Func <Task> func = () => worker.Emit(message, operationCancellationToken);

                await func.Should().ThrowAsync <OperationCanceledException>();
            }
        public async Task <Product> Handle(GetProductByIdQuery request, CancellationToken cancellationToken)
        {
            var message = new GatewayMessage(request);
            var tcs     = new TaskCompletionSource <object>();

            _taskKeeper.Keep(request.CommandId, tcs);
            await _producer.Produce(message);

            var result = await tcs.Task;

            if (result is Product product)
            {
                return(product);
            }
            else
            {
                throw new GatewayException("Incorrect response format");
            }
        }
        public void HelloMessagesShouldSerialize(
            uint interval,
            int sequenceNumber
            )
        {
            var serializer     = CreateSerializer();
            var gatewayMessage = new GatewayMessage
            {
                OpCode         = GatewayOpCode.Hello,
                SequenceNumber = sequenceNumber,
                Data           = new HelloEvent
                {
                    HeartbeatInterval = interval,
                },
            };

            var result = serializer.Serialize(gatewayMessage);

            result.Should().MatchRegex("\"op\":[ ]?10", "Op Code should equal 10.");
            result.Should().MatchRegex($"\"s\":[ ]?{sequenceNumber}", $"Sequence number should equal {sequenceNumber}");
            result.Should().MatchRegex($"\"d\":[ ]?{{[ ]?\"heartbeat_interval\":[ ]?{interval}[ ]?}}", $"Data should contain heartbeat interval of {interval}");
        }
示例#29
0
        /// <summary>
        /// Adds a new message.
        /// </summary>
        /// <param name="clientId">Client to add.</param>
        /// <param name="timeReceived">Time the message was received</param>
        /// <param name="message">The original message.</param>
        /// <param name="headers">The headers.</param>
        /// <returns><value>true</value> if successfully added.</returns>
        public bool InsertMessage(string clientId, DateTime timeReceived, Stream message, IDictionary <string, string> headers)
        {
            using (var session = SessionFactory.OpenSession())
                using (var tx = session.BeginTransaction(IsolationLevel.ReadCommitted))
                {
                    var gatewayMessage = session.Get <GatewayMessage>(clientId);

                    if (gatewayMessage != null)
                    {
                        tx.Commit();
                        return(false);
                    }

                    gatewayMessage = new GatewayMessage
                    {
                        Id              = clientId,
                        Headers         = ConvertDictionaryToString(headers),
                        TimeReceived    = timeReceived,
                        OriginalMessage = new byte[message.Length],
                    };

                    message.Read(gatewayMessage.OriginalMessage, 0, (int)message.Length);


                    try
                    {
                        session.Save(gatewayMessage);
                        tx.Commit();
                    }
                    catch (GenericADOException)
                    {
                        tx.Rollback();
                        return(false);
                    }
                }

            return(true);
        }
示例#30
0
 public void On(string channel, GatewayMessage callback)
 {
     channels[channel] = callback;
 }
示例#31
0
        /// <summary>
        /// Adds a new message.
        /// </summary>
        /// <param name="clientId">Client to add.</param>
        /// <param name="timeReceived">Time the message was received</param>
        /// <param name="message">The original message.</param>
        /// <param name="headers">The headers.</param>
        /// <returns><value>true</value> if successfully added.</returns>
        public bool InsertMessage(string clientId, DateTime timeReceived, Stream message, IDictionary<string, string> headers)
        {
            using (var session = SessionFactory.OpenSession())
            using (var tx = session.BeginTransaction(IsolationLevel.ReadCommitted))
            {
                var gatewayMessage = session.Get<GatewayMessage>(clientId);

                if (gatewayMessage != null)
                {
                    tx.Commit();
                    return false;
                }

                gatewayMessage = new GatewayMessage
                                         {
                                             Id = clientId,
                                             Headers = ConvertDictionaryToString(headers),
                                             TimeReceived = timeReceived,
                                             OriginalMessage = new byte[message.Length],
                                         };

                message.Read(gatewayMessage.OriginalMessage, 0, (int) message.Length);

                try
                {
                    session.Save(gatewayMessage);
                    tx.Commit();
                }
                catch (GenericADOException)
                {
                    tx.Rollback();
                    return false;
                }
            }

            return true;
        }
 /// <inheritdoc />
 public async Task Emit(GatewayMessage message, CancellationToken cancellationToken)
 {
     cancellationToken.ThrowIfCancellationRequested();
     ThrowIfNotRunning();
     await channel.Write(message, cancellationToken);
 }