[rest api] submit storage request parameters as json
This commit is contained in:
parent
fec9ad8141
commit
7d03e83bfc
|
@ -207,14 +207,12 @@ proc store*(
|
||||||
|
|
||||||
return manifest.cid.success
|
return manifest.cid.success
|
||||||
|
|
||||||
proc requestStorage*(
|
proc requestStorage*(self: DaggerNodeRef,
|
||||||
self: DaggerNodeRef,
|
|
||||||
cid: Cid,
|
cid: Cid,
|
||||||
ppb: uint,
|
duration: UInt256,
|
||||||
duration: Duration,
|
|
||||||
nodes: uint,
|
nodes: uint,
|
||||||
tolerance: uint,
|
tolerance: uint,
|
||||||
autoRenew: bool = false): Future[?!Cid] {.async.} =
|
maxPrice: UInt256): Future[?!Cid] {.async.} =
|
||||||
## Initiate a request for storage sequence, this might
|
## Initiate a request for storage sequence, this might
|
||||||
## be a multistep procedure.
|
## be a multistep procedure.
|
||||||
##
|
##
|
||||||
|
@ -224,7 +222,7 @@ proc requestStorage*(
|
||||||
## - Run the PoR setup on the erasure dataset
|
## - Run the PoR setup on the erasure dataset
|
||||||
## - Call into the marketplace and purchasing contracts
|
## - Call into the marketplace and purchasing contracts
|
||||||
##
|
##
|
||||||
trace "Received a request for storage!", cid, ppb, duration, nodes, tolerance, autoRenew
|
trace "Received a request for storage!", cid, duration, nodes, tolerance, maxPrice
|
||||||
|
|
||||||
without blk =? (await self.blockStore.getBlock(cid)), error:
|
without blk =? (await self.blockStore.getBlock(cid)), error:
|
||||||
trace "Unable to retrieve manifest block", cid
|
trace "Unable to retrieve manifest block", cid
|
||||||
|
|
|
@ -175,90 +175,35 @@ proc initRestApi*(node: DaggerNodeRef, conf: DaggerConf): RestRouter =
|
||||||
if not stream.isNil:
|
if not stream.isNil:
|
||||||
await stream.close()
|
await stream.close()
|
||||||
|
|
||||||
router.api(
|
router.rawApi(
|
||||||
MethodPost,
|
MethodPost,
|
||||||
"/api/dagger/v1/storage/request/{cid}") do (
|
"/api/dagger/v1/storage/request/{cid}") do (cid: Cid) -> RestApiResponse:
|
||||||
cid: Cid,
|
|
||||||
ppb: Option[uint],
|
|
||||||
duration: Option[Duration],
|
|
||||||
nodes: Option[uint],
|
|
||||||
loss: Option[uint],
|
|
||||||
renew: Option[bool]) -> RestApiResponse:
|
|
||||||
## Create a request for storage
|
## Create a request for storage
|
||||||
##
|
##
|
||||||
## Cid - the cid of the previously uploaded dataset
|
## cid - the cid of a previously uploaded dataset
|
||||||
## ppb - the price per byte the client is willing to pay
|
|
||||||
## duration - the duration of the contract
|
## duration - the duration of the contract
|
||||||
## nodeCount - the total amount of the nodes storing the dataset, including `lossTolerance`
|
## maxPrice - the maximum price the client is willing to pay
|
||||||
## lossTolerance - the number of nodes losses the user is willing to tolerate
|
|
||||||
## autoRenew - should the contract be autorenewed -
|
|
||||||
## will fail unless the user has enough funds lockedup
|
|
||||||
##
|
|
||||||
|
|
||||||
var
|
# TODO: store on multiple nodes
|
||||||
cid =
|
let nodes: uint = 1
|
||||||
if cid.isErr:
|
let tolerance: uint = 0
|
||||||
return RestApiResponse.error(Http400, $cid.error())
|
|
||||||
else:
|
|
||||||
cid.get()
|
|
||||||
|
|
||||||
ppb =
|
without cid =? cid.tryGet.catch, error:
|
||||||
if ppb.isNone:
|
return RestApiResponse.error(Http400, error.msg)
|
||||||
return RestApiResponse.error(Http400, "Missing ppb")
|
|
||||||
else:
|
|
||||||
if ppb.get().isErr:
|
|
||||||
return RestApiResponse.error(Http500, $ppb.get().error)
|
|
||||||
else:
|
|
||||||
ppb.get().get()
|
|
||||||
|
|
||||||
duration =
|
let body = await request.getBody()
|
||||||
if duration.isNone:
|
|
||||||
return RestApiResponse.error(Http400, "Missing duration")
|
|
||||||
else:
|
|
||||||
if duration.get().isErr:
|
|
||||||
return RestApiResponse.error(Http500, $duration.get().error)
|
|
||||||
else:
|
|
||||||
duration.get().get()
|
|
||||||
|
|
||||||
nodes =
|
without params =? StorageRequestParams.fromJson(body), error:
|
||||||
if nodes.isNone:
|
return RestApiResponse.error(Http400, error.msg)
|
||||||
return RestApiResponse.error(Http400, "Missing node count")
|
|
||||||
else:
|
|
||||||
if nodes.get().isErr:
|
|
||||||
return RestApiResponse.error(Http500, $nodes.get().error)
|
|
||||||
else:
|
|
||||||
nodes.get().get()
|
|
||||||
|
|
||||||
loss =
|
without storageCid =? await node.requestStorage(cid,
|
||||||
if loss.isNone:
|
params.duration,
|
||||||
return RestApiResponse.error(Http400, "Missing loss tolerance")
|
|
||||||
else:
|
|
||||||
if loss.get().isErr:
|
|
||||||
return RestApiResponse.error(Http500, $loss.get().error)
|
|
||||||
else:
|
|
||||||
loss.get().get()
|
|
||||||
|
|
||||||
renew = if renew.isNone:
|
|
||||||
false
|
|
||||||
else:
|
|
||||||
if renew.get().isErr:
|
|
||||||
return RestApiResponse.error(Http500, $renew.get().error)
|
|
||||||
else:
|
|
||||||
renew.get().get()
|
|
||||||
|
|
||||||
try:
|
|
||||||
without storageCid =? (await node.requestStorage(
|
|
||||||
cid,
|
|
||||||
ppb,
|
|
||||||
duration,
|
|
||||||
nodes,
|
nodes,
|
||||||
loss,
|
tolerance,
|
||||||
renew)), error:
|
params.maxPrice), error:
|
||||||
return RestApiResponse.error(Http500, error.msg)
|
return RestApiResponse.error(Http500, error.msg)
|
||||||
|
|
||||||
return RestApiResponse.response($storageCid)
|
return RestApiResponse.response($storageCid)
|
||||||
except CatchableError as exc:
|
|
||||||
return RestApiResponse.error(Http500, exc.msg)
|
|
||||||
|
|
||||||
router.rawApi(
|
router.rawApi(
|
||||||
MethodPost,
|
MethodPost,
|
||||||
|
|
|
@ -4,9 +4,21 @@ import pkg/stew/byteutils
|
||||||
import pkg/questionable/results
|
import pkg/questionable/results
|
||||||
import ../sales
|
import ../sales
|
||||||
|
|
||||||
|
type
|
||||||
|
StorageRequestParams* = object
|
||||||
|
duration*: UInt256
|
||||||
|
maxPrice*: UInt256
|
||||||
|
|
||||||
proc fromJson*(_: type Availability, bytes: seq[byte]): ?!Availability =
|
proc fromJson*(_: type Availability, bytes: seq[byte]): ?!Availability =
|
||||||
let json = ?catch parseJson(string.fromBytes(bytes))
|
let json = ?catch parseJson(string.fromBytes(bytes))
|
||||||
let size = ?catch UInt256.fromHex(json["size"].getStr)
|
let size = ?catch UInt256.fromHex(json["size"].getStr)
|
||||||
let duration = ?catch UInt256.fromHex(json["duration"].getStr)
|
let duration = ?catch UInt256.fromHex(json["duration"].getStr)
|
||||||
let minPrice = ?catch UInt256.fromHex(json["minPrice"].getStr)
|
let minPrice = ?catch UInt256.fromHex(json["minPrice"].getStr)
|
||||||
success Availability.init(size, duration, minPrice)
|
success Availability.init(size, duration, minPrice)
|
||||||
|
|
||||||
|
proc fromJson*(_: type StorageRequestParams,
|
||||||
|
bytes: seq[byte]): ?! StorageRequestParams =
|
||||||
|
let json = ?catch parseJson(string.fromBytes(bytes))
|
||||||
|
let duration = ?catch UInt256.fromHex(json["duration"].getStr)
|
||||||
|
let maxPrice = ?catch UInt256.fromHex(json["maxPrice"].getStr)
|
||||||
|
success StorageRequestParams(duration: duration, maxPrice: maxPrice)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import std/httpclient
|
||||||
import std/json
|
import std/json
|
||||||
import pkg/asynctest
|
import pkg/asynctest
|
||||||
import pkg/chronos
|
import pkg/chronos
|
||||||
|
import pkg/stew/byteutils
|
||||||
|
|
||||||
suite "Integration tests":
|
suite "Integration tests":
|
||||||
|
|
||||||
|
@ -43,6 +44,11 @@ suite "Integration tests":
|
||||||
let info2 = client.get(baseurl2 & "/info").body
|
let info2 = client.get(baseurl2 & "/info").body
|
||||||
check info1 != info2
|
check info1 != info2
|
||||||
|
|
||||||
|
test "node accepts file uploads":
|
||||||
|
let url = baseurl1 & "/upload"
|
||||||
|
let response = client.post(url, "some file contents")
|
||||||
|
check response.status == "200 OK"
|
||||||
|
|
||||||
test "node handles new storage availability":
|
test "node handles new storage availability":
|
||||||
let url = baseurl1 & "/sales/availability"
|
let url = baseurl1 & "/sales/availability"
|
||||||
let json = %*{"size": "0x1", "duration": "0x2", "minPrice": "0x3"}
|
let json = %*{"size": "0x1", "duration": "0x2", "minPrice": "0x3"}
|
||||||
|
@ -55,3 +61,10 @@ suite "Integration tests":
|
||||||
let response = client.get(url)
|
let response = client.get(url)
|
||||||
check response.status == "200 OK"
|
check response.status == "200 OK"
|
||||||
check parseJson(response.body) == %*[availability]
|
check parseJson(response.body) == %*[availability]
|
||||||
|
|
||||||
|
test "node handles storage request":
|
||||||
|
let cid = client.post(baseurl1 & "/upload", "some file contents").body
|
||||||
|
let url = baseurl1 & "/storage/request/" & cid
|
||||||
|
let json = %*{"duration": "0x1", "maxPrice": "0x2"}
|
||||||
|
let response = client.post(url, $json)
|
||||||
|
check response.status == "200 OK"
|
||||||
|
|
Loading…
Reference in New Issue