[sales] call onSale() when offer has been selected

This commit is contained in:
Mark Spanbroek 2022-03-31 10:24:06 +02:00 committed by markspanbroek
parent 71baedb5ec
commit 2ffde32772
4 changed files with 67 additions and 8 deletions

View File

@ -46,5 +46,5 @@ method subscribeSelection*(market: Market,
Future[Subscription] {.base, async.} = Future[Subscription] {.base, async.} =
raiseAssert("not implemented") raiseAssert("not implemented")
method unsubscribe*(subscription: Subscription) {.base, async.} = method unsubscribe*(subscription: Subscription) {.base, async, upraises:[].} =
raiseAssert("not implemented") raiseAssert("not implemented")

View File

@ -13,14 +13,16 @@ const DefaultOfferExpiryInterval = (10 * 60).u256
type type
Sales* = ref object Sales* = ref object
market: Market market: Market
available*: seq[Availability]
subscription: ?Subscription subscription: ?Subscription
available*: seq[Availability]
offerExpiryInterval*: UInt256 offerExpiryInterval*: UInt256
onSale*: OnSale
Availability* = object Availability* = object
id*: array[32, byte] id*: array[32, byte]
size*: uint64 size*: uint64
duration*: uint64 duration*: uint64
minPrice*: UInt256 minPrice*: UInt256
OnSale = proc(offer: StorageOffer) {.gcsafe, upraises: [].}
func new*(_: type Sales, market: Market): Sales = func new*(_: type Sales, market: Market): Sales =
Sales(market: market, offerExpiryInterval: DefaultOfferExpiryInterval) Sales(market: market, offerExpiryInterval: DefaultOfferExpiryInterval)
@ -56,11 +58,21 @@ proc createOffer(sales: Sales,
) )
proc handleRequest(sales: Sales, request: StorageRequest) {.async.} = proc handleRequest(sales: Sales, request: StorageRequest) {.async.} =
if availability =? sales.findAvailability(request): without availability =? sales.findAvailability(request):
return
sales.remove(availability) sales.remove(availability)
let offer = sales.createOffer(request, availability) let offer = sales.createOffer(request, availability)
await sales.market.offerStorage(offer) await sales.market.offerStorage(offer)
var subscription: ?Subscription
proc onSelect(offerId: array[32, byte]) {.gcsafe, upraises:[].} =
if subscription =? subscription:
asyncSpawn subscription.unsubscribe()
sales.onSale(offer)
subscription = some await sales.market.subscribeSelection(request.id, onSelect)
proc start*(sales: Sales) = proc start*(sales: Sales) =
doAssert sales.subscription.isNone, "Sales already started" doAssert sales.subscription.isNone, "Sales already started"

View File

@ -1,5 +1,6 @@
import std/sequtils import std/sequtils
import std/heapqueue import std/heapqueue
import pkg/questionable
import pkg/dagger/market import pkg/dagger/market
export market export market
@ -15,6 +16,7 @@ type
Subscriptions = object Subscriptions = object
onRequest: seq[RequestSubscription] onRequest: seq[RequestSubscription]
onOffer: seq[OfferSubscription] onOffer: seq[OfferSubscription]
onSelect: seq[SelectSubscription]
RequestSubscription* = ref object of Subscription RequestSubscription* = ref object of Subscription
market: MockMarket market: MockMarket
callback: OnRequest callback: OnRequest
@ -22,23 +24,39 @@ type
market: MockMarket market: MockMarket
requestId: array[32, byte] requestId: array[32, byte]
callback: OnOffer callback: OnOffer
SelectSubscription* = ref object of Subscription
market: MockMarket
requestId: array[32, byte]
callback: OnSelect
Expiry = object Expiry = object
future: Future[void] future: Future[void]
expiry: UInt256 expiry: UInt256
method requestStorage*(market: MockMarket, request: StorageRequest) {.async.} = method requestStorage*(market: MockMarket, request: StorageRequest) {.async.} =
market.requested.add(request) market.requested.add(request)
for subscription in market.subscriptions.onRequest: let subscriptions = market.subscriptions.onRequest
for subscription in subscriptions:
subscription.callback(request) subscription.callback(request)
method offerStorage*(market: MockMarket, offer: StorageOffer) {.async.} = method offerStorage*(market: MockMarket, offer: StorageOffer) {.async.} =
market.offered.add(offer) market.offered.add(offer)
for subscription in market.subscriptions.onOffer: let subscriptions = market.subscriptions.onOffer
for subscription in subscriptions:
if subscription.requestId == offer.requestId: if subscription.requestId == offer.requestId:
subscription.callback(offer) subscription.callback(offer)
proc findOffer(market: MockMarket, id: array[32, byte]): ?StorageOffer =
for offer in market.offered:
if offer.id == id:
return some offer
method selectOffer*(market: MockMarket, id: array[32, byte]) {.async.} = method selectOffer*(market: MockMarket, id: array[32, byte]) {.async.} =
market.selected.add(id) market.selected.add(id)
let subscriptions = market.subscriptions.onSelect
for subscription in subscriptions:
if offer =? market.findOffer(id):
if subscription.requestId == offer.requestId:
subscription.callback(id)
method subscribeRequests*(market: MockMarket, method subscribeRequests*(market: MockMarket,
callback: OnRequest): callback: OnRequest):
@ -62,12 +80,27 @@ method subscribeOffers*(market: MockMarket,
market.subscriptions.onOffer.add(subscription) market.subscriptions.onOffer.add(subscription)
return subscription return subscription
method subscribeSelection*(market: MockMarket,
requestId: array[32, byte],
callback: OnSelect):
Future[Subscription] {.async.} =
let subscription = SelectSubscription(
market: market,
requestId: requestId,
callback: callback
)
market.subscriptions.onSelect.add(subscription)
return subscription
method unsubscribe*(subscription: RequestSubscription) {.async.} = method unsubscribe*(subscription: RequestSubscription) {.async.} =
subscription.market.subscriptions.onRequest.keepItIf(it != subscription) subscription.market.subscriptions.onRequest.keepItIf(it != subscription)
method unsubscribe*(subscription: OfferSubscription) {.async.} = method unsubscribe*(subscription: OfferSubscription) {.async.} =
subscription.market.subscriptions.onOffer.keepItIf(it != subscription) subscription.market.subscriptions.onOffer.keepItIf(it != subscription)
method unsubscribe*(subscription: SelectSubscription) {.async.} =
subscription.market.subscriptions.onSelect.keepItIf(it != subscription)
func `<`(a, b: Expiry): bool = func `<`(a, b: Expiry): bool =
a.expiry < b.expiry a.expiry < b.expiry

View File

@ -74,3 +74,17 @@ suite "Sales":
await market.requestStorage(request) await market.requestStorage(request)
check market.offered[0].expiry == now + sales.offerExpiryInterval check market.offered[0].expiry == now + sales.offerExpiryInterval
sales.stop() sales.stop()
test "call onSale when offer is selected":
let availability = Availability.init(size=100, duration=60, minPrice=42.u256)
sales.add(availability)
var selectedOffer: StorageOffer
sales.onSale = proc(offer: StorageOffer) =
selectedOffer = offer
sales.start()
let request = StorageRequest(duration:60.u256, size:100.u256, maxPrice:42.u256)
await market.requestStorage(request)
let offer = market.offered[0]
await market.selectOffer(offer.id)
check selectedOffer == offer
sales.stop()