All Downloads are FREE. Search and download functionalities are using the official Maven repository.

examples.ledger.db.Log.scala Maven / Gradle / Ivy

package examples.ledger.db

import java.io.FileWriter
import kyo.*
import scala.jdk.CollectionConverters.*

trait Log:

    def transaction(
        balance: Int,
        account: Int,
        amount: Int,
        desc: String
    ): Unit < IO

end Log

object Log:

    case class Entry(balance: Int, account: Int, amount: Int, desc: String)

    val init: Log < (Env[DB.Config] & IO) = defer {
        val cfg = await(Env.get[DB.Config])
        val q   = await(Queue.Unbounded.init[Entry](Access.MultiProducerSingleConsumer))
        val log = await(IO(Live(cfg.workingDir + "/log.dat", q)))
        val _   = await(Async.run(log.flushLoop(cfg.flushInterval)))
        log
    }

    class Live(filePath: String, q: Queue.Unbounded[Entry]) extends Log:

        private val writer = new FileWriter(filePath, true)

        def transaction(
            balance: Int,
            account: Int,
            amount: Int,
            desc: String
        ): Unit < IO =
            q.add(Entry(balance, account, amount, desc))

        private[Log] def flushLoop(interval: Duration): Unit < Async = defer {
            await(Async.sleep(interval))
            val entries = await(q.drain)
            await(append(entries))
            await(flushLoop(interval))
        }

        private def append(entries: Seq[Entry]) =
            IO {
                if entries.nonEmpty then
                    val str =
                        entries.map { e =>
                            s"${e.balance}|${e.account}|${e.amount}|${e.desc}"
                        }.mkString("\n")
                    writer.append(str + "\n")
                    writer.flush()
            }

    end Live

end Log




© 2015 - 2025 Weber Informatics LLC | Privacy Policy