Add metrics (#478)
* Adds metrics to block exchange. * Adds metrics to purchasing * Adds metrics to upload and download API * Adds metrics to the repo store * Fixes exception in repostore start. * Merge managed to mess up indentation.
This commit is contained in:
parent
8bebc90428
commit
14c5270e83
|
@ -15,6 +15,7 @@ import std/algorithm
|
||||||
import pkg/chronos
|
import pkg/chronos
|
||||||
import pkg/chronicles
|
import pkg/chronicles
|
||||||
import pkg/libp2p
|
import pkg/libp2p
|
||||||
|
import pkg/metrics
|
||||||
import pkg/stint
|
import pkg/stint
|
||||||
|
|
||||||
import ../../stores/blockstore
|
import ../../stores/blockstore
|
||||||
|
@ -36,6 +37,13 @@ export peers, pendingblocks, payments, discovery
|
||||||
logScope:
|
logScope:
|
||||||
topics = "codex blockexcengine"
|
topics = "codex blockexcengine"
|
||||||
|
|
||||||
|
declareCounter(codexBlockExchangeWantHaveListsSent, "codex blockexchange wantHave lists sent")
|
||||||
|
declareCounter(codexBlockExchangeWantHaveListsReceived, "codex blockexchange wantHave lists received")
|
||||||
|
declareCounter(codexBlockExchangeWantBlockListsSent, "codex blockexchange wantBlock lists sent")
|
||||||
|
declareCounter(codexBlockExchangeWantBlockListsReceived, "codex blockexchange wantBlock lists received")
|
||||||
|
declareCounter(codexBlockExchangeBlocksSent, "codex blockexchange blocks sent")
|
||||||
|
declareCounter(codexBlockExchangeBlocksReceived, "codex blockexchange blocks received")
|
||||||
|
|
||||||
const
|
const
|
||||||
DefaultMaxPeersPerRequest* = 10
|
DefaultMaxPeersPerRequest* = 10
|
||||||
DefaultTaskQueueSize = 100
|
DefaultTaskQueueSize = 100
|
||||||
|
@ -190,6 +198,8 @@ proc requestBlock*(
|
||||||
|
|
||||||
await b.sendWantBlock(cid, blockPeer)
|
await b.sendWantBlock(cid, blockPeer)
|
||||||
|
|
||||||
|
codexBlockExchangeWantBlockListsSent.inc()
|
||||||
|
|
||||||
if (peers.len - 1) == 0:
|
if (peers.len - 1) == 0:
|
||||||
trace "No peers to send want list to", cid
|
trace "No peers to send want list to", cid
|
||||||
b.discovery.queueFindBlocksReq(@[cid])
|
b.discovery.queueFindBlocksReq(@[cid])
|
||||||
|
@ -197,6 +207,8 @@ proc requestBlock*(
|
||||||
|
|
||||||
await b.sendWantHave(cid, blockPeer, toSeq(b.peers))
|
await b.sendWantHave(cid, blockPeer, toSeq(b.peers))
|
||||||
|
|
||||||
|
codexBlockExchangeWantHaveListsSent.inc()
|
||||||
|
|
||||||
return await blk
|
return await blk
|
||||||
|
|
||||||
proc blockPresenceHandler*(
|
proc blockPresenceHandler*(
|
||||||
|
@ -297,6 +309,8 @@ proc blocksHandler*(
|
||||||
trace "Unable to store block", cid = blk.cid
|
trace "Unable to store block", cid = blk.cid
|
||||||
|
|
||||||
await b.resolveBlocks(blocks)
|
await b.resolveBlocks(blocks)
|
||||||
|
codexBlockExchangeBlocksReceived.inc(blocks.len.int64)
|
||||||
|
|
||||||
let
|
let
|
||||||
peerCtx = b.peers.get(peer)
|
peerCtx = b.peers.get(peer)
|
||||||
|
|
||||||
|
@ -336,6 +350,9 @@ proc wantListHandler*(
|
||||||
b.pricing.get(Pricing(price: 0.u256))
|
b.pricing.get(Pricing(price: 0.u256))
|
||||||
.price.toBytesBE)
|
.price.toBytesBE)
|
||||||
|
|
||||||
|
if e.wantType == WantType.WantHave:
|
||||||
|
codexBlockExchangeWantHaveListsReceived.inc()
|
||||||
|
|
||||||
if not have and e.sendDontHave:
|
if not have and e.sendDontHave:
|
||||||
trace "Adding dont have entry to presence response", cid = e.cid
|
trace "Adding dont have entry to presence response", cid = e.cid
|
||||||
presence.add(
|
presence.add(
|
||||||
|
@ -353,6 +370,7 @@ proc wantListHandler*(
|
||||||
elif e.wantType == WantType.WantBlock:
|
elif e.wantType == WantType.WantBlock:
|
||||||
trace "Added entry to peer's want blocks list", cid = e.cid
|
trace "Added entry to peer's want blocks list", cid = e.cid
|
||||||
peerCtx.peerWants.add(e)
|
peerCtx.peerWants.add(e)
|
||||||
|
codexBlockExchangeWantBlockListsReceived.inc()
|
||||||
else:
|
else:
|
||||||
# peer doesn't want this block anymore
|
# peer doesn't want this block anymore
|
||||||
if e.cancel:
|
if e.cancel:
|
||||||
|
@ -467,6 +485,9 @@ proc taskHandler*(b: BlockExcEngine, task: BlockExcPeerCtx) {.gcsafe, async.} =
|
||||||
task.id,
|
task.id,
|
||||||
blocks)
|
blocks)
|
||||||
|
|
||||||
|
codexBlockExchangeBlocksSent.inc(blocks.len.int64)
|
||||||
|
|
||||||
|
trace "About to remove entries from peerWants", blocks = blocks.len, items = task.peerWants.len
|
||||||
# Remove successfully sent blocks
|
# Remove successfully sent blocks
|
||||||
task.peerWants.keepIf(
|
task.peerWants.keepIf(
|
||||||
proc(e: Entry): bool =
|
proc(e: Entry): bool =
|
||||||
|
|
|
@ -16,12 +16,15 @@ push: {.upraises: [].}
|
||||||
import pkg/chronicles
|
import pkg/chronicles
|
||||||
import pkg/chronos
|
import pkg/chronos
|
||||||
import pkg/libp2p
|
import pkg/libp2p
|
||||||
|
import pkg/metrics
|
||||||
|
|
||||||
import ../../blocktype
|
import ../../blocktype
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "codex pendingblocks"
|
topics = "codex pendingblocks"
|
||||||
|
|
||||||
|
declareGauge(codexBlockExchangePendingBlockRequests, "codex blockexchange pending block requests")
|
||||||
|
|
||||||
const
|
const
|
||||||
DefaultBlockTimeout* = 10.minutes
|
DefaultBlockTimeout* = 10.minutes
|
||||||
|
|
||||||
|
@ -33,6 +36,9 @@ type
|
||||||
PendingBlocksManager* = ref object of RootObj
|
PendingBlocksManager* = ref object of RootObj
|
||||||
blocks*: Table[Cid, BlockReq] # pending Block requests
|
blocks*: Table[Cid, BlockReq] # pending Block requests
|
||||||
|
|
||||||
|
proc updatePendingBlockGauge(p: PendingBlocksManager) =
|
||||||
|
codexBlockExchangePendingBlockRequests.set(p.blocks.len.int64)
|
||||||
|
|
||||||
proc getWantHandle*(
|
proc getWantHandle*(
|
||||||
p: PendingBlocksManager,
|
p: PendingBlocksManager,
|
||||||
cid: Cid,
|
cid: Cid,
|
||||||
|
@ -50,6 +56,7 @@ proc getWantHandle*(
|
||||||
|
|
||||||
trace "Adding pending future for block", cid, inFlight = p.blocks[cid].inFlight
|
trace "Adding pending future for block", cid, inFlight = p.blocks[cid].inFlight
|
||||||
|
|
||||||
|
p.updatePendingBlockGauge()
|
||||||
return await p.blocks[cid].handle.wait(timeout)
|
return await p.blocks[cid].handle.wait(timeout)
|
||||||
except CancelledError as exc:
|
except CancelledError as exc:
|
||||||
trace "Blocks cancelled", exc = exc.msg, cid
|
trace "Blocks cancelled", exc = exc.msg, cid
|
||||||
|
@ -60,6 +67,7 @@ proc getWantHandle*(
|
||||||
raise exc
|
raise exc
|
||||||
finally:
|
finally:
|
||||||
p.blocks.del(cid)
|
p.blocks.del(cid)
|
||||||
|
p.updatePendingBlockGauge()
|
||||||
|
|
||||||
proc resolve*(p: PendingBlocksManager,
|
proc resolve*(p: PendingBlocksManager,
|
||||||
blocks: seq[Block]) =
|
blocks: seq[Block]) =
|
||||||
|
|
|
@ -11,6 +11,7 @@ const
|
||||||
# Namespaces
|
# Namespaces
|
||||||
CodexMetaNamespace* = "meta" # meta info stored here
|
CodexMetaNamespace* = "meta" # meta info stored here
|
||||||
CodexRepoNamespace* = "repo" # repository namespace, blocks and manifests are subkeys
|
CodexRepoNamespace* = "repo" # repository namespace, blocks and manifests are subkeys
|
||||||
|
CodexBlockTotalNamespace* = CodexMetaNamespace & "/total" # number of blocks in the repo
|
||||||
CodexBlocksNamespace* = CodexRepoNamespace & "/blocks" # blocks namespace
|
CodexBlocksNamespace* = CodexRepoNamespace & "/blocks" # blocks namespace
|
||||||
CodexManifestNamespace* = CodexRepoNamespace & "/manifests" # manifest namespace
|
CodexManifestNamespace* = CodexRepoNamespace & "/manifests" # manifest namespace
|
||||||
CodexBlocksTtlNamespace* = # Cid TTL
|
CodexBlocksTtlNamespace* = # Cid TTL
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
|
import pkg/metrics
|
||||||
import ../statemachine
|
import ../statemachine
|
||||||
import ./errorhandling
|
import ./errorhandling
|
||||||
import ./error
|
import ./error
|
||||||
|
|
||||||
|
declareCounter(codexPurchasesCancelled, "codex purchases cancelled")
|
||||||
|
|
||||||
type PurchaseCancelled* = ref object of ErrorHandlingState
|
type PurchaseCancelled* = ref object of ErrorHandlingState
|
||||||
|
|
||||||
method `$`*(state: PurchaseCancelled): string =
|
method `$`*(state: PurchaseCancelled): string =
|
||||||
"cancelled"
|
"cancelled"
|
||||||
|
|
||||||
method run*(state: PurchaseCancelled, machine: Machine): Future[?State] {.async.} =
|
method run*(state: PurchaseCancelled, machine: Machine): Future[?State] {.async.} =
|
||||||
|
codexPurchasesCancelled.inc()
|
||||||
let purchase = Purchase(machine)
|
let purchase = Purchase(machine)
|
||||||
await purchase.market.withdrawFunds(purchase.requestId)
|
await purchase.market.withdrawFunds(purchase.requestId)
|
||||||
let error = newException(Timeout, "Purchase cancelled due to timeout")
|
let error = newException(Timeout, "Purchase cancelled due to timeout")
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
import pkg/metrics
|
||||||
import ../statemachine
|
import ../statemachine
|
||||||
|
|
||||||
|
declareCounter(codexPurchasesError, "codex purchases error")
|
||||||
|
|
||||||
type PurchaseErrored* = ref object of PurchaseState
|
type PurchaseErrored* = ref object of PurchaseState
|
||||||
error*: ref CatchableError
|
error*: ref CatchableError
|
||||||
|
|
||||||
|
@ -7,5 +10,6 @@ method `$`*(state: PurchaseErrored): string =
|
||||||
"errored"
|
"errored"
|
||||||
|
|
||||||
method run*(state: PurchaseErrored, machine: Machine): Future[?State] {.async.} =
|
method run*(state: PurchaseErrored, machine: Machine): Future[?State] {.async.} =
|
||||||
|
codexPurchasesError.inc()
|
||||||
let purchase = Purchase(machine)
|
let purchase = Purchase(machine)
|
||||||
purchase.future.fail(state.error)
|
purchase.future.fail(state.error)
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
import pkg/metrics
|
||||||
import ../statemachine
|
import ../statemachine
|
||||||
import ./error
|
import ./error
|
||||||
|
|
||||||
|
declareCounter(codexPurchasesFailed, "codex purchases failed")
|
||||||
|
|
||||||
type
|
type
|
||||||
PurchaseFailed* = ref object of PurchaseState
|
PurchaseFailed* = ref object of PurchaseState
|
||||||
|
|
||||||
|
@ -8,5 +11,6 @@ method `$`*(state: PurchaseFailed): string =
|
||||||
"failed"
|
"failed"
|
||||||
|
|
||||||
method run*(state: PurchaseFailed, machine: Machine): Future[?State] {.async.} =
|
method run*(state: PurchaseFailed, machine: Machine): Future[?State] {.async.} =
|
||||||
|
codexPurchasesFailed.inc()
|
||||||
let error = newException(PurchaseError, "Purchase failed")
|
let error = newException(PurchaseError, "Purchase failed")
|
||||||
return some State(PurchaseErrored(error: error))
|
return some State(PurchaseErrored(error: error))
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
|
import pkg/metrics
|
||||||
import ../statemachine
|
import ../statemachine
|
||||||
|
|
||||||
|
declareCounter(codexPurchasesFinished, "codex purchases finished")
|
||||||
|
|
||||||
type PurchaseFinished* = ref object of PurchaseState
|
type PurchaseFinished* = ref object of PurchaseState
|
||||||
|
|
||||||
method `$`*(state: PurchaseFinished): string =
|
method `$`*(state: PurchaseFinished): string =
|
||||||
"finished"
|
"finished"
|
||||||
|
|
||||||
method run*(state: PurchaseFinished, machine: Machine): Future[?State] {.async.} =
|
method run*(state: PurchaseFinished, machine: Machine): Future[?State] {.async.} =
|
||||||
|
codexPurchasesFinished.inc()
|
||||||
let purchase = Purchase(machine)
|
let purchase = Purchase(machine)
|
||||||
purchase.future.complete()
|
purchase.future.complete()
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
|
import pkg/metrics
|
||||||
import ../statemachine
|
import ../statemachine
|
||||||
import ./errorhandling
|
import ./errorhandling
|
||||||
import ./submitted
|
import ./submitted
|
||||||
|
|
||||||
|
declareCounter(codexPurchasesPending, "codex purchases pending")
|
||||||
|
|
||||||
type PurchasePending* = ref object of ErrorHandlingState
|
type PurchasePending* = ref object of ErrorHandlingState
|
||||||
|
|
||||||
method `$`*(state: PurchasePending): string =
|
method `$`*(state: PurchasePending): string =
|
||||||
"pending"
|
"pending"
|
||||||
|
|
||||||
method run*(state: PurchasePending, machine: Machine): Future[?State] {.async.} =
|
method run*(state: PurchasePending, machine: Machine): Future[?State] {.async.} =
|
||||||
|
codexPurchasesPending.inc()
|
||||||
let purchase = Purchase(machine)
|
let purchase = Purchase(machine)
|
||||||
let request = !purchase.request
|
let request = !purchase.request
|
||||||
await purchase.market.requestStorage(request)
|
await purchase.market.requestStorage(request)
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
|
import pkg/metrics
|
||||||
import ../statemachine
|
import ../statemachine
|
||||||
import ./errorhandling
|
import ./errorhandling
|
||||||
import ./finished
|
import ./finished
|
||||||
import ./failed
|
import ./failed
|
||||||
|
|
||||||
|
declareCounter(codexPurchasesStarted, "codex purchases started")
|
||||||
|
|
||||||
type PurchaseStarted* = ref object of ErrorHandlingState
|
type PurchaseStarted* = ref object of ErrorHandlingState
|
||||||
|
|
||||||
method `$`*(state: PurchaseStarted): string =
|
method `$`*(state: PurchaseStarted): string =
|
||||||
"started"
|
"started"
|
||||||
|
|
||||||
method run*(state: PurchaseStarted, machine: Machine): Future[?State] {.async.} =
|
method run*(state: PurchaseStarted, machine: Machine): Future[?State] {.async.} =
|
||||||
|
codexPurchasesStarted.inc()
|
||||||
let purchase = Purchase(machine)
|
let purchase = Purchase(machine)
|
||||||
|
|
||||||
let clock = purchase.clock
|
let clock = purchase.clock
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
|
import pkg/metrics
|
||||||
import ../statemachine
|
import ../statemachine
|
||||||
import ./errorhandling
|
import ./errorhandling
|
||||||
import ./started
|
import ./started
|
||||||
import ./cancelled
|
import ./cancelled
|
||||||
|
|
||||||
|
declareCounter(codexPurchasesSubmitted, "codex purchases submitted")
|
||||||
|
|
||||||
type PurchaseSubmitted* = ref object of ErrorHandlingState
|
type PurchaseSubmitted* = ref object of ErrorHandlingState
|
||||||
|
|
||||||
method `$`*(state: PurchaseSubmitted): string =
|
method `$`*(state: PurchaseSubmitted): string =
|
||||||
"submitted"
|
"submitted"
|
||||||
|
|
||||||
method run*(state: PurchaseSubmitted, machine: Machine): Future[?State] {.async.} =
|
method run*(state: PurchaseSubmitted, machine: Machine): Future[?State] {.async.} =
|
||||||
|
codexPurchasesSubmitted.inc()
|
||||||
let purchase = Purchase(machine)
|
let purchase = Purchase(machine)
|
||||||
let request = !purchase.request
|
let request = !purchase.request
|
||||||
let market = purchase.market
|
let market = purchase.market
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import pkg/metrics
|
||||||
import ../statemachine
|
import ../statemachine
|
||||||
import ./errorhandling
|
import ./errorhandling
|
||||||
import ./submitted
|
import ./submitted
|
||||||
|
@ -6,12 +7,15 @@ import ./cancelled
|
||||||
import ./finished
|
import ./finished
|
||||||
import ./failed
|
import ./failed
|
||||||
|
|
||||||
|
declareCounter(codexPurchasesUnknown, "codex purchases unknown")
|
||||||
|
|
||||||
type PurchaseUnknown* = ref object of ErrorHandlingState
|
type PurchaseUnknown* = ref object of ErrorHandlingState
|
||||||
|
|
||||||
method `$`*(state: PurchaseUnknown): string =
|
method `$`*(state: PurchaseUnknown): string =
|
||||||
"unknown"
|
"unknown"
|
||||||
|
|
||||||
method run*(state: PurchaseUnknown, machine: Machine): Future[?State] {.async.} =
|
method run*(state: PurchaseUnknown, machine: Machine): Future[?State] {.async.} =
|
||||||
|
codexPurchasesUnknown.inc()
|
||||||
let purchase = Purchase(machine)
|
let purchase = Purchase(machine)
|
||||||
if (request =? await purchase.market.getRequest(purchase.requestId)) and
|
if (request =? await purchase.market.getRequest(purchase.requestId)) and
|
||||||
(requestState =? await purchase.market.requestState(purchase.requestId)):
|
(requestState =? await purchase.market.requestState(purchase.requestId)):
|
||||||
|
|
|
@ -20,6 +20,7 @@ import pkg/chronicles
|
||||||
import pkg/chronos
|
import pkg/chronos
|
||||||
import pkg/presto
|
import pkg/presto
|
||||||
import pkg/libp2p
|
import pkg/libp2p
|
||||||
|
import pkg/metrics
|
||||||
import pkg/stew/base10
|
import pkg/stew/base10
|
||||||
import pkg/stew/byteutils
|
import pkg/stew/byteutils
|
||||||
import pkg/confutils
|
import pkg/confutils
|
||||||
|
@ -42,6 +43,9 @@ import ./json
|
||||||
logScope:
|
logScope:
|
||||||
topics = "codex restapi"
|
topics = "codex restapi"
|
||||||
|
|
||||||
|
declareCounter(codexApiUploads, "codex API uploads")
|
||||||
|
declareCounter(codexApiDownloads, "codex API downloads")
|
||||||
|
|
||||||
proc validate(
|
proc validate(
|
||||||
pattern: string,
|
pattern: string,
|
||||||
value: string): int
|
value: string): int
|
||||||
|
@ -164,6 +168,7 @@ proc initRestApi*(node: CodexNodeRef, conf: CodexConf): RestRouter =
|
||||||
trace "Sending chunk", size = buff.len
|
trace "Sending chunk", size = buff.len
|
||||||
await resp.sendChunk(addr buff[0], buff.len)
|
await resp.sendChunk(addr buff[0], buff.len)
|
||||||
await resp.finish()
|
await resp.finish()
|
||||||
|
codexApiDownloads.inc()
|
||||||
except CatchableError as exc:
|
except CatchableError as exc:
|
||||||
trace "Excepting streaming blocks", exc = exc.msg
|
trace "Excepting streaming blocks", exc = exc.msg
|
||||||
return RestApiResponse.error(Http500)
|
return RestApiResponse.error(Http500)
|
||||||
|
@ -238,6 +243,7 @@ proc initRestApi*(node: CodexNodeRef, conf: CodexConf): RestRouter =
|
||||||
trace "Error uploading file", exc = error.msg
|
trace "Error uploading file", exc = error.msg
|
||||||
return RestApiResponse.error(Http500, error.msg)
|
return RestApiResponse.error(Http500, error.msg)
|
||||||
|
|
||||||
|
codexApiUploads.inc()
|
||||||
trace "Uploaded file", cid
|
trace "Uploaded file", cid
|
||||||
return RestApiResponse.response($cid)
|
return RestApiResponse.response($cid)
|
||||||
except CancelledError:
|
except CancelledError:
|
||||||
|
|
|
@ -20,6 +20,7 @@ const
|
||||||
CodexMetaKey* = Key.init(CodexMetaNamespace).tryGet
|
CodexMetaKey* = Key.init(CodexMetaNamespace).tryGet
|
||||||
CodexRepoKey* = Key.init(CodexRepoNamespace).tryGet
|
CodexRepoKey* = Key.init(CodexRepoNamespace).tryGet
|
||||||
CodexBlocksKey* = Key.init(CodexBlocksNamespace).tryGet
|
CodexBlocksKey* = Key.init(CodexBlocksNamespace).tryGet
|
||||||
|
CodexTotalBlocksKey* = Key.init(CodexBlockTotalNamespace).tryGet
|
||||||
CodexManifestKey* = Key.init(CodexManifestNamespace).tryGet
|
CodexManifestKey* = Key.init(CodexManifestNamespace).tryGet
|
||||||
BlocksTtlKey* = Key.init(CodexBlocksTtlNamespace).tryGet
|
BlocksTtlKey* = Key.init(CodexBlocksTtlNamespace).tryGet
|
||||||
QuotaKey* = Key.init(CodexQuotaNamespace).tryGet
|
QuotaKey* = Key.init(CodexQuotaNamespace).tryGet
|
||||||
|
|
|
@ -14,6 +14,7 @@ push: {.upraises: [].}
|
||||||
import pkg/chronos
|
import pkg/chronos
|
||||||
import pkg/chronicles
|
import pkg/chronicles
|
||||||
import pkg/libp2p
|
import pkg/libp2p
|
||||||
|
import pkg/metrics
|
||||||
import pkg/questionable
|
import pkg/questionable
|
||||||
import pkg/questionable/results
|
import pkg/questionable/results
|
||||||
import pkg/datastore
|
import pkg/datastore
|
||||||
|
@ -30,6 +31,10 @@ export blocktype, libp2p
|
||||||
logScope:
|
logScope:
|
||||||
topics = "codex repostore"
|
topics = "codex repostore"
|
||||||
|
|
||||||
|
declareGauge(codexRepostoreBlocks, "codex repostore blocks")
|
||||||
|
declareGauge(codexRepostoreBytesUsed, "codex repostore bytes used")
|
||||||
|
declareGauge(codexRepostoreBytesReserved, "codex repostore bytes reserved")
|
||||||
|
|
||||||
const
|
const
|
||||||
DefaultBlockTtl* = 24.hours
|
DefaultBlockTtl* = 24.hours
|
||||||
DefaultQuotaBytes* = 1'u shl 33'u # ~8GB
|
DefaultQuotaBytes* = 1'u shl 33'u # ~8GB
|
||||||
|
@ -43,6 +48,7 @@ type
|
||||||
repoDs*: Datastore
|
repoDs*: Datastore
|
||||||
metaDs*: Datastore
|
metaDs*: Datastore
|
||||||
clock: Clock
|
clock: Clock
|
||||||
|
totalBlocks*: uint # number of blocks in the store
|
||||||
quotaMaxBytes*: uint # maximum available bytes
|
quotaMaxBytes*: uint # maximum available bytes
|
||||||
quotaUsedBytes*: uint # bytes used by the repo
|
quotaUsedBytes*: uint # bytes used by the repo
|
||||||
quotaReservedBytes*: uint # bytes reserved by the repo
|
quotaReservedBytes*: uint # bytes reserved by the repo
|
||||||
|
@ -61,6 +67,11 @@ iterator items*(q: BlockExpirationIter): Future[?BlockExpiration] =
|
||||||
while not q.finished:
|
while not q.finished:
|
||||||
yield q.next()
|
yield q.next()
|
||||||
|
|
||||||
|
proc updateMetrics(self: RepoStore) =
|
||||||
|
codexRepostoreBlocks.set(self.totalBlocks.int64)
|
||||||
|
codexRepostoreBytesUsed.set(self.quotaUsedBytes.int64)
|
||||||
|
codexRepostoreBytesReserved.set(self.quotaReservedBytes.int64)
|
||||||
|
|
||||||
func totalUsed*(self: RepoStore): uint =
|
func totalUsed*(self: RepoStore): uint =
|
||||||
(self.quotaUsedBytes + self.quotaReservedBytes)
|
(self.quotaUsedBytes + self.quotaReservedBytes)
|
||||||
|
|
||||||
|
@ -105,6 +116,14 @@ proc getBlockExpirationEntry(
|
||||||
let value = self.getBlockExpirationTimestamp(ttl).toBytes
|
let value = self.getBlockExpirationTimestamp(ttl).toBytes
|
||||||
return success((key, value))
|
return success((key, value))
|
||||||
|
|
||||||
|
proc persistTotalBlocksCount(self: RepoStore): Future[?!void] {.async.} =
|
||||||
|
if err =? (await self.metaDs.put(
|
||||||
|
CodexTotalBlocksKey,
|
||||||
|
@(self.totalBlocks.uint64.toBytesBE))).errorOption:
|
||||||
|
trace "Error total blocks key!", err = err.msg
|
||||||
|
return failure(err)
|
||||||
|
return success()
|
||||||
|
|
||||||
method putBlock*(
|
method putBlock*(
|
||||||
self: RepoStore,
|
self: RepoStore,
|
||||||
blk: Block,
|
blk: Block,
|
||||||
|
@ -156,6 +175,12 @@ method putBlock*(
|
||||||
return failure(err)
|
return failure(err)
|
||||||
|
|
||||||
self.quotaUsedBytes = used
|
self.quotaUsedBytes = used
|
||||||
|
inc self.totalBlocks
|
||||||
|
if isErr (await self.persistTotalBlocksCount()):
|
||||||
|
trace "Unable to update block total metadata"
|
||||||
|
return failure("Unable to update block total metadata")
|
||||||
|
|
||||||
|
self.updateMetrics()
|
||||||
return success()
|
return success()
|
||||||
|
|
||||||
proc updateQuotaBytesUsed(self: RepoStore, blk: Block): Future[?!void] {.async.} =
|
proc updateQuotaBytesUsed(self: RepoStore, blk: Block): Future[?!void] {.async.} =
|
||||||
|
@ -166,6 +191,7 @@ proc updateQuotaBytesUsed(self: RepoStore, blk: Block): Future[?!void] {.async.}
|
||||||
trace "Error updating quota key!", err = err.msg
|
trace "Error updating quota key!", err = err.msg
|
||||||
return failure(err)
|
return failure(err)
|
||||||
self.quotaUsedBytes = used
|
self.quotaUsedBytes = used
|
||||||
|
self.updateMetrics()
|
||||||
return success()
|
return success()
|
||||||
|
|
||||||
proc removeBlockExpirationEntry(self: RepoStore, cid: Cid): Future[?!void] {.async.} =
|
proc removeBlockExpirationEntry(self: RepoStore, cid: Cid): Future[?!void] {.async.} =
|
||||||
|
@ -195,6 +221,12 @@ method delBlock*(self: RepoStore, cid: Cid): Future[?!void] {.async.} =
|
||||||
|
|
||||||
trace "Deleted block", cid, totalUsed = self.totalUsed
|
trace "Deleted block", cid, totalUsed = self.totalUsed
|
||||||
|
|
||||||
|
dec self.totalBlocks
|
||||||
|
if isErr (await self.persistTotalBlocksCount()):
|
||||||
|
trace "Unable to update block total metadata"
|
||||||
|
return failure("Unable to update block total metadata")
|
||||||
|
|
||||||
|
self.updateMetrics()
|
||||||
return success()
|
return success()
|
||||||
|
|
||||||
method hasBlock*(self: RepoStore, cid: Cid): Future[?!bool] {.async.} =
|
method hasBlock*(self: RepoStore, cid: Cid): Future[?!bool] {.async.} =
|
||||||
|
@ -346,6 +378,7 @@ proc release*(self: RepoStore, bytes: uint): Future[?!void] {.async.} =
|
||||||
return failure(err)
|
return failure(err)
|
||||||
|
|
||||||
trace "Released bytes", bytes
|
trace "Released bytes", bytes
|
||||||
|
self.updateMetrics()
|
||||||
return success()
|
return success()
|
||||||
|
|
||||||
proc start*(self: RepoStore): Future[void] {.async.} =
|
proc start*(self: RepoStore): Future[void] {.async.} =
|
||||||
|
@ -358,6 +391,14 @@ proc start*(self: RepoStore): Future[void] {.async.} =
|
||||||
|
|
||||||
trace "Starting repo"
|
trace "Starting repo"
|
||||||
|
|
||||||
|
without total =? await self.metaDs.get(CodexTotalBlocksKey), err:
|
||||||
|
if not (err of DatastoreKeyNotFound):
|
||||||
|
error "Unable to read total number of blocks from metadata store", err = err.msg, key = $CodexTotalBlocksKey
|
||||||
|
|
||||||
|
if total.len > 0:
|
||||||
|
self.totalBlocks = uint64.fromBytesBE(total).uint
|
||||||
|
trace "Number of blocks in store at start", total = self.totalBlocks
|
||||||
|
|
||||||
## load current persist and cache bytes from meta ds
|
## load current persist and cache bytes from meta ds
|
||||||
without quotaUsedBytes =? await self.metaDs.get(QuotaUsedKey), err:
|
without quotaUsedBytes =? await self.metaDs.get(QuotaUsedKey), err:
|
||||||
if not (err of DatastoreKeyNotFound):
|
if not (err of DatastoreKeyNotFound):
|
||||||
|
@ -386,6 +427,7 @@ proc start*(self: RepoStore): Future[void] {.async.} =
|
||||||
|
|
||||||
notice "Current bytes used for persist quota", bytes = self.quotaReservedBytes
|
notice "Current bytes used for persist quota", bytes = self.quotaReservedBytes
|
||||||
|
|
||||||
|
self.updateMetrics()
|
||||||
self.started = true
|
self.started = true
|
||||||
|
|
||||||
proc stop*(self: RepoStore): Future[void] {.async.} =
|
proc stop*(self: RepoStore): Future[void] {.async.} =
|
||||||
|
|
Loading…
Reference in New Issue