-
-
Notifications
You must be signed in to change notification settings - Fork 29
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
5e11c4e
commit 3d4d5d1
Showing
8 changed files
with
149 additions
and
18 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package lila.fishnet | ||
|
||
import cats.syntax.all.* | ||
import cats.effect.IO | ||
import cats.effect.std.Queue | ||
import cats.effect.kernel.Ref | ||
import lila.fishnet.Work.Acquired | ||
import org.joda.time.DateTime | ||
import lila.fishnet.Work.Move | ||
|
||
trait FishnetClient: | ||
def acquire(accquire: MoveDb.Acquire): IO[Option[Work]] | ||
def move(workId: Work.Id): IO[Option[Lila.Move]] | ||
|
||
trait LilaClient: | ||
def send(move: Lila.Move): IO[Unit] | ||
|
||
trait Executor: | ||
// get a move from the queue return Work | ||
def acquire(accquire: MoveDb.Acquire): IO[Option[Work.Move]] | ||
// get Work from Map => send to lila | ||
def move(workId: Work.Id, result: Fishnet.PostMove): IO[Unit] | ||
def add(work: Work.Move): IO[Unit] | ||
|
||
object Executor: | ||
|
||
def instance(client: LilaClient): IO[Executor] = | ||
for | ||
workQueue <- Queue.unbounded[IO, Work.Move] | ||
waitingQueue <- | ||
Ref.of[IO, Map[Work.Id, Work.Move]](Map.empty) // Verify concurrent access with AtomicCell | ||
yield new Executor: | ||
type State = Map[Work.Id, Work.Move] | ||
|
||
def add(work: Work.Move): IO[Unit] = | ||
workQueue.offer(work) | ||
|
||
def acquire(accquire: MoveDb.Acquire): IO[Option[Work.Move]] = | ||
for | ||
work <- workQueue.tryTake | ||
acquiredWork = work.map(_.copy(acquired = Work.Acquired(accquire.clientKey, DateTime.now).some)) | ||
_ <- acquiredWork.fold(IO.unit)(w => waitingQueue.update(_ + (w.id -> w))) | ||
yield acquiredWork | ||
|
||
def move(id: Work.Id, result: Fishnet.PostMove): IO[Unit] = | ||
waitingQueue.flatModify: m => | ||
m.get(id).fold(m -> notFound(id, result.fishnet.apikey).void): work => | ||
if work.isAcquiredBy(result.fishnet.apikey) then | ||
result.move.uci match | ||
case Some(uci) => | ||
val move = Lila.Move(work.game, uci) | ||
(m - id) -> client.send(move) | ||
case _ => updateOrGiveUp(m, work.invalid) | ||
else | ||
m -> notAcquired(work, result.fishnet.apikey) | ||
|
||
def updateOrGiveUp(state: State, move: Work.Move): (State, IO[Unit]) = | ||
val newState = state - move.id | ||
val io = if move.isOutOfTries then | ||
workQueue.offer(move) | ||
else | ||
IO.unit | ||
newState -> io | ||
|
||
// report not found | ||
def notFound(id: Work.Id, key: ClientKey): IO[Unit] = | ||
IO.println(s"not found $id, $key") | ||
|
||
// report not acquired | ||
def notAcquired(work: Work.Move, key: ClientKey): IO[Unit] = | ||
IO.println(s"not acquired $work, $key") |
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
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,22 @@ | ||
package lila.fishnet | ||
|
||
import chess.format.Uci | ||
|
||
trait StringValue extends Any: | ||
def value: String | ||
override def toString = value | ||
|
||
trait IntValue extends Any: | ||
def value: Int | ||
override def toString = value.toString | ||
|
||
case class IpAddress(value: String) extends AnyVal with StringValue | ||
|
||
case class ClientKey(value: String) extends AnyVal with StringValue | ||
|
||
object Fishnet: | ||
case class Fishnet(apikey: ClientKey) | ||
case class Acquire(fishnet: Fishnet) | ||
case class PostMove(fishnet: Fishnet, move: MoveResult) | ||
case class MoveResult(bestmove: String): | ||
def uci: Option[Uci] = Uci(bestmove) |
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 |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package lila.fishnet | ||
|
||
import weaver.* | ||
import weaver.scalacheck.Checkers | ||
import cats.effect.IO | ||
import cats.effect.kernel.Ref | ||
import org.joda.time.DateTime | ||
import monocle.syntax.all.* | ||
|
||
object ExecutorTest extends SimpleIOSuite with Checkers: | ||
|
||
val work = Work.Move( | ||
_id = Work.Id("id"), | ||
game = Work.Game( | ||
id = "id", | ||
initialFen = None, | ||
variant = chess.variant.Standard, | ||
moves = "", | ||
), | ||
level = 1, | ||
clock = None, | ||
tries = 0, | ||
lastTryByKey = None, | ||
acquired = None, | ||
createdAt = DateTime.now, | ||
) | ||
|
||
val key = ClientKey("key") | ||
|
||
test("add => acqurired => work"): | ||
for | ||
executor <- createExecutor() | ||
_ <- executor.add(work) | ||
acquiredOption <- executor.acquire(MoveDb.Acquire(ClientKey("key"))) | ||
acquired = acquiredOption.get | ||
yield assert(acquired.acquired.get.clientKey == key) `and` assert(acquired.copy(acquired = None) == work) | ||
|
||
def createExecutor(): IO[Executor] = | ||
createLilaClient.flatMap(Executor.instance) | ||
|
||
def createLilaClient: IO[LilaClient] = | ||
Ref.of[IO, List[Lila.Move]](Nil) | ||
.map: ref => | ||
new LilaClient: | ||
def send(move: Lila.Move): IO[Unit] = | ||
ref.update(_ :+ move) |
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