WIP
This commit is contained in:
parent
1195bab53c
commit
41e9e797c1
5 changed files with 119 additions and 25 deletions
|
@ -38,10 +38,10 @@ val Deps = new {
|
||||||
}
|
}
|
||||||
|
|
||||||
val Gs = new {
|
val Gs = new {
|
||||||
val Uuid: ModuleID = "gs" %% "gs-uuid-v0" % "0.2.4"
|
val Uuid: ModuleID = "gs" %% "gs-uuid-v0" % "0.3.0"
|
||||||
val Slug: ModuleID = "gs" %% "gs-slug-v0" % "0.1.3"
|
val Slug: ModuleID = "gs" %% "gs-slug-v0" % "0.1.3"
|
||||||
val Config: ModuleID = "gs" %% "gs-config-v0" % "0.1.1"
|
val Config: ModuleID = "gs" %% "gs-config-v0" % "0.1.1"
|
||||||
val Datagen: ModuleID = "gs" %% "gs-datagen-core-v0" % "0.1.1"
|
val Datagen: ModuleID = "gs" %% "gs-datagen-core-v0" % "0.2.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
val MUnit: ModuleID = "org.scalameta" %% "munit" % "1.0.0-RC1"
|
val MUnit: ModuleID = "org.scalameta" %% "munit" % "1.0.0-RC1"
|
||||||
|
|
|
@ -6,22 +6,28 @@ import doobie.*
|
||||||
import doobie.implicits.*
|
import doobie.implicits.*
|
||||||
import gs.smolban.db.DbError
|
import gs.smolban.db.DbError
|
||||||
import gs.smolban.db.TicketDb
|
import gs.smolban.db.TicketDb
|
||||||
|
import gs.smolban.db.doobie.DoobieTypes.*
|
||||||
import gs.smolban.model.CreatedAt
|
import gs.smolban.model.CreatedAt
|
||||||
import gs.smolban.model.CreatedBy
|
import gs.smolban.model.CreatedBy
|
||||||
import gs.smolban.model.Group
|
import gs.smolban.model.Group
|
||||||
import gs.smolban.model.Ticket
|
import gs.smolban.model.Ticket
|
||||||
import gs.smolban.model.users.User
|
import gs.smolban.model.users.User
|
||||||
import gs.uuid.v0.UUIDFormat
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
final class DoobieTicketDb[F[_]: Async] extends TicketDb[F]:
|
final class DoobieTicketDb[F[_]: Async](
|
||||||
|
val xa: Transactor[F]
|
||||||
|
) extends TicketDb[F]:
|
||||||
|
import DoobieTicketDb.Sql
|
||||||
|
|
||||||
/** @inheritdoc
|
/** @inheritdoc
|
||||||
*/
|
*/
|
||||||
override def createTicket(ticket: Ticket): EitherT[F, DbError, Ticket] = ???
|
override def createTicket(ticket: Ticket): EitherT[F, DbError, Ticket] = ???
|
||||||
|
|
||||||
/** @inheritdoc
|
/** @inheritdoc
|
||||||
*/
|
*/
|
||||||
override def readTicket(ref: Ticket.Reference): F[Option[Ticket]] = ???
|
override def readTicket(ref: Ticket.Reference): F[Option[Ticket]] =
|
||||||
|
???
|
||||||
|
// Sql.readTicket(ref.id, ref.group).option.transact(xa)
|
||||||
|
// for compose multiple reads
|
||||||
|
|
||||||
/** @inheritdoc
|
/** @inheritdoc
|
||||||
*/
|
*/
|
||||||
|
@ -36,27 +42,31 @@ final class DoobieTicketDb[F[_]: Async] extends TicketDb[F]:
|
||||||
|
|
||||||
object DoobieTicketDb:
|
object DoobieTicketDb:
|
||||||
|
|
||||||
object Sql:
|
private object Sql:
|
||||||
|
|
||||||
implicit val ticketIdGet: Get[Ticket.Id] = Get[Long].tmap(Ticket.Id(_))
|
case class TicketContents(
|
||||||
implicit val ticketIdPut: Put[Ticket.Id] = Put[Long].tcontramap(_.toLong())
|
createdAt: CreatedAt,
|
||||||
|
createdBy: CreatedBy,
|
||||||
|
title: String,
|
||||||
|
description: String,
|
||||||
|
status: Ticket.Status,
|
||||||
|
assignee: Option[User.Id]
|
||||||
|
)
|
||||||
|
|
||||||
implicit val groupIdGet: Get[Group.Id] = Get[Array[Byte]].tmap { bytes =>
|
// TODO: figure out how to read tags
|
||||||
Group.Id(gs.uuid.v0.UUID(gs.uuid.v0.UUIDFormat.fromBytes(bytes)))
|
// also storing them
|
||||||
}
|
// make tagdb and such...
|
||||||
|
|
||||||
implicit val groupIdPut: Put[Group.Id] = Put[Array[Byte]].tcontramap { id =>
|
def readTicket(
|
||||||
gs.uuid.v0.UUIDFormat.toBytes(id.toUUID().toUUID)
|
ticketId: Ticket.Id,
|
||||||
}
|
groupId: Group.Id
|
||||||
|
): Query0[TicketContents] = sql"""
|
||||||
/* private case class TicketContents( createdAt: CreatedAt, createdBy:
|
SELECT
|
||||||
* CreatedBy, title: String, description: String, status: Ticket.Status,
|
created_at, created_by, title, description, status, assignee
|
||||||
* assignee: Option[User.Id] )
|
FROM tickets
|
||||||
*
|
WHERE
|
||||||
* def readTicket(ticketId: Ticket.Id, groupId: Group.Id) = sql""" SELECT
|
ticket_id = $ticketId AND group_id = $groupId
|
||||||
* created_at, created_by, title, description, status, assignee FROM tickets
|
""".query[TicketContents]
|
||||||
* WHERE ticket_id = $ticketId AND group_id = $groupId
|
|
||||||
* """.query[TicketContents] */
|
|
||||||
|
|
||||||
end Sql
|
end Sql
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
package gs.smolban.db.doobie
|
||||||
|
|
||||||
|
import DoobieTypes.ErrorMessages
|
||||||
|
import doobie.*
|
||||||
|
import gs.smolban.model.CreatedAt
|
||||||
|
import gs.smolban.model.CreatedBy
|
||||||
|
import gs.smolban.model.Group
|
||||||
|
import gs.smolban.model.Ticket
|
||||||
|
import gs.smolban.model.users.User
|
||||||
|
import gs.uuid.v0.UUID
|
||||||
|
import gs.uuid.v0.UUIDFormat
|
||||||
|
|
||||||
|
trait DoobieTypes:
|
||||||
|
|
||||||
|
implicit val ticketIdGet: Get[Ticket.Id] =
|
||||||
|
Get[Long].tmap(Ticket.Id(_))
|
||||||
|
|
||||||
|
implicit val ticketIdPut: Put[Ticket.Id] =
|
||||||
|
Put[Long].tcontramap(_.toLong())
|
||||||
|
|
||||||
|
implicit val ticketStatusGet: Get[Ticket.Status] =
|
||||||
|
Get[String].temap(dbValue =>
|
||||||
|
Ticket.Status.parse(dbValue) match
|
||||||
|
case None => Left(ErrorMessages.invalidTicketStatus(dbValue))
|
||||||
|
case Some(status) => Right(status)
|
||||||
|
)
|
||||||
|
|
||||||
|
implicit val ticketStatusPut: Put[Ticket.Status] =
|
||||||
|
Put[String].tcontramap(_.name)
|
||||||
|
|
||||||
|
implicit val groupIdGet: Get[Group.Id] =
|
||||||
|
Get[Array[Byte]].tmap(bytes => Group.Id(UUID(UUIDFormat.fromBytes(bytes))))
|
||||||
|
|
||||||
|
implicit val groupIdPut: Put[Group.Id] =
|
||||||
|
Put[Array[Byte]].tcontramap(id => UUIDFormat.toBytes(id.toUUID().toUUID()))
|
||||||
|
|
||||||
|
implicit val userIdGet: Get[User.Id] =
|
||||||
|
Get[Array[Byte]].tmap(bytes => User.Id(UUID(UUIDFormat.fromBytes(bytes))))
|
||||||
|
|
||||||
|
implicit val userIdPut: Put[User.Id] =
|
||||||
|
Put[Array[Byte]].tcontramap(id => UUIDFormat.toBytes(id.toUUID().toUUID()))
|
||||||
|
|
||||||
|
implicit val createdAtGet: Get[CreatedAt] =
|
||||||
|
Get[Long].tmap(CreatedAt.fromMilliseconds)
|
||||||
|
|
||||||
|
implicit val createdAtPut: Put[CreatedAt] =
|
||||||
|
Put[Long].tcontramap(_.toMilliseconds())
|
||||||
|
|
||||||
|
implicit val createdByGet: Get[CreatedBy] =
|
||||||
|
Get[Array[Byte]].tmap(bytes =>
|
||||||
|
CreatedBy(User.Id(UUID(UUIDFormat.fromBytes(bytes))))
|
||||||
|
)
|
||||||
|
|
||||||
|
implicit val createdByPut: Put[CreatedBy] =
|
||||||
|
Put[Array[Byte]].tcontramap(id =>
|
||||||
|
UUIDFormat.toBytes(id.toUserId().toUUID().toUUID())
|
||||||
|
)
|
||||||
|
|
||||||
|
object DoobieTypes extends DoobieTypes:
|
||||||
|
|
||||||
|
object ErrorMessages:
|
||||||
|
|
||||||
|
def invalidTicketStatus(candidate: String): String =
|
||||||
|
s"'$candidate' is not a valid ticket status."
|
||||||
|
|
||||||
|
end ErrorMessages
|
||||||
|
|
||||||
|
end DoobieTypes
|
|
@ -19,6 +19,15 @@ object CreatedAt:
|
||||||
*/
|
*/
|
||||||
def apply(timestamp: Instant): CreatedAt = timestamp
|
def apply(timestamp: Instant): CreatedAt = timestamp
|
||||||
|
|
||||||
|
/** Instantiate a new [[CreatedAt]].
|
||||||
|
*
|
||||||
|
* @param millis
|
||||||
|
* The epoch milliseconds describing the instant of this timestamp.
|
||||||
|
* @return
|
||||||
|
* The new instance.
|
||||||
|
*/
|
||||||
|
def fromMilliseconds(millis: Long): CreatedAt = Instant.ofEpochMilli(millis)
|
||||||
|
|
||||||
given CanEqual[CreatedAt, CreatedAt] = CanEqual.derived
|
given CanEqual[CreatedAt, CreatedAt] = CanEqual.derived
|
||||||
|
|
||||||
given Show[CreatedAt] = _.toInstant().toString()
|
given Show[CreatedAt] = _.toInstant().toString()
|
||||||
|
@ -31,4 +40,11 @@ object CreatedAt:
|
||||||
*/
|
*/
|
||||||
def toInstant(): Instant = createdAt
|
def toInstant(): Instant = createdAt
|
||||||
|
|
||||||
|
/** Express this instant as epoch milliseconds.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The epoch milliseconds.
|
||||||
|
*/
|
||||||
|
def toMilliseconds(): Long = createdAt.toEpochMilli()
|
||||||
|
|
||||||
end CreatedAt
|
end CreatedAt
|
||||||
|
|
|
@ -7,7 +7,7 @@ import cats.Show
|
||||||
*
|
*
|
||||||
* Tags are defined _globally_ in Smolban.
|
* Tags are defined _globally_ in Smolban.
|
||||||
*/
|
*/
|
||||||
opaque type Tag = String
|
opaque type Tag = String // TODO: Make this have a unique id (long?) and value
|
||||||
|
|
||||||
object Tag:
|
object Tag:
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue