Skip to content

Commit

Permalink
feat: using ducktape for object transformation (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
jachro authored Feb 23, 2024
1 parent 65528c4 commit f0a7ac3
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 36 deletions.
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ lazy val commons = project
Dependencies.borer ++
Dependencies.catsCore ++
Dependencies.catsEffect ++
Dependencies.ducktape ++
Dependencies.fs2Core ++
Dependencies.scodecBits ++
Dependencies.scribe,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package io.renku.search.model
import cats.kernel.Order
import io.bullet.borer.derivation.MapBasedCodecs.*
import io.bullet.borer.{Codec, Decoder, Encoder}
import io.github.arainko.ducktape.*
import io.renku.search.borer.codecs.all.given

import java.time.Instant
Expand All @@ -31,24 +32,28 @@ object projects:
object Id:
def apply(v: String): Id = v
extension (self: Id) def value: String = self
given Transformer[String, Id] = apply
given Codec[Id] = Codec.of[String]

opaque type Name = String
object Name:
def apply(v: String): Name = v
extension (self: Name) def value: String = self
given Transformer[String, Name] = apply
given Codec[Name] = Codec.of[String]

opaque type Slug = String
object Slug:
def apply(v: String): Slug = v
extension (self: Slug) def value: String = self
given Transformer[String, Slug] = apply
given Codec[Slug] = Codec.of[String]

opaque type Repository = String
object Repository:
def apply(v: String): Repository = v
extension (self: Repository) def value: String = self
given Transformer[String, Repository] = apply
given Codec[Repository] = Codec.of[String]

opaque type Description = String
Expand All @@ -62,12 +67,14 @@ object projects:
}
}
extension (self: Description) def value: String = self
given Transformer[String, Description] = apply
given Codec[Description] = Codec.of[String]

opaque type CreationDate = Instant
object CreationDate:
def apply(v: Instant): CreationDate = v
extension (self: CreationDate) def value: Instant = self
given Transformer[Instant, CreationDate] = apply
given Codec[CreationDate] = Codec.of[Instant]

enum Visibility derives Codec:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
package io.renku.search.model

import io.bullet.borer.Codec
import io.github.arainko.ducktape.Transformer

object users:

opaque type Id = String
object Id:
def apply(v: String): Id = v
extension (self: Id) def value: String = self
given Transformer[String, Id] = apply
given Codec[Id] = Codec.bimap[String, Id](_.value, Id.apply)
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ package io.renku.search.api

import cats.effect.Async
import cats.syntax.all.*
import io.github.arainko.ducktape.*
import io.renku.search.api.data.*
import io.renku.search.solr.client.SearchSolrClient
import io.renku.search.solr.documents.{Project as SolrProject, User as SolrUser}
import io.renku.search.solr.documents.Project as SolrProject
import io.renku.solr.client.QueryResponse
import org.http4s.dsl.Http4sDsl
import scribe.Scribe
import io.renku.search.api.data.*
import io.renku.solr.client.QueryResponse

private class SearchApiImpl[F[_]: Async](solrClient: SearchSolrClient[F])
extends Http4sDsl[F]
Expand All @@ -51,25 +52,11 @@ private class SearchApiImpl[F[_]: Async](solrClient: SearchSolrClient[F])
.as(message)
.map(_.asLeft[SearchResult])

private def toApiProject(p: SolrProject): SearchEntity =
def toUser(user: SolrUser): User = User(user.id)
Project(
p.id,
p.name,
p.slug,
p.repositories,
p.visibility,
p.description,
toUser(p.createdBy),
p.creationDate,
p.members.map(toUser)
)

private def toApiResult(currentPage: PageDef)(
solrResult: QueryResponse[SolrProject]
): SearchResult =
val hasMore = solrResult.responseBody.docs.size > currentPage.limit
val pageInfo = PageWithTotals(currentPage, solrResult.responseBody.numFound, hasMore)
val items = solrResult.responseBody.docs.map(toApiProject)
val items = solrResult.responseBody.docs.map(_.to[Project])
if (hasMore) SearchResult(items.init, pageInfo)
else SearchResult(items, pageInfo)
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ import cats.effect.{Async, Resource, Temporal}
import cats.syntax.all.*
import fs2.Chunk
import fs2.io.net.Network
import io.github.arainko.ducktape.*
import io.renku.avro.codec.AvroReader
import io.renku.avro.codec.decoders.all.given
import io.renku.events.v1.ProjectCreated
import io.renku.events.v1
import io.renku.events.v1.{ProjectCreated, Visibility}
import io.renku.queue.client.*
import io.renku.redis.client.{ClientId, QueueName, RedisConfig}
import io.renku.search.model.*
Expand Down Expand Up @@ -126,23 +128,12 @@ private class SearchProvisionerImpl[F[_]: Async](
.onError(markProcessedOnFailure(lastMessage, queueClient))
}

private given Transformer[String, User] = (from: String) => User(users.Id(from))
private given Transformer[v1.Visibility, projects.Visibility] =
(from: v1.Visibility) => projects.Visibility.unsafeFromString(from.name())

private lazy val toSolrDocuments: Seq[ProjectCreated] => Seq[Project] =
_.map { pc =>

def toUser(id: String): User = User(users.Id(id))

Project(
projects.Id(pc.id),
projects.Name(pc.name),
projects.Slug(pc.slug),
pc.repositories.map(projects.Repository(_)),
projects.Visibility.unsafeFromString(pc.visibility.name()),
pc.description.map(projects.Description(_)),
toUser(pc.createdBy),
projects.CreationDate(pc.creationDate),
pc.members.map(toUser)
)
}
_.map(_.to[Project])

private def markProcessedOnFailure(
message: QueueMessage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,4 @@ class SearchProvisionerSpec extends CatsEffectSuite with QueueSpec with SearchSo
)

override def munitFixtures: Seq[Fixture[_]] =
List(withQueueClient, withSearchSolrClient)
List(withRedisClient, withQueueClient, withSearchSolrClient)
5 changes: 5 additions & 0 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ object Dependencies {
val catsParse = "1.0.0"
val catsScalaCheck = "0.3.2"
val ciris = "3.5.0"
val ducktape = "0.1.11"
val fs2 = "3.9.4"
val http4s = "0.23.25"
val luceneQueryParser = "9.9.2"
Expand Down Expand Up @@ -81,6 +82,10 @@ object Dependencies {
"org.typelevel" %% "munit-cats-effect-3" % V.catsEffectMunit
)

val ducktape = Seq(
"io.github.arainko" %% "ducktape" % V.ducktape
)

val fs2Core = Seq(
"co.fs2" %% "fs2-core" % V.fs2
)
Expand Down

0 comments on commit f0a7ac3

Please sign in to comment.