Skip to content

Commit

Permalink
Added Timestamp to provide a better type-safe reference to a date
Browse files Browse the repository at this point in the history
  • Loading branch information
darkfrog26 committed Dec 23, 2024
1 parent b241beb commit dd315f8
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 9 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ val developerURL: String = "https://matthicks.com"

name := projectName
ThisBuild / organization := org
ThisBuild / version := "1.2.3-SNAPSHOT"
ThisBuild / version := "1.3.0-SNAPSHOT"
ThisBuild / scalaVersion := scala3
ThisBuild / crossScalaVersions := allScalaVersions
ThisBuild / scalacOptions ++= Seq("-unchecked", "-deprecation")
Expand Down
15 changes: 15 additions & 0 deletions core/src/main/scala/lightdb/Timestamp.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package lightdb

import fabric.define.DefType
import fabric.rw._

case class Timestamp(value: Long = System.currentTimeMillis()) extends AnyVal

object Timestamp {
implicit val rw: RW[Timestamp] = RW.from(
r = _.value.json,
w = j => Timestamp(j.asLong),
d = DefType.Int
)
implicit val numeric: Numeric[Timestamp] = Numeric[Long].map(Timestamp.apply)(_.value)
}
6 changes: 4 additions & 2 deletions core/src/main/scala/lightdb/doc/RecordDocument.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package lightdb.doc

import lightdb.Timestamp

trait RecordDocument[Doc <: RecordDocument[Doc]] extends Document[Doc] {
def created: Long
def modified: Long
def created: Timestamp
def modified: Timestamp
}
6 changes: 3 additions & 3 deletions core/src/main/scala/lightdb/doc/RecordDocumentModel.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package lightdb.doc

import fabric.rw._
import lightdb.field.Field
import lightdb.Timestamp

trait RecordDocumentModel[Doc <: RecordDocument[Doc]] extends DocumentModel[Doc] {
val created: I[Long] = field.index("created", (doc: Doc) => doc.created)
val modified: I[Long] = field.index("modified", (doc: Doc) => doc.modified)
val created: I[Timestamp] = field.index("created", (doc: Doc) => doc.created)
val modified: I[Timestamp] = field.index("modified", (doc: Doc) => doc.modified)
}
17 changes: 17 additions & 0 deletions core/src/main/scala/lightdb/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package object lightdb {
implicit class NumericOps[A](numeric: Numeric[A]) {
def map[B](to: A => B)(from: B => A): Numeric[B] = new Numeric[B] {
override def plus(x: B, y: B): B = to(numeric.plus(from(x), from(y)))
override def minus(x: B, y: B): B = to(numeric.minus(from(x), from(y)))
override def times(x: B, y: B): B = to(numeric.times(from(x), from(y)))
override def negate(x: B): B = to(numeric.negate(from(x)))
override def fromInt(x: Int): B = to(numeric.fromInt(x))
override def toInt(x: B): Int = numeric.toInt(from(x))
override def toLong(x: B): Long = numeric.toLong(from(x))
override def toFloat(x: B): Float = numeric.toFloat(from(x))
override def toDouble(x: B): Double = numeric.toDouble(from(x))
override def compare(x: B, y: B): Int = numeric.compare(from(x), from(y))
override def parseString(str: String): Option[B] = numeric.parseString(str).map(to)
}
}
}
1 change: 1 addition & 0 deletions core/src/main/scala/lightdb/store/split/SplitStore.scala
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ case class SplitStore[Doc <: Document[Doc], Model <: DocumentModel[Doc]](overrid
}

private def reIndexInternal()(implicit transaction: Transaction[Doc]): Unit = {
// TODO: Process concurrently
searching.truncate()
storage.iterator.foreach { doc =>
searching.insert(doc)
Expand Down
12 changes: 9 additions & 3 deletions core/src/test/scala/spec/AbstractSpecialCasesSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import lightdb.collection.Collection
import lightdb.doc.{JsonConversion, RecordDocument, RecordDocumentModel}
import lightdb.store.StoreManager
import lightdb.upgrade.DatabaseUpgrade
import lightdb.{Id, LightDB, Sort}
import lightdb.{Id, LightDB, Sort, Timestamp}
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

Expand Down Expand Up @@ -34,6 +34,12 @@ trait AbstractSpecialCasesSpec extends AnyWordSpec with Matchers { spec =>
list.map(_._id).toSet should be(Set(SpecialOne.id("first"), SpecialOne.id("second")))
}
}
"verify filtering by created works" in {
DB.specialOne.transaction { implicit transaction =>
DB.specialOne.query.filter(_.created < Timestamp()).toList.map(_.name).toSet should be(Set("First", "Second"))
DB.specialOne.query.filter(_.created > Timestamp()).toList.map(_.name).toSet should be(Set.empty)
}
}
"verify the storage of data is correct" in {
DB.specialOne.transaction { implicit transaction =>
val list = DB.specialOne.query.sort(Sort.ByField(SpecialOne.name).asc).search.json(ref => List(ref._id)).list
Expand Down Expand Up @@ -68,8 +74,8 @@ trait AbstractSpecialCasesSpec extends AnyWordSpec with Matchers { spec =>
case class SpecialOne(name: String,
wrappedString: WrappedString,
person: Person,
created: Long = System.currentTimeMillis(),
modified: Long = System.currentTimeMillis(),
created: Timestamp = Timestamp(),
modified: Timestamp = Timestamp(),
_id: Id[SpecialOne] = SpecialOne.id()) extends RecordDocument[SpecialOne]

object SpecialOne extends RecordDocumentModel[SpecialOne] with JsonConversion[SpecialOne] {
Expand Down

0 comments on commit dd315f8

Please sign in to comment.