public async Task SendAckAsync(string clientId, IFlowPacket ack, IMqttChannel <IPacket> channel, PendingMessageStatus status = PendingMessageStatus.PendingToSend) { if ((ack.Type == MqttPacketType.PublishReceived || ack.Type == MqttPacketType.PublishRelease) && status == PendingMessageStatus.PendingToSend) { SavePendingAcknowledgement(ack, clientId); } if (!channel.IsConnected) { return; } await channel.SendAsync(ack) .ConfigureAwait(continueOnCapturedContext: false); if (ack.Type == MqttPacketType.PublishReceived) { await MonitorAckAsync <PublishRelease> (ack, clientId, channel) .ConfigureAwait(continueOnCapturedContext: false); } else if (ack.Type == MqttPacketType.PublishRelease) { await MonitorAckAsync <PublishComplete> (ack, clientId, channel) .ConfigureAwait(continueOnCapturedContext: false); } }
async Task SendPendingAcknowledgementsAsync(ClientSession session, IMqttChannel <IPacket> channel) { foreach (PendingAcknowledgement pendingAcknowledgement in session.GetPendingAcknowledgements()) { IFlowPacket ack = default; if (pendingAcknowledgement.Type == MqttPacketType.PublishReceived) { ack = new PublishReceived(pendingAcknowledgement.PacketId); } else if (pendingAcknowledgement.Type == MqttPacketType.PublishRelease) { ack = new PublishRelease(pendingAcknowledgement.PacketId); } await _senderFlow.SendAckAsync(session.Id, ack, channel); } }
public override async Task ExecuteAsync(string clientId, IPacket input, IMqttChannel <IPacket> channel) { if (!_senderRules.TryGetValue(input.Type, out Func <string, ushort, IFlowPacket> senderRule)) { return; } if (!(input is IFlowPacket flowPacket)) { return; } IFlowPacket ackPacket = senderRule(clientId, flowPacket.PacketId); if (ackPacket != default(IFlowPacket)) { await SendAckAsync(clientId, ackPacket, channel); } }
protected async Task MonitorAckAsync <T> (IFlowPacket sentMessage, string clientId, IMqttChannel <IPacket> channel) where T : IFlowPacket { var intervalSubscription = Observable .Interval(TimeSpan.FromSeconds(configuration.WaitTimeoutSecs), NewThreadScheduler.Default) .Subscribe(async _ => { if (channel.IsConnected) { tracer.Warn(Properties.Resources.PublishFlow_RetryingQoSFlow, sentMessage.Type, clientId); await channel.SendAsync(sentMessage); } }); await channel .ReceiverStream .ObserveOn(NewThreadScheduler.Default) .OfType <T> () .FirstOrDefaultAsync(x => x.PacketId == sentMessage.PacketId); intervalSubscription.Dispose(); }
void SavePendingAcknowledgement(IFlowPacket ack, string clientId) { if (ack.Type != MqttPacketType.PublishReceived && ack.Type != MqttPacketType.PublishRelease) { return; } var unacknowledgeMessage = new PendingAcknowledgement { PacketId = ack.PacketId, Type = ack.Type }; var session = sessionRepository.Get(s => s.ClientId == clientId); if (session == null) { throw new MqttException(string.Format(Properties.Resources.SessionRepository_ClientSessionNotFound, clientId)); } session.AddPendingAcknowledgement(unacknowledgeMessage); sessionRepository.Update(session); }
void SavePendingAcknowledgement(IFlowPacket ack, string clientId) { if (ack.Type != MqttPacketType.PublishReceived && ack.Type != MqttPacketType.PublishRelease) { return; } PendingAcknowledgement unacknowledgeMessage = new PendingAcknowledgement { PacketId = ack.PacketId, Type = ack.Type }; ClientSession session = sessionRepository.Read(clientId); if (session == null) { throw new MqttException(ClientProperties.SessionRepository_ClientSessionNotFound(clientId)); } session.AddPendingAcknowledgement(unacknowledgeMessage); sessionRepository.Update(session); }