Skip to content

Commit

Permalink
Implement store endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
lenguyenthanh committed May 10, 2024
1 parent 2a3eadb commit 8afbc94
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 7 deletions.
4 changes: 4 additions & 0 deletions modules/api/src/main/smithy/_global.smithy
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ list Ids {
member: String
}

list Strings {
member: String
}

structure CountResponse {
@required
count: Integer
Expand Down
130 changes: 129 additions & 1 deletion modules/api/src/main/smithy/search.smithy
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ namespace lila.search.spec
use alloy#simpleRestJson
use smithy4s.meta#adt
use smithy.api#default
use smithy.api#jsonName

@simpleRestJson
service SearchService {
version: "3.0.0"
operations: [Search, Count, DeleteById, DeleteByIds, Mapping, Refresh]
operations: [Search, Count, DeleteById, DeleteByIds, Mapping, Refresh, Store]
}

@readonly
Expand Down Expand Up @@ -52,6 +53,12 @@ operation Refresh {
errors: [InternalServerError]
}

@http(method: "POST", uri: "/store/{id}", code: 200)
operation Store {
input: StoreInput
errors: [InternalServerError]
}

structure SearchInput {

@required
Expand Down Expand Up @@ -102,6 +109,16 @@ structure RefreshInput {
index: Index
}

structure StoreInput {

@required
source: Source

@httpLabel
@required
id: String
}

structure Forum {
@required
text: String
Expand Down Expand Up @@ -180,6 +197,117 @@ union Query {
team: Team
}

structure ForumSource {
@required
@jsonName("bo")
body: String
@required
@jsonName("to")
topic: String
@required
@jsonName("ti")
topicId: String
@jsonName("au")
author: String
@required
@jsonName("tr")
troll: Boolean
@required
@jsonName("da")
date: Timestamp
}

structure GameSource {
@required
@jsonName("s")
status: String
@required
@jsonName("t")
turns: Integer
@required
@jsonName("r")
rated: Boolean
@required
@jsonName("p")
perf: String
@jsonName("u")
uids: Ids
@jsonName("w")
winner: String
@jsonName("o")
loser: String
@required
@jsonName("c")
winnerColor: Integer
@required
@jsonName("a")
averageRating: Integer
@required
@jsonName("i")
hasAi: Boolean
@required
@jsonName("d")
date: Timestamp // or string?
@required
@jsonName("l")
duration: Integer
@required
@jsonName("ct")
clockInit: Integer
@jsonName("ci")
clockInc: Integer
@jsonName("n")
analysed: Boolean
@required
@jsonName("wu")
whiteUser: String
@required
@jsonName("bu")
blackUser: String
@jsonName("so")
source: Integer
}

structure StudySource {
@required
name: String
@required
owner: String
@required
members: Ids
@required
chapterNames: String

@required
chapterTexts: String
@default
topics: Strings
@required
likes: Integer
@required
public: Boolean
}

structure TeamSource {
@required
@jsonName("na")
name: String
@required
@jsonName("de")
description: String
@required
@jsonName("nbm")
nbMembers: Integer
}

@adt
union Source {
forum: ForumSource
game: GameSource
study: StudySource
team: TeamSource
}

enum Index {
Forum = "forum"
Game = "game"
Expand Down
32 changes: 32 additions & 0 deletions modules/app/src/main/scala/service.search.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,20 @@ import forum.ForumQuery.*
import io.github.arainko.ducktape.*
import org.joda.time.DateTime
import smithy4s.Timestamp
import com.sksamuel.elastic4s.Indexable
import smithy4s.schema.Schema

class SearchServiceImpl(esClient: ESClient[IO])(using Logger[IO]) extends SearchService[IO]:

import SearchServiceImpl.{ given, * }

override def store(source: Source, id: String): IO[Unit] =
esClient
.store(source.index, Id(id), source)
.handleErrorWith: e =>
error"Error in store: source=$source, id=$id" *>
IO.raiseError(InternalServerError("Internal server error"))

override def refresh(index: Index): IO[Unit] =
esClient
.refreshIndex(index.transform)
Expand Down Expand Up @@ -108,3 +117,26 @@ object SearchServiceImpl:
case q: Query.Game => lila.search.Index("game")
case q: Query.Study => lila.search.Index("study")
case q: Query.Team => lila.search.Index("team")

// given Indexable[Source] = (s: Source) => writeToString(s)

import smithy4s.json.Json.given
import com.github.plokhotnyuk.jsoniter_scala.core._
given Schema[Source.ForumSource] = lila.search.spec.Source.ForumSource.schema
given Schema[Source.GameSource] = lila.search.spec.Source.GameSource.schema
given Schema[Source.StudySource] = lila.search.spec.Source.StudySource.schema
given Schema[Source.TeamSource] = lila.search.spec.Source.TeamSource.schema

given Indexable[Source] = (s: Source) =>
s match
case s: Source.ForumSource => writeToString[Source.ForumSource](s)
case s: Source.GameSource => writeToString[Source.GameSource](s)
case s: Source.StudySource => writeToString[Source.StudySource](s)
case s: Source.TeamSource => writeToString[Source.TeamSource](s)

extension (source: Source)
def index = source match
case s: Source.ForumSource => lila.search.Index("forum")
case s: Source.GameSource => lila.search.Index("game")
case s: Source.StudySource => lila.search.Index("study")
case s: Source.TeamSource => lila.search.Index("team")
6 changes: 6 additions & 0 deletions modules/client/src/main/scala/PlayClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ class PlayClient(client: StandaloneWSClient, baseUrl: String)(using ExecutionCon

import implicits.given

override def store(source: Source, id: String): Future[Unit] =
client
.url(s"$baseUrl/store/$id")
.post(source)
.map(_ => ())

override def refresh(index: Index): Future[Unit] =
client
.url(s"$baseUrl/refresh/${index.name}")
Expand Down
6 changes: 5 additions & 1 deletion modules/e2e/src/test/scala/CompatSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import com.comcast.ip4s.*
import akka.actor.ActorSystem
import play.api.libs.ws.*
import play.api.libs.ws.ahc.*
import lila.search.spec.{ Query, Index as SpecIndex }
import lila.search.spec.{ Query, Index as SpecIndex, Source }
import scala.concurrent.ExecutionContext.Implicits.*
import com.sksamuel.elastic4s.Indexable

Expand Down Expand Up @@ -50,6 +50,10 @@ object CompatSuite extends weaver.IOSuite:
test("refresh endpoint"): client =>
IO.fromFuture(IO(client.refresh(SpecIndex.Forum))).map(expect.same(_, ()))

test("store endpoint"): client =>
val source = Source.teamSource("names", "desc", 100)
IO.fromFuture(IO(client.store(source, "id"))).map(expect.same(_, ()))

def testAppConfig = AppConfig(
server = HttpServerConfig(ip"0.0.0.0", port"9999", shutdownTimeout = 1),
elastic = ElasticConfig("http://0.0.0.0:9200")
Expand Down
10 changes: 5 additions & 5 deletions play/app/src/main/scala/controllers/WebApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@ class WebApi @Inject() (cc: ControllerComponents, client: ESClient[Future])(impl
implicit val indexableJsValue: Indexable[JsValue] = (t: JsValue) => Json.stringify(t)
implicit val indexableJsObject: Indexable[JsObject] = (t: JsObject) => Json.stringify(t)

def store(index: String, id: String) =
JsObjectBody { obj =>
client.store(Index(index), Id(id), obj).inject(Ok(s"inserted $index/$id"))
}

def deleteById(index: String, id: String) =
Action.async {
client.deleteOne(Index(index), Id(id)).inject(Ok(s"deleted $index/$id"))
Expand Down Expand Up @@ -66,6 +61,11 @@ class WebApi @Inject() (cc: ControllerComponents, client: ESClient[Future])(impl
}
}

def store(index: String, id: String) =
JsObjectBody { obj =>
client.store(Index(index), Id(id), obj).inject(Ok(s"inserted $index/$id"))
}

def storeBulk(index: String) =
JsObjectBody { objs =>
Chronometer(s"bulk ${objs.fields.size} $index") {
Expand Down

0 comments on commit 8afbc94

Please sign in to comment.