0

I'm using Alpakka JMS connector to dequeue items from Oracle AQ, and Slick for database operations, the queue and the tables are on the same schema.

I need to make the dequeue and DB operations transactionally, so if one fails, the other will also fail. Is there a way to achieve this functionality?

What I've come up so far is to have two separate transactions, which is not safe:

val source: Source[Message, NotUsed] = JmsSource(
    JmsSourceSettings(connectionFactory)
        .withQueue("My_Queue").withBufferSize(10)
        .withAcknowledgeMode(AcknowledgeMode.ClientAcknowledge)
)

val sink = Sink.foreach { m: Message =>
    val txtMessage = m.asInstanceOf[TextMessage].getText

    // commits only for Slick
    val dbResult = db.run(
        (for{
            tableUpdate <- updateTable()
            result <- updateAnotherTable()
        } yield result).transactionally
    )

    dbResult.map { _ =>
        // commits only for JMS
        m.acknowledge() 
    }
}

source.runWith(sink)
Feyyaz
  • 3,147
  • 4
  • 35
  • 50
  • 1
    There is nothing Slick could do in this case. You can build a workaround where you look for the Slick commit first (a Future) and if that is successful, look for the JMS commit and if that is not successful, then you could perhaps delete the inserted record? – joesan Dec 15 '17 at 10:21
  • Unfortunately it does not guarantee the consistency, as the compensation function may fail too. – Feyyaz Dec 15 '17 at 10:58
  • Actually I'm expecting a workaround with Oracle sessions. Both Alpakka and Slick are pointing to the same database&schema, maybe there is a trick to tell them to use the same session, so when Slick `commit` **or** Alpakka `acknowledge` is called, both of the operations will be committed in single transaction. – Feyyaz Dec 15 '17 at 11:04

0 Answers0