Ejemplo n.º 1
0
        public async Task <MessageRoute> RouteForDestination(Envelope envelope)
        {
            envelope.Destination = _lookup.Resolve(envelope.Destination);

            var messageType = envelope.Message.GetType();
            var routes      = await Route(messageType);

            var candidate = routes.FirstOrDefault(x => x.MatchesEnvelope(envelope));

            if (candidate != null)
            {
                return(candidate);
            }


            var modelWriter = _serializers.WriterFor(messageType);
            var contentType = envelope.ContentType ?? envelope.AcceptedContentTypes.Intersect(modelWriter.ContentTypes).FirstOrDefault()
                              ?? "application/json";


            var channel = _channels.GetOrBuildChannel(envelope.Destination);

            return(new MessageRoute(
                       messageType,
                       modelWriter,
                       channel,
                       contentType));
        }
Ejemplo n.º 2
0
        private async Task <int> recoverFrom(Uri destination, IDocumentSession session)
        {
            try
            {
                var channel = _channels.GetOrBuildChannel(destination);

                if (channel.Latched)
                {
                    return(0);
                }

                var outgoing = await session.Connection.CreateCommand(_findOutgoingEnvelopesSql)
                               .With("destination", destination.ToString(), NpgsqlDbType.Varchar)
                               .ExecuteToEnvelopes();

                var filtered = filterExpired(session, outgoing);

                // Might easily try to do this in the time between starting
                // and having the data fetched. Was able to make that happen in
                // (contrived) testing
                if (channel.Latched || !filtered.Any())
                {
                    return(0);
                }

                session.MarkOwnership(_marker.Outgoing, _marker.CurrentNodeId, filtered);

                await session.SaveChangesAsync();

                _logger.RecoveredOutgoing(filtered);

                foreach (var envelope in filtered)
                {
                    try
                    {
                        await channel.QuickSend(envelope);
                    }
                    catch (Exception e)
                    {
                        _logger.LogException(e, message: $"Unable to enqueue {envelope} for sending");
                    }
                }

                return(outgoing.Count());
            }
            catch (UnknownTransportException e)
            {
                _logger.LogException(e, message: $"Could not resolve a channel for {destination}");

                await DeleteFromOutgoingEnvelopes(session, TransportConstants.AnyNode, destination);

                await session.SaveChangesAsync();

                return(0);
            }
        }
Ejemplo n.º 3
0
        public Task Enqueue <T>(T message)
        {
            var isDurable = _settings.Workers.ShouldBeDurable(typeof(T));
            var uri       = isDurable ? TransportConstants.DurableLoopbackUri : TransportConstants.LoopbackUri;

            var channel = _channels.GetOrBuildChannel(uri);


            var envelope = new Envelope(message);

            return(channel.Send(envelope));
        }
Ejemplo n.º 4
0
        private Envelope buildAcknowledgement()
        {
            var ack = new Envelope
            {
                ParentId    = Envelope.Id,
                Destination = Envelope.ReplyUri,
                ResponseId  = Envelope.Id,
                SagaId      = Envelope.SagaId,
                Message     = new Acknowledgement {
                    CorrelationId = Envelope.Id
                },
                Route = new MessageRoute(typeof(Acknowledgement), Envelope.ReplyUri, "application/json")
                {
                    Channel = _channels.GetOrBuildChannel(Envelope.ReplyUri),
                },
                Writer = _serialization.JsonWriterFor(typeof(Acknowledgement))
            };

            return(ack);
        }
Ejemplo n.º 5
0
        private async Task <int> recoverFrom(Uri destination, SqlConnection conn)
        {
            try
            {
                Envelope[]      filtered = null;
                List <Envelope> outgoing = null;

                if (_channels.GetOrBuildChannel(destination).Latched)
                {
                    return(0);
                }

                var tx = conn.BeginTransaction();

                try
                {
                    outgoing = await conn.CreateCommand(tx, _findOutgoingEnvelopesSql)
                               .With("destination", destination.ToString(), SqlDbType.VarChar)
                               .ExecuteToEnvelopes();

                    filtered = await filterExpired(conn, tx, outgoing);

                    // Might easily try to do this in the time between starting
                    // and having the data fetched. Was able to make that happen in
                    // (contrived) testing
                    if (_channels.GetOrBuildChannel(destination).Latched || !filtered.Any())
                    {
                        tx.Rollback();
                        return(0);
                    }

                    await markOwnership(conn, tx, filtered);


                    tx.Commit();
                }
                catch (Exception)
                {
                    tx.Rollback();
                    throw;
                }

                _logger.RecoveredOutgoing(filtered);

                foreach (var envelope in filtered)
                {
                    try
                    {
                        await _channels.GetOrBuildChannel(destination).QuickSend(envelope);
                    }
                    catch (Exception e)
                    {
                        _logger.LogException(e, message: $"Unable to enqueue {envelope} for sending");
                    }
                }

                return(outgoing.Count());
            }
            catch (UnknownTransportException e)
            {
                _logger.LogException(e, message: $"Could not resolve a channel for {destination}");

                var tx = conn.BeginTransaction();
                await DeleteFromOutgoingEnvelopes(conn, TransportConstants.AnyNode, destination, tx);

                tx.Commit();

                return(0);
            }
        }