chore(marketplace): add a cache for storage requests (#1090)

* Add cache to for requests

* Change request cache description message and use const as default value

* Set request cache size configuration hidden
This commit is contained in:
Arnaud 2025-02-17 11:34:42 +01:00 committed by GitHub
parent 25c84f4e0e
commit dc08ff8840
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 50 additions and 5 deletions

View File

@ -109,7 +109,9 @@ proc bootstrapInteractions(s: CodexServer): Future[void] {.async.} =
quit QuitFailure quit QuitFailure
let marketplace = Marketplace.new(marketplaceAddress, signer) let marketplace = Marketplace.new(marketplaceAddress, signer)
let market = OnChainMarket.new(marketplace, config.rewardRecipient) let market = OnChainMarket.new(
marketplace, config.rewardRecipient, config.marketplaceRequestCacheSize
)
let clock = OnChainClock.new(provider) let clock = OnChainClock.new(provider)
var client: ?ClientInteractions var client: ?ClientInteractions

View File

@ -44,6 +44,7 @@ import ./utils
import ./nat import ./nat
import ./utils/natutils import ./utils/natutils
from ./contracts/config import DefaultRequestCacheSize
from ./validationconfig import MaxSlots, ValidationGroups from ./validationconfig import MaxSlots, ValidationGroups
export units, net, codextypes, logutils, completeCmdArg, parseCmdArg, NatConfig export units, net, codextypes, logutils, completeCmdArg, parseCmdArg, NatConfig
@ -51,7 +52,7 @@ export ValidationGroups, MaxSlots
export export
DefaultQuotaBytes, DefaultBlockTtl, DefaultBlockMaintenanceInterval, DefaultQuotaBytes, DefaultBlockTtl, DefaultBlockMaintenanceInterval,
DefaultNumberOfBlocksToMaintainPerInterval DefaultNumberOfBlocksToMaintainPerInterval, DefaultRequestCacheSize
type ThreadCount* = distinct Natural type ThreadCount* = distinct Natural
@ -359,6 +360,16 @@ type
name: "reward-recipient" name: "reward-recipient"
.}: Option[EthAddress] .}: Option[EthAddress]
marketplaceRequestCacheSize* {.
desc:
"Maximum number of StorageRequests kept in memory." &
"Reduces fetching of StorageRequest data from the contract.",
defaultValue: DefaultRequestCacheSize,
defaultValueDesc: $DefaultRequestCacheSize,
name: "request-cache-size",
hidden
.}: uint16
case persistenceCmd* {.defaultValue: noCmd, command.}: PersistenceCmd case persistenceCmd* {.defaultValue: noCmd, command.}: PersistenceCmd
of PersistenceCmd.prover: of PersistenceCmd.prover:
circuitDir* {. circuitDir* {.

View File

@ -4,6 +4,8 @@ import pkg/questionable/results
export contractabi export contractabi
const DefaultRequestCacheSize* = 128.uint16
type type
MarketplaceConfig* = object MarketplaceConfig* = object
collateral*: CollateralConfig collateral*: CollateralConfig

View File

@ -2,6 +2,7 @@ import std/strutils
import pkg/ethers import pkg/ethers
import pkg/upraises import pkg/upraises
import pkg/questionable import pkg/questionable
import pkg/lrucache
import ../utils/exceptions import ../utils/exceptions
import ../logutils import ../logutils
import ../market import ../market
@ -20,6 +21,7 @@ type
signer: Signer signer: Signer
rewardRecipient: ?Address rewardRecipient: ?Address
configuration: ?MarketplaceConfig configuration: ?MarketplaceConfig
requestCache: LruCache[string, StorageRequest]
MarketSubscription = market.Subscription MarketSubscription = market.Subscription
EventSubscription = ethers.Subscription EventSubscription = ethers.Subscription
@ -27,12 +29,22 @@ type
eventSubscription: EventSubscription eventSubscription: EventSubscription
func new*( func new*(
_: type OnChainMarket, contract: Marketplace, rewardRecipient = Address.none _: type OnChainMarket,
contract: Marketplace,
rewardRecipient = Address.none,
requestCacheSize: uint16 = DefaultRequestCacheSize,
): OnChainMarket = ): OnChainMarket =
without signer =? contract.signer: without signer =? contract.signer:
raiseAssert("Marketplace contract should have a signer") raiseAssert("Marketplace contract should have a signer")
OnChainMarket(contract: contract, signer: signer, rewardRecipient: rewardRecipient) var requestCache = newLruCache[string, StorageRequest](int(requestCacheSize))
OnChainMarket(
contract: contract,
signer: signer,
rewardRecipient: rewardRecipient,
requestCache: requestCache,
)
proc raiseMarketError(message: string) {.raises: [MarketError].} = proc raiseMarketError(message: string) {.raises: [MarketError].} =
raise newException(MarketError, message) raise newException(MarketError, message)
@ -112,9 +124,16 @@ method requestStorage(market: OnChainMarket, request: StorageRequest) {.async.}
method getRequest*( method getRequest*(
market: OnChainMarket, id: RequestId market: OnChainMarket, id: RequestId
): Future[?StorageRequest] {.async.} = ): Future[?StorageRequest] {.async.} =
let key = $id
if market.requestCache.contains(key):
return some market.requestCache[key]
convertEthersError: convertEthersError:
try: try:
return some await market.contract.getRequest(id) let request = await market.contract.getRequest(id)
market.requestCache[key] = request
return some request
except Marketplace_UnknownRequest: except Marketplace_UnknownRequest:
return none StorageRequest return none StorageRequest

View File

@ -3,6 +3,7 @@ import std/importutils
import pkg/chronos import pkg/chronos
import pkg/ethers/erc20 import pkg/ethers/erc20
import codex/contracts import codex/contracts
import pkg/lrucache
import ../ethertest import ../ethertest
import ./examples import ./examples
import ./time import ./time
@ -591,3 +592,13 @@ ethersuite "On-Chain Market":
let expectedPayout = request.expectedPayout(filledAt, requestEnd.u256) let expectedPayout = request.expectedPayout(filledAt, requestEnd.u256)
check endBalanceHost == (startBalanceHost + request.ask.collateralPerSlot) check endBalanceHost == (startBalanceHost + request.ask.collateralPerSlot)
check endBalanceReward == (startBalanceReward + expectedPayout) check endBalanceReward == (startBalanceReward + expectedPayout)
test "the request is added in cache after the fist access":
await market.requestStorage(request)
check market.requestCache.contains($request.id) == false
discard await market.getRequest(request.id)
check market.requestCache.contains($request.id) == true
let cacheValue = market.requestCache[$request.id]
check cacheValue == request