-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bce8947
commit 43ce43a
Showing
6 changed files
with
106 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,91 @@ | ||
package lightdb.collection | ||
|
||
import cats.effect.IO | ||
import lightdb.LightDB | ||
import lightdb.document.{Document, DocumentModel} | ||
import lightdb.{Id, LightDB} | ||
import lightdb.document.{Document, DocumentListener, DocumentModel} | ||
import lightdb.transaction.Transaction | ||
import lightdb.util.Initializable | ||
import cats.implicits._ | ||
|
||
case class Collection[D <: Document[D]](name: String, | ||
model: DocumentModel[D], | ||
db: LightDB) extends Initializable { | ||
override protected def initialize(): IO[Unit] = model.init(this) | ||
db: LightDB) extends Initializable { collection => | ||
private implicit class ListIO[R](list: List[IO[R]]) { | ||
def ioSeq: IO[Unit] = if (model.parallel) { | ||
list.parSequence.map(_ => ()) | ||
} else { | ||
list.sequence.map(_ => ()) | ||
} | ||
} | ||
|
||
private def recurseOption(doc: D, | ||
invoke: (DocumentListener[D], D) => IO[Option[D]], | ||
listeners: List[DocumentListener[D]] = model.listener()): IO[Option[D]] = listeners.headOption match { | ||
case Some(l) => invoke(l, doc).flatMap { | ||
case Some(v) => recurseOption(v, invoke, listeners.tail) | ||
case None => IO.pure(None) | ||
} | ||
case None => IO.pure(Some(doc)) | ||
} | ||
|
||
override protected def initialize(): IO[Unit] = for { | ||
_ <- IO(model.collection = this) | ||
_ <- db.storeManager[D](name).map(store => model.store = store) | ||
_ <- model.listener().map(_.init(this)).ioSeq.map(_ => model._initialized.set(true)) | ||
} yield () | ||
|
||
object transaction { | ||
def apply[Return](f: Transaction[D] => IO[Return]): IO[Return] = create() | ||
.flatMap { transaction => | ||
f(transaction).guarantee(release(transaction)) | ||
} | ||
|
||
private def create(): IO[Transaction[D]] = for { | ||
transaction <- IO(Transaction[D](collection)) | ||
_ <- model.listener().map(l => l.transactionStart(transaction)).ioSeq | ||
} yield transaction | ||
|
||
private def release(transaction: Transaction[D]): IO[Unit] = | ||
model.listener().map(l => l.transactionEnd(transaction)).ioSeq | ||
} | ||
|
||
def apply(id: Id[D])(implicit transaction: Transaction[D]): IO[D] = model.store(id) | ||
|
||
def get(id: Id[D])(implicit transaction: Transaction[D]): IO[Option[D]] = model.store.get(id) | ||
|
||
final def set(doc: D)(implicit transaction: Transaction[D]): IO[Option[D]] = { | ||
recurseOption(doc, (l, d) => l.preSet(d, transaction)).flatMap { | ||
case Some(d) => for { | ||
_ <- model.store.set(d) | ||
_ <- model.listener().map(l => l.postSet(d, transaction)).ioSeq | ||
} yield Some(d) | ||
case None => IO.pure(None) | ||
} | ||
} | ||
|
||
def stream(implicit transaction: Transaction[D]): fs2.Stream[IO, D] = model.store.stream | ||
|
||
def count(implicit transaction: Transaction[D]): IO[Int] = model.store.count | ||
|
||
def idStream(implicit transaction: Transaction[D]): fs2.Stream[IO, Id[D]] = model.store.idStream | ||
|
||
final def delete(doc: D)(implicit transaction: Transaction[D]): IO[Option[D]] = { | ||
recurseOption(doc, (l, d) => l.preDelete(d, transaction)).flatMap { | ||
case Some(d) => for { | ||
_ <- model.store.delete(d._id) | ||
_ <- model.listener().map(l => l.postDelete(d, transaction)).ioSeq | ||
} yield Some(d) | ||
case None => IO.pure(None) | ||
} | ||
} | ||
|
||
def truncate()(implicit transaction: Transaction[D]): IO[Unit] = model.listener() | ||
.map(l => l.truncate(transaction)) | ||
.ioSeq | ||
.map(_ => ()) | ||
|
||
def dispose(): IO[Unit] = model.listener() | ||
.map(l => l.dispose()) | ||
.ioSeq | ||
.map(_ => ()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
package lightdb.transaction | ||
|
||
import lightdb.collection.Collection | ||
import lightdb.document.Document | ||
|
||
trait Transaction[D <: Document[D]] | ||
case class Transaction[D <: Document[D]](collection: Collection[D]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters