Restarted AMQP Source does not recreates auto-delete queue
vasily-kirichenko opened this issue · comments
let system = ActorSystem.Create("test", ConfigurationFactory.Load())
let mat = ActorMaterializer.Create(system, ActorMaterializerSettings.Create(system).WithSupervisionStrategy(Deciders.ResumingDecider))
let connSettings =
AmqpConnectionDetails
.Create("localhost", 5672)
.WithAutomaticRecoveryEnabled(true)
.WithNetworkRecoveryInterval(TimeSpan.FromSeconds 1.0)
.WithTopologyRecoveryEnabled(true)
let taskQueue = "task-queue"
let taskQueueDecl = QueueDeclaration.Create(taskQueue).WithDurable(false).WithAutoDelete(true)
// send 10 tasks
let sink = AmqpSink.CreateSimple(AmqpSinkSettings.Create(connSettings).WithRoutingKey(taskQueue).WithDeclarations(taskQueueDecl))
Source.From([1..10]).Select(fun x -> x |> string |> ByteString.FromString).RunWith(sink, mat).Wait()
let reportQueue = QueueDeclaration.Create("report-queue").WithDurable(false).WithAutoDelete(true)
RestartSource
.WithBackoff((fun _ ->
AmqpSource.CommittableSource(NamedQueueSourceSettings.Create(connSettings, taskQueue), bufferSize = 100)),
TimeSpan.FromSeconds 1.0, TimeSpan.FromSeconds 2.0, 0.2)
.Throttle(1, TimeSpan.FromMilliseconds 1000.0, 0, ThrottleMode.Shaping)
.Select(fun x ->
printfn "[0] %s" (x.Message.Bytes.ToString())
x)
.SelectAsync(1, fun cms ->
async {
if cms.Message.Bytes.ToString() = "5" then
do! cms.Nack() |> Async.AwaitTask
do! cms.Ack() |> Async.AwaitTask // here we fail on "5" message
return cms.Message.Bytes
}
|> Async.StartAsTask)
.Select(fun x ->
printfn "[1] %O" x
x)
.RunWith(
RestartSink.WithBackoff((fun _ ->
AmqpSink.CreateSimple(AmqpSinkSettings.Create(connSettings).WithRoutingKey(reportQueue.Name).WithDeclarations(reportQueue))),
TimeSpan.FromSeconds 1.0, TimeSpan.FromSeconds 2.0, 0.2), mat)
|> ignore
system.WhenTerminated.Wait()
[0] 1
[1] 1
[0] 2
[1] 2
[0] 3
[1] 3
[0] 4
[1] 4
[0] 5
[1] 5
[ERROR][18-Jan-18 19:45:06][Thread 0011][Akka.Streams.Dsl.RestartWithBackoffSource`2+Logic[Akka.Streams.Amqp.Dsl.CommittableIncomingMessage,Akka.NotUsed]] Restarting graph due to failure
Cause: Akka.Streams.Amqp.ShutdownSignalException: ShutdownSignal has been received, ShutdownInitiator=Peer, Cause=, ClassId=60, MethodId=80, ReplyCode=406, ReplyText=PRECONDITION_FAILED - unknown delivery tag 5
[DEBUG][18-Jan-18 19:45:06][Thread 0011][Akka.Streams.Dsl.RestartWithBackoffSource`2+Logic[Akka.Streams.Amqp.Dsl.CommittableIncomingMessage,Akka.NotUsed]] Last restart attempt was more than 00:00:01 ago, resetting restart count
[DEBUG][18-Jan-18 19:45:06][Thread 0011][Akka.Streams.Dsl.RestartWithBackoffSource`2+Logic[Akka.Streams.Amqp.Dsl.CommittableIncomingMessage,Akka.NotUsed]] Restarting graph in 00:00:01.0657050
[0] 6
[ERROR][18-Jan-18 19:45:08][Thread 0003][[akka://test/user/StreamSupervisor-0/Flow-1-0-unknown-operation#477839087]] Error during PreStart in [AmqpSource]
Cause: RabbitMQ.Client.Exceptions.OperationInterruptedException: The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=404, text="NOT_FOUND - no queue 'task-queue' in vhost '/'", classId=60, methodId=20, cause=
at RabbitMQ.Client.Impl.SimpleBlockingRpcContinuation.GetReply(TimeSpan timeout)
at RabbitMQ.Client.Impl.ModelBase.BasicConsume(String queue, Boolean autoAck, String consumerTag, Boolean noLocal, Boolean exclusive, IDictionary`2 arguments, IBasicConsumer consumer)
at RabbitMQ.Client.Impl.AutorecoveringModel.BasicConsume(String queue, Boolean autoAck, String consumerTag, Boolean noLocal, Boolean exclusive, IDictionary`2 arguments, IBasicConsumer consumer)
at Akka.Streams.Amqp.AmqpSourceStage.AmqpSourceStageLogic.SetupNamedQueue(NamedQueueSourceSettings settings)
at Akka.Streams.Amqp.AmqpConnectorLogic.PreStart()
at Akka.Streams.Implementation.Fusing.GraphInterpreter.Init(IMaterializer subMaterializer)
[ERROR][18-Jan-18 19:45:08][Thread 0003][Akka.Streams.Dsl.RestartWithBackoffSource`2+Logic[Akka.Streams.Amqp.Dsl.CommittableIncomingMessage,Akka.NotUsed]] Restarting graph due to failure
Cause: RabbitMQ.Client.Exceptions.OperationInterruptedException: The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=404, text="NOT_FOUND - no queue 'task-queue' in vhost '/'", classId=60, methodId=20, cause=
at RabbitMQ.Client.Impl.SimpleBlockingRpcContinuation.GetReply(TimeSpan timeout)
at RabbitMQ.Client.Impl.ModelBase.BasicConsume(String queue, Boolean autoAck, String consumerTag, Boolean noLocal, Boolean exclusive, IDictionary`2 arguments, IBasicConsumer consumer)
at RabbitMQ.Client.Impl.AutorecoveringModel.BasicConsume(String queue, Boolean autoAck, String consumerTag, Boolean noLocal, Boolean exclusive, IDictionary`2 arguments, IBasicConsumer consumer)
at Akka.Streams.Amqp.AmqpSourceStage.AmqpSourceStageLogic.SetupNamedQueue(NamedQueueSourceSettings settings)
at Akka.Streams.Amqp.AmqpConnectorLogic.PreStart()
at Akka.Streams.Implementation.Fusing.GraphInterpreter.Init(IMaterializer subMaterializer)
[DEBUG][18-Jan-18 19:45:08][Thread 0003][Akka.Streams.Dsl.RestartWithBackoffSource`2+Logic[Akka.Streams.Amqp.Dsl.CommittableIncomingMessage,Akka.NotUsed]] Restarting graph in 00:00:02.3403801
[ERROR][18-Jan-18 19:45:10][Thread 0005][[akka://test/user/StreamSupervisor-0/Flow-1-0-unknown-operation#477839087]] Error during PreStart in [AmqpSource]
Cause: RabbitMQ.Client.Exceptions.OperationInterruptedException: The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=404, text="NOT_FOUND - no queue 'task-queue' in vhost '/'", classId=60, methodId=20, cause=
at RabbitMQ.Client.Impl.SimpleBlockingRpcContinuation.GetReply(TimeSpan timeout)
at RabbitMQ.Client.Impl.ModelBase.BasicConsume(String queue, Boolean autoAck, String consumerTag, Boolean noLocal, Boolean exclusive, IDictionary`2 arguments, IBasicConsumer consumer)
at RabbitMQ.Client.Impl.AutorecoveringModel.BasicConsume(String queue, Boolean autoAck, String consumerTag, Boolean noLocal, Boolean exclusive, IDictionary`2 arguments, IBasicConsumer consumer)
at Akka.Streams.Amqp.AmqpSourceStage.AmqpSourceStageLogic.SetupNamedQueue(NamedQueueSourceSettings settings)
at Akka.Streams.Amqp.AmqpConnectorLogic.PreStart()
at Akka.Streams.Implementation.Fusing.GraphInterpreter.Init(IMaterializer subMaterializer)
[ERROR][18-Jan-18 19:45:10][Thread 0005][Akka.Streams.Dsl.RestartWithBackoffSource`2+Logic[Akka.Streams.Amqp.Dsl.CommittableIncomingMessage,Akka.NotUsed]] Restarting graph due to failure
Cause: RabbitMQ.Client.Exceptions.OperationInterruptedException: The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=404, text="NOT_FOUND - no queue 'task-queue' in vhost '/'", classId=60, methodId=20, cause=
at RabbitMQ.Client.Impl.SimpleBlockingRpcContinuation.GetReply(TimeSpan timeout)
at RabbitMQ.Client.Impl.ModelBase.BasicConsume(String queue, Boolean autoAck, String consumerTag, Boolean noLocal, Boolean exclusive, IDictionary`2 arguments, IBasicConsumer consumer)
at RabbitMQ.Client.Impl.AutorecoveringModel.BasicConsume(String queue, Boolean autoAck, String consumerTag, Boolean noLocal, Boolean exclusive, IDictionary`2 arguments, IBasicConsumer consumer)
at Akka.Streams.Amqp.AmqpSourceStage.AmqpSourceStageLogic.SetupNamedQueue(NamedQueueSourceSettings settings)
at Akka.Streams.Amqp.AmqpConnectorLogic.PreStart()
at Akka.Streams.Implementation.Fusing.GraphInterpreter.Init(IMaterializer subMaterializer)
[DEBUG][18-Jan-18 19:45:10][Thread 0005][Akka.Streams.Dsl.RestartWithBackoffSource`2+Logic[Akka.Streams.Amqp.Dsl.CommittableIncomingMessage,Akka.NotUsed]] Restarting graph in 00:00:02.1493502
[ERROR][18-Jan-18 19:45:12][Thread 0008][[akka://test/user/StreamSupervisor-0/Flow-1-0-unknown-operation#477839087]] Error during PreStart in [AmqpSource]
Cause: RabbitMQ.Client.Exceptions.OperationInterruptedException: The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=404, text="NOT_FOUND - no queue 'task-queue' in vhost '/'", classId=60, methodId=20, cause=
at RabbitMQ.Client.Impl.SimpleBlockingRpcContinuation.GetReply(TimeSpan timeout)
at RabbitMQ.Client.Impl.ModelBase.BasicConsume(String queue, Boolean autoAck, String consumerTag, Boolean noLocal, Boolean exclusive, IDictionary`2 arguments, IBasicConsumer consumer)
at RabbitMQ.Client.Impl.AutorecoveringModel.BasicConsume(String queue, Boolean autoAck, String consumerTag, Boolean noLocal, Boolean exclusive, IDictionary`2 arguments, IBasicConsumer consumer)
at Akka.Streams.Amqp.AmqpSourceStage.AmqpSourceStageLogic.SetupNamedQueue(NamedQueueSourceSettings settings)
at Akka.Streams.Amqp.AmqpConnectorLogic.PreStart()
at Akka.Streams.Implementation.Fusing.GraphInterpreter.Init(IMaterializer subMaterializer)
It fails with "text="NOT_FOUND - no queue 'task-queue'". I don't understand why.
OK, carefully catching exceptions and nack
ing task messages works pretty good:
.SelectAsync(1, fun cms ->
async {
try
if cms.Message.Bytes.ToString() = "5" then failwithf "It's 5 and we are failing."
do! cms.Ack() |> Async.AwaitTask
with e ->
do! cms.Nack() |> Async.AwaitTask
return cms
}
|> Async.StartAsTask)
The problem is that auto-delete queues are owned by channels they are declared by, and if a channel dies, the queues disappear too. RestartSource
properly re-creates the channel (IModel
), but not the queue (should it?). So I consider this by design.