From 28df5cb10d6f6b0e6e7f933b0406da2f76d24428 Mon Sep 17 00:00:00 2001 From: Kevin Thomas Date: Mon, 25 Nov 2024 10:42:42 -0800 Subject: [PATCH] feat: exponential backoff and jitter to required play requests --- package-lock.json | 11 +++++ package.json | 1 + src/pages/play/hb.tsx | 102 +++++++++++++++++++++++++--------------- src/pages/play/maia.tsx | 43 +++++++++++------ 4 files changed, 104 insertions(+), 53 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5ec2104..97a7eca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "chess.ts": "^0.16.2", "chroma-js": "^2.4.2", "classnames": "^2.3.1", + "exponential-backoff": "^3.1.1", "framer-motion": "^11.5.6", "gray-matter": "^4.0.3", "lila-stockfish-web": "^0.0.7", @@ -3452,6 +3453,11 @@ "node": ">=0.8.x" } }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -10092,6 +10098,11 @@ "dev": true, "peer": true }, + "exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", diff --git a/package.json b/package.json index 39a6bfa..2a25c23 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "chess.ts": "^0.16.2", "chroma-js": "^2.4.2", "classnames": "^2.3.1", + "exponential-backoff": "^3.1.1", "framer-motion": "^11.5.6", "gray-matter": "^4.0.3", "lila-stockfish-web": "^0.0.7", diff --git a/src/pages/play/hb.tsx b/src/pages/play/hb.tsx index 2d40131..5434944 100644 --- a/src/pages/play/hb.tsx +++ b/src/pages/play/hb.tsx @@ -1,23 +1,25 @@ import { NextPage } from 'next/types' -import { usePlayController } from 'src/hooks/usePlayController' -import { GameplayInterface } from 'src/components/GameplayInterface' +import { PieceSymbol } from 'chess.ts' +import { useRouter } from 'next/router' +import type { Key } from 'chessground/types' +import { backOff } from 'exponential-backoff' +import type { DrawShape } from 'chessground/draw' +import { useCallback, useContext, useEffect, useMemo, useState } from 'react' + import { - getGameMove, - getPlayPlayerStats, startGame, + getGameMove, submitGameMove, + getPlayPlayerStats, } from 'src/api' -import { PlayControllerContext } from 'src/contexts/PlayControllerContext/PlayControllerContext' -import { useCallback, useContext, useEffect, useMemo, useState } from 'react' -import type { DrawShape } from 'chessground/draw' -import type { Key } from 'chessground/types' -import { HandBrainPlayControls } from 'src/components/HandBrainPlayControls' -import { PieceSymbol } from 'chess.ts' -import { Color, PlayGameConfig, TimeControl } from 'src/types' -import { useRouter } from 'next/router' import { Loading } from 'src/components' -import { useStats } from 'src/hooks/useStats' import { ModalContext } from 'src/contexts' +import { useStats } from 'src/hooks/useStats' +import { Color, PlayGameConfig, TimeControl } from 'src/types' +import { usePlayController } from 'src/hooks/usePlayController' +import { GameplayInterface } from 'src/components/GameplayInterface' +import { HandBrainPlayControls } from 'src/components/HandBrainPlayControls' +import { PlayControllerContext } from 'src/contexts/PlayControllerContext/PlayControllerContext' const brainStatsLoader = async () => { const stats = await getPlayPlayerStats() @@ -79,10 +81,16 @@ const useHandBrainPlayController = ( let canceled = false const maiaChoosePiece = async () => { - const maiaMoves = await getGameMove( - controller.moves, - playGameConfig.maiaPartnerVersion, - playGameConfig.startFen, + const maiaMoves = await backOff( + () => + getGameMove( + controller.moves, + playGameConfig.maiaPartnerVersion, + playGameConfig.startFen, + ), + { + jitter: 'full', + }, ) const nextMove = maiaMoves['top_move'] @@ -134,13 +142,19 @@ const useHandBrainPlayController = ( ? parseInt(controller.timeControl.split('+')[0]) * 60 : 0 - const maiaMoves = await getGameMove( - controller.moves, - playGameConfig.maiaVersion, - playGameConfig.startFen, - null, - playGameConfig.simulateMaiaTime ? initialClock : 0, - playGameConfig.simulateMaiaTime ? maiaClock : 0, + const maiaMoves = await backOff( + () => + getGameMove( + controller.moves, + playGameConfig.maiaVersion, + playGameConfig.startFen, + null, + playGameConfig.simulateMaiaTime ? initialClock : 0, + playGameConfig.simulateMaiaTime ? maiaClock : 0, + ), + { + jitter: 'full', + }, ) const nextMove = maiaMoves['top_move'] const moveDelay = maiaMoves['move_delay'] @@ -183,11 +197,17 @@ const useHandBrainPlayController = ( setSelectedPiece(piece) setBrainMoves([...brainMoves, piece]) - const maiaMoves = await getGameMove( - controller.moves, - playGameConfig.maiaPartnerVersion, - playGameConfig.startFen, - piece, + const maiaMoves = await backOff( + () => + getGameMove( + controller.moves, + playGameConfig.maiaPartnerVersion, + playGameConfig.startFen, + piece, + ), + { + jitter: 'full', + }, ) const nextMove = maiaMoves['top_move'] makeMove(nextMove) @@ -236,15 +256,21 @@ const useHandBrainPlayController = ( const winner = controller.game.termination?.winner const submitFn = async () => { - await submitGameMove( - controller.game.id, - controller.moves, - controller.moveTimes, - gameOverState, - playGameConfig.isBrain ? 'brain' : 'hand', - playGameConfig.startFen || undefined, - winner, - brainMoves, + await backOff( + () => + submitGameMove( + controller.game.id, + controller.moves, + controller.moveTimes, + gameOverState, + playGameConfig.isBrain ? 'brain' : 'hand', + playGameConfig.startFen || undefined, + winner, + brainMoves, + ), + { + jitter: 'full', + }, ) if (controller.game.termination) { const winner = controller.game.termination?.winner diff --git a/src/pages/play/maia.tsx b/src/pages/play/maia.tsx index a8fb29b..2eae3d2 100644 --- a/src/pages/play/maia.tsx +++ b/src/pages/play/maia.tsx @@ -1,5 +1,6 @@ import { NextPage } from 'next/types' import { useRouter } from 'next/router' +import { backOff } from 'exponential-backoff' import { useContext, useEffect, useMemo } from 'react' import { @@ -59,13 +60,19 @@ const useVsMaiaPlayController = ( ? parseInt(controller.timeControl.split('+')[0]) * 60 : 0 - const maiaMoves = await getGameMove( - controller.moves, - playGameConfig.maiaVersion, - playGameConfig.startFen, - null, - playGameConfig.simulateMaiaTime ? initialClock : 0, - playGameConfig.simulateMaiaTime ? maiaClock : 0, + const maiaMoves = await backOff( + () => + getGameMove( + controller.moves, + playGameConfig.maiaVersion, + playGameConfig.startFen, + null, + playGameConfig.simulateMaiaTime ? initialClock : 0, + playGameConfig.simulateMaiaTime ? maiaClock : 0, + ), + { + jitter: 'full', + }, ) const nextMove = maiaMoves['top_move'] const moveDelay = maiaMoves['move_delay'] @@ -106,14 +113,20 @@ const useVsMaiaPlayController = ( const winner = controller.game.termination?.winner const submitFn = async () => { - await submitGameMove( - controller.game.id, - controller.moves, - controller.moveTimes, - gameOverState, - 'play', - playGameConfig.startFen || undefined, - winner, + await backOff( + () => + submitGameMove( + controller.game.id, + controller.moves, + controller.moveTimes, + gameOverState, + 'play', + playGameConfig.startFen || undefined, + winner, + ), + { + jitter: 'full', + }, ) // Only update stats after final move submitted