nim-codex/codex/sales/salesagent.nim

86 lines
2.3 KiB
Nim
Raw Normal View History

import pkg/chronos
import pkg/upraises
import pkg/stint
import ./statemachine
import ./states/[downloading, unknown]
import ../contracts/requests
import ../rng
proc newSalesAgent*(sales: Sales,
requestId: RequestId,
availability: ?Availability,
request: ?StorageRequest): SalesAgent =
SalesAgent(
sales: sales,
requestId: requestId,
availability: availability,
request: request)
# fwd declarations
proc subscribeCancellation*(agent: SalesAgent): Future[void] {.gcsafe.}
proc subscribeFailure*(agent: SalesAgent): Future[void] {.gcsafe.}
proc populateRequest(agent: SalesAgent) {.async.} =
if agent.request.isNone:
agent.request = await agent.sales.market.getRequest(agent.requestId)
proc init*(agent: SalesAgent, numSlots: uint64) {.async.} =
let rng = Rng.instance
let slotIndex = rng.rand(numSlots - 1)
agent.slotIndex = some slotIndex.u256
# TODO: try not to block the thread waiting for the network
await agent.populateRequest()
await agent.subscribeCancellation()
await agent.subscribeFailure()
proc deinit*(agent: SalesAgent) {.async.} =
try:
await agent.fulfilled.unsubscribe()
except CatchableError:
discard
try:
await agent.failed.unsubscribe()
except CatchableError:
discard
if not agent.cancelled.completed:
await agent.cancelled.cancelAndWait()
proc subscribeCancellation*(agent: SalesAgent) {.async.} =
let market = agent.sales.market
proc onCancelled() {.async.} =
let clock = agent.sales.clock
without request =? agent.request:
return
await clock.waitUntil(request.expiry.truncate(int64))
await agent.fulfilled.unsubscribe()
without state =? (agent.state as SaleState):
return
await state.onCancelled(request)
agent.cancelled = onCancelled()
proc onFulfilled(_: RequestId) {.async.} =
agent.cancelled.cancel()
agent.fulfilled =
await market.subscribeFulfillment(agent.requestId, onFulfilled)
proc subscribeFailure*(agent: SalesAgent) {.async.} =
let market = agent.sales.market
proc onFailed(_: RequestId) {.async.} =
without request =? agent.request:
return
without state =? (agent.state as SaleState):
return
await state.onFailed(request)
agent.failed =
await market.subscribeRequestFailed(agent.requestId, onFailed)