Adds endpoint to expose quota information (#652)

This commit is contained in:
Ben Bierens 2023-12-14 11:57:16 +01:00 committed by GitHub
parent e62cb96bde
commit f1b1fe9152
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 7 deletions

View File

@ -266,7 +266,7 @@ proc new*(
erasure = Erasure.new(store, leoEncoderProvider, leoDecoderProvider) erasure = Erasure.new(store, leoEncoderProvider, leoDecoderProvider)
codexNode = CodexNodeRef.new(switch, store, engine, erasure, discovery) codexNode = CodexNodeRef.new(switch, store, engine, erasure, discovery)
restServer = RestServerRef.new( restServer = RestServerRef.new(
codexNode.initRestApi(config), codexNode.initRestApi(config, repoStore),
initTAddress(config.apiBindAddress , config.apiPort), initTAddress(config.apiBindAddress , config.apiPort),
bufferSize = (1024 * 64), bufferSize = (1024 * 64),
maxRequestBodySize = int.high) maxRequestBodySize = int.high)

View File

@ -34,7 +34,7 @@ import ../conf
import ../contracts import ../contracts
import ../manifest import ../manifest
import ../streams/asyncstreamwrapper import ../streams/asyncstreamwrapper
import ../stores/blockstore import ../stores
import ./coders import ./coders
import ./json import ./json
@ -106,7 +106,7 @@ proc retrieveCid(
if not stream.isNil: if not stream.isNil:
await stream.close() await stream.close()
proc initDataApi(node: CodexNodeRef, router: var RestRouter) = proc initDataApi(node: CodexNodeRef, repoStore: RepoStore, router: var RestRouter) =
router.rawApi( router.rawApi(
MethodPost, MethodPost,
"/api/codex/v1/data") do ( "/api/codex/v1/data") do (
@ -183,6 +183,17 @@ proc initDataApi(node: CodexNodeRef, router: var RestRouter) =
await node.retrieveCid(cid.get(), local = false, resp=resp) await node.retrieveCid(cid.get(), local = false, resp=resp)
router.api(
MethodGet,
"/api/codex/v1/space") do () -> RestApiResponse:
let json = % RestRepoStore(
totalBlocks: repoStore.totalBlocks,
quotaMaxBytes: repoStore.quotaMaxBytes,
quotaUsedBytes: repoStore.quotaUsedBytes,
quotaReservedBytes: repoStore.quotaReservedBytes
)
return RestApiResponse.response($json, contentType="application/json")
proc initSalesApi(node: CodexNodeRef, router: var RestRouter) = proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =
router.api( router.api(
MethodGet, MethodGet,
@ -456,10 +467,10 @@ proc initDebugApi(node: CodexNodeRef, conf: CodexConf, router: var RestRouter) =
trace "Excepting processing request", exc = exc.msg trace "Excepting processing request", exc = exc.msg
return RestApiResponse.error(Http500) return RestApiResponse.error(Http500)
proc initRestApi*(node: CodexNodeRef, conf: CodexConf): RestRouter = proc initRestApi*(node: CodexNodeRef, conf: CodexConf, repoStore: RepoStore): RestRouter =
var router = RestRouter.init(validate) var router = RestRouter.init(validate)
initDataApi(node, router) initDataApi(node, repoStore, router)
initSalesApi(node, router) initSalesApi(node, router)
initPurchasingApi(node, router) initPurchasingApi(node, router)
initDebugApi(node, conf, router) initDebugApi(node, conf, router)

View File

@ -60,6 +60,12 @@ type
RestNodeId* = object RestNodeId* = object
id*: NodeId id*: NodeId
RestRepoStore* = object
totalBlocks* {.serialize.}: uint
quotaMaxBytes* {.serialize.}: uint
quotaUsedBytes* {.serialize.}: uint
quotaReservedBytes* {.serialize.}: uint
proc init*(_: type RestContent, cid: Cid, manifest: Manifest): RestContent = proc init*(_: type RestContent, cid: Cid, manifest: Manifest): RestContent =
RestContent( RestContent(
cid: cid, cid: cid,

View File

@ -245,6 +245,22 @@ components:
type: boolean type: boolean
description: "Indicates if content is protected by erasure-coding" description: "Indicates if content is protected by erasure-coding"
Space:
type: object
properties:
totalBlocks:
type: number
description: "Number of blocks stored by the node"
quotaMaxBytes:
type: number
description: "Maximum storage space used by the node"
quotaUsedBytes:
type: number
description: "Amount of storage space currently in use"
quotaReservedBytes:
type: number
description: "Amount of storage space reserved"
servers: servers:
- url: "http://localhost:8080/api/codex/v1" - url: "http://localhost:8080/api/codex/v1"
@ -371,8 +387,7 @@ paths:
required: true required: true
schema: schema:
$ref: "#/components/schemas/Cid" $ref: "#/components/schemas/Cid"
description: File to be downloaded. description: "File to be downloaded."
responses: responses:
"200": "200":
description: Retrieved content specified by CID description: Retrieved content specified by CID
@ -388,6 +403,22 @@ paths:
"500": "500":
description: Well it was bad-bad description: Well it was bad-bad
"/space":
get:
summary: "Gets a summary of the storage space allocation of the node."
tags: [ Data ]
operationId: space
responses:
"200":
description: "Summary of storage allocation"
content:
application/json:
schema:
$ref: "#/components/schemas/Space"
"500":
description: "It's not working as planned"
"/sales/slots": "/sales/slots":
get: get:
summary: "Returns active slots" summary: "Returns active slots"

View File

@ -56,6 +56,16 @@ proc list*(client: CodexClient): ?!seq[RestContent] =
let json = ? parseJson(response.body).catch let json = ? parseJson(response.body).catch
seq[RestContent].fromJson(json) seq[RestContent].fromJson(json)
proc space*(client: CodexClient): ?!RestRepoStore =
let url = client.baseurl & "/space"
let response = client.http.get(url)
if response.status != "200 OK":
return failure(response.status)
let json = ? parseJson(response.body).catch
RestRepoStore.fromJson(json)
proc requestStorageRaw*( proc requestStorageRaw*(
client: CodexClient, client: CodexClient,
cid: Cid, cid: Cid,

View File

@ -44,6 +44,16 @@ twonodessuite "Integration tests", debug1 = false, debug2 = false:
let cid2 = client1.upload("some other contents").get let cid2 = client1.upload("some other contents").get
check cid1 != cid2 check cid1 != cid2
test "node shows used and available space":
discard client1.upload("some file contents").get
discard client1.postAvailability(size=12.u256, duration=2.u256, minPrice=3.u256, maxCollateral=4.u256).get
let space = client1.space().tryGet()
check:
space.totalBlocks == 2.uint
space.quotaMaxBytes == 8589934592.uint
space.quotaUsedBytes == 65518.uint
space.quotaReservedBytes == 12.uint
test "node allows local file downloads": test "node allows local file downloads":
let content1 = "some file contents" let content1 = "some file contents"
let content2 = "some other contents" let content2 = "some other contents"