slickakka-streamslick-3.0alpakka

How do you transform a `FixedSqlAction` into a `StreamingDBIO` in Slick?


I'm creating an akka-stream using Alpakka and the Slick module but I'm stuck in a type mismatch problem.

One branch is about getting the total number of invoices in their table:

  def getTotal(implicit session: SlickSession) = {
    import session.profile.api._
    val query = TableQuery[Tables.Invoice].length.result
    Slick.source(query)
  }

But the end line doesn't compile because Alpakka is expecting a StreamingDBIO but I'm providing a FixedSqlAction[Int,slick.dbio.NoStream,slick.dbio.Effect.Read].

How can I move from the non-streaming result to the streaming one?


Solution

  • Taking the length of a table results in a single value, not a stream. So the simplest way to get a Source to feed a stream is

    def getTotal(implicit session: SlickSession): Source[Int, NotUsed] =
      Source.lazyFuture { () =>
        // Don't actually run the query until the stream has materialized and
        //  demand has reached the source
        val query = TableQuery[Tables.Invoice].length.result
        session.db.run(query)
      }
    

    Alpakka's Slick connector is more oriented towards streaming (including managing pagination etc.) results of queries that have a lot of results. For a single result, converting the Future of the result that vanilla Slick gives you into a stream is sufficient.

    If you want to start executing the query as soon as you call getTotal (note that this whether or not the downstream ever runs or demands data from the source), you can have

    def getTotal(implicit session: SlickSession): Source[Int, NotUsed] = {
      val query = TableQuery[Tables.Invoice].length.result
      Source.future(session.db.run(query))
    }