Akka Streams KillSwitch in alpakka jms

时间:2017-12-18 06:05:56

标签: scala akka-stream alpakka

I have a scenario in which I am starting multiple jmsSource (for different queues) using alpakka. I also need to detach the queues at any point in time. So I have added KillSwitch to the jms akka streams as below :-

trait MessageListener  {

  lazy val jmsPipeline = jmsSource
    .map { x => log.info(s"Received message ${x} from ${queue}"); x }
    .viaMat(KillSwitches.single)(Keep.right)
    .toMat(Sink.foreach { x => pipelineActorRef ! PreProcessorMessage(x) })
    (Keep.both)
    .run()

   def start(): Unit = {
             log.info("Invoking listener : {}", queue)
             jmsPipeline
             log.info("listener : {} started", queue)
          }
  def stop():Unit  =     jmsPipeline._1.shutdown()

  def queue: String

}

object ListenerA extends MessageListener {
  override def queue: String = "Queue_A"
}

object ListenerB extends MessageListener {
  override def queue: String = "Queue_B"
} 

.. and so on.

After I start up the application, all the queues are connected and works fine. But when I try to detach the queue using the stop method, not all the queues gets disconnected and the behaviour is random. I also checked that the killSwitch is different for all the listeners.

Could someone please tell me what's getting wrong here?

1 个答案:

答案 0 :(得分:0)

您的日志支持您使用不同的流连接到多个队列的错觉,但您有多个可能连接到同一队列的流。在两个侦听器对象中,记录器记录重写的queue名称,但此队列名称不用于配置jmsSource

您没有显示jmsSource的定义;显然,它定义在MessageListener特征之外的某个位置,在这种情况下,ListenerAListenerB都使用相同的jmsSource。换句话说,虽然ListenerAListenerB具有jmsPipeline的不同实例(这就是kill开关不同的原因),但这两个jmsPipeline实例都是从同一个实例派生的jmsSource实例(除非jmsSourcedef,在每次调用时都会创建不同的Source,但即使是这种情况,基本问题仍然存在:{{1}在配置中没有使用。)

在Alpakka中,JMS队列在queue上配置,因此JmsSourceSettings可能如下所示:

jmsSource

例如,当调用val jmsSource: Source[String, NotUsed] = JmsSource.textSource( JmsSourceSettings(connectionFactory).withBufferSize(10).withQueue("MyQueue") ) // the queue is configured here ^ 时,将记录以下内容:

ListenerA.start()

同样,上述日志语句中的Invoking listener : Queue_A listener : Queue_A started "Queue_A"中被覆盖的def queue: String成员的值;它不一定是ListenerA中实际配置的队列(在上例中为jmsSource)。与"MyQueue"相同的内容以及您在ListenerB组合器中重新登录的消息。

一个简单的解决方法是将map及其jmsSource的定义移到JmsSourceSettings特征中,并在这些设置中实际使用MessageListener