[stores] update getBlock return type
change return type for `method getBlock` from `Future[?!(?Block)]` to `Future[?!Block]` use `type BlockNotFoundError = object of CodexError` to differentiate between "block not found in the store" and other errors also make some logic and error handling/messages more consistent across BlockStore implementations closes #177 closes #182 closes #210 alternative to #205, #209
This commit is contained in:
parent
e0e2d7b583
commit
3d823dcbc6
|
@ -379,8 +379,8 @@ proc taskHandler*(b: BlockExcEngine, task: BlockExcPeerCtx) {.gcsafe, async.} =
|
||||||
|
|
||||||
# Extract succesfully received blocks
|
# Extract succesfully received blocks
|
||||||
let blocks = blockFuts
|
let blocks = blockFuts
|
||||||
.filterIt(it.completed and it.read.isOk and it.read.get.isSome)
|
.filterIt(it.completed and it.read.isOk)
|
||||||
.mapIt(it.read.get.get)
|
.mapIt(it.read.get)
|
||||||
|
|
||||||
if blocks.len > 0:
|
if blocks.len > 0:
|
||||||
trace "Sending blocks to peer", peer = task.id, blocks = blocks.len
|
trace "Sending blocks to peer", peer = task.id, blocks = blocks.len
|
||||||
|
|
|
@ -29,6 +29,8 @@ type
|
||||||
cid*: Cid
|
cid*: Cid
|
||||||
data*: seq[byte]
|
data*: seq[byte]
|
||||||
|
|
||||||
|
BlockNotFoundError* = object of CodexError
|
||||||
|
|
||||||
template EmptyCid*: untyped =
|
template EmptyCid*: untyped =
|
||||||
var
|
var
|
||||||
emptyCid {.global, threadvar.}:
|
emptyCid {.global, threadvar.}:
|
||||||
|
|
|
@ -114,13 +114,9 @@ proc encode*(
|
||||||
for j in 0..<blocks:
|
for j in 0..<blocks:
|
||||||
let idx = blockIdx[j]
|
let idx = blockIdx[j]
|
||||||
if idx < manifest.len:
|
if idx < manifest.len:
|
||||||
without blkOrNone =? await dataBlocks[j], error:
|
without blk =? (await dataBlocks[j]), error:
|
||||||
trace "Unable to retrieve block", error = error.msg
|
trace "Unable to retrieve block", error = error.msg
|
||||||
return error.failure
|
return failure error
|
||||||
|
|
||||||
without blk =? blkOrNone:
|
|
||||||
trace "Block not found", cid = encoded[idx]
|
|
||||||
return failure("Block not found")
|
|
||||||
|
|
||||||
trace "Encoding block", cid = blk.cid, pos = idx
|
trace "Encoding block", cid = blk.cid, pos = idx
|
||||||
shallowCopy(data[j], blk.data)
|
shallowCopy(data[j], blk.data)
|
||||||
|
@ -211,12 +207,8 @@ proc decode*(
|
||||||
|
|
||||||
idxPendingBlocks.del(idxPendingBlocks.find(done))
|
idxPendingBlocks.del(idxPendingBlocks.find(done))
|
||||||
|
|
||||||
without blkOrNone =? (await done), error:
|
without blk =? (await done), error:
|
||||||
trace "Failed retrieving block", exc = error.msg
|
trace "Failed retrieving block", error = error.msg
|
||||||
return error.failure
|
|
||||||
|
|
||||||
without blk =? blkOrNone:
|
|
||||||
trace "Block not found"
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if idx >= encoded.K:
|
if idx >= encoded.K:
|
||||||
|
|
|
@ -73,12 +73,9 @@ proc fetchManifest*(
|
||||||
return failure "CID has invalid content type for manifest"
|
return failure "CID has invalid content type for manifest"
|
||||||
|
|
||||||
trace "Received retrieval request", cid
|
trace "Received retrieval request", cid
|
||||||
without blkOrNone =? await node.blockStore.getBlock(cid), error:
|
|
||||||
return failure(error)
|
|
||||||
|
|
||||||
without blk =? blkOrNone:
|
without blk =? await node.blockStore.getBlock(cid), error:
|
||||||
trace "Block not found", cid
|
return failure error
|
||||||
return failure("Block not found")
|
|
||||||
|
|
||||||
without manifest =? Manifest.decode(blk):
|
without manifest =? Manifest.decode(blk):
|
||||||
return failure(
|
return failure(
|
||||||
|
@ -107,7 +104,7 @@ proc fetchBatched*(
|
||||||
|
|
||||||
await allFuturesThrowing(allFinished(blocks))
|
await allFuturesThrowing(allFinished(blocks))
|
||||||
if not onBatch.isNil:
|
if not onBatch.isNil:
|
||||||
await onBatch(blocks.mapIt( it.read.get.get ))
|
await onBatch(blocks.mapIt( it.read.get ))
|
||||||
except CancelledError as exc:
|
except CancelledError as exc:
|
||||||
raise exc
|
raise exc
|
||||||
except CatchableError as exc:
|
except CatchableError as exc:
|
||||||
|
|
|
@ -24,7 +24,7 @@ type
|
||||||
OnBlock* = proc(cid: Cid): Future[void] {.upraises: [], gcsafe.}
|
OnBlock* = proc(cid: Cid): Future[void] {.upraises: [], gcsafe.}
|
||||||
BlockStore* = ref object of RootObj
|
BlockStore* = ref object of RootObj
|
||||||
|
|
||||||
method getBlock*(self: BlockStore, cid: Cid): Future[?! (? Block)] {.base.} =
|
method getBlock*(self: BlockStore, cid: Cid): Future[?!Block] {.base.} =
|
||||||
## Get a block from the blockstore
|
## Get a block from the blockstore
|
||||||
##
|
##
|
||||||
|
|
||||||
|
|
|
@ -43,24 +43,24 @@ const
|
||||||
DefaultCacheSizeMiB* = 100
|
DefaultCacheSizeMiB* = 100
|
||||||
DefaultCacheSize* = DefaultCacheSizeMiB * MiB # bytes
|
DefaultCacheSize* = DefaultCacheSizeMiB * MiB # bytes
|
||||||
|
|
||||||
method getBlock*(self: CacheStore, cid: Cid): Future[?! (? Block)] {.async.} =
|
method getBlock*(self: CacheStore, cid: Cid): Future[?!Block] {.async.} =
|
||||||
## Get a block from the stores
|
## Get a block from the stores
|
||||||
##
|
##
|
||||||
|
|
||||||
trace "Getting block from cache", cid
|
trace "Getting block from cache", cid
|
||||||
|
|
||||||
if cid.isEmpty:
|
if cid.isEmpty:
|
||||||
trace "Empty block, ignoring"
|
trace "Empty block, ignoring"
|
||||||
return cid.emptyBlock.some.success
|
return success cid.emptyBlock
|
||||||
|
|
||||||
if cid notin self.cache:
|
if cid notin self.cache:
|
||||||
return Block.none.success
|
return failure (ref BlockNotFoundError)(msg: "Block not in cache")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
let blk = self.cache[cid]
|
return success self.cache[cid]
|
||||||
return blk.some.success
|
|
||||||
except CatchableError as exc:
|
except CatchableError as exc:
|
||||||
trace "Exception requesting block", cid, exc = exc.msg
|
trace "Error requesting block from cache", cid, error = exc.msg
|
||||||
return failure(exc)
|
return failure exc
|
||||||
|
|
||||||
method hasBlock*(self: CacheStore, cid: Cid): Future[?!bool] {.async.} =
|
method hasBlock*(self: CacheStore, cid: Cid): Future[?!bool] {.async.} =
|
||||||
## Check if the block exists in the blockstore
|
## Check if the block exists in the blockstore
|
||||||
|
|
|
@ -37,47 +37,70 @@ type
|
||||||
template blockPath*(self: FSStore, cid: Cid): string =
|
template blockPath*(self: FSStore, cid: Cid): string =
|
||||||
self.repoDir / ($cid)[^self.postfixLen..^1] / $cid
|
self.repoDir / ($cid)[^self.postfixLen..^1] / $cid
|
||||||
|
|
||||||
method getBlock*(self: FSStore, cid: Cid): Future[?! (? Block)] {.async.} =
|
method getBlock*(self: FSStore, cid: Cid): Future[?!Block] {.async.} =
|
||||||
## Get a block from the stores
|
## Get a block from the cache or filestore.
|
||||||
|
## Save a copy to the cache if present in the filestore but not in the cache
|
||||||
##
|
##
|
||||||
|
|
||||||
trace "Getting block from filestore", cid
|
if not self.cache.isNil:
|
||||||
|
trace "Getting block from cache or filestore", cid
|
||||||
|
else:
|
||||||
|
trace "Getting block from filestore", cid
|
||||||
|
|
||||||
if cid.isEmpty:
|
if cid.isEmpty:
|
||||||
trace "Empty block, ignoring"
|
trace "Empty block, ignoring"
|
||||||
return cid.emptyBlock.some.success
|
return success cid.emptyBlock
|
||||||
|
|
||||||
let cachedBlock = await self.cache.getBlock(cid)
|
if not self.cache.isNil:
|
||||||
if cachedBlock.isErr:
|
let
|
||||||
return cachedBlock
|
cachedBlockRes = await self.cache.getBlock(cid)
|
||||||
if cachedBlock.get.isSome:
|
|
||||||
trace "Retrieved block from cache", cid
|
if not cachedBlockRes.isErr:
|
||||||
return cachedBlock
|
return success cachedBlockRes.get
|
||||||
|
else:
|
||||||
|
trace "Unable to read block from cache", cid, error = cachedBlockRes.error.msg
|
||||||
|
|
||||||
# Read file contents
|
# Read file contents
|
||||||
var data: seq[byte]
|
var
|
||||||
|
data: seq[byte]
|
||||||
|
|
||||||
let
|
let
|
||||||
path = self.blockPath(cid)
|
path = self.blockPath(cid)
|
||||||
res = io2.readFile(path, data)
|
res = io2.readFile(path, data)
|
||||||
|
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
if not isFile(path): # May be, check instead that "res.error == ERROR_FILE_NOT_FOUND" ?
|
if not isFile(path): # May be, check instead that "res.error == ERROR_FILE_NOT_FOUND" ?
|
||||||
return Block.none.success
|
return failure (ref BlockNotFoundError)(msg: "Block not in filestore")
|
||||||
else:
|
else:
|
||||||
let error = io2.ioErrorMsg(res.error)
|
let
|
||||||
trace "Cannot read file from filestore", path, error
|
error = io2.ioErrorMsg(res.error)
|
||||||
return failure("Cannot read file from filestore")
|
|
||||||
|
|
||||||
without var blk =? Block.new(cid, data), error:
|
trace "Error requesting block from filestore", path, error
|
||||||
return error.failure
|
return failure "Error requesting block from filestore: " & error
|
||||||
|
|
||||||
# TODO: add block to the cache
|
without blk =? Block.new(cid, data), error:
|
||||||
return blk.some.success
|
trace "Unable to construct block from data", cid, error = error.msg
|
||||||
|
return failure error
|
||||||
|
|
||||||
|
if not self.cache.isNil:
|
||||||
|
let
|
||||||
|
putCachedRes = await self.cache.putBlock(blk)
|
||||||
|
|
||||||
|
if putCachedRes.isErr:
|
||||||
|
trace "Unable to store block in cache", cid, error = putCachedRes.error.msg
|
||||||
|
|
||||||
|
return success blk
|
||||||
|
|
||||||
method putBlock*(self: FSStore, blk: Block): Future[?!void] {.async.} =
|
method putBlock*(self: FSStore, blk: Block): Future[?!void] {.async.} =
|
||||||
## Write block contents to file with name based on blk.cid,
|
## Write a block's contents to a file with name based on blk.cid.
|
||||||
## save second copy to the cache
|
## Save a copy to the cache
|
||||||
##
|
##
|
||||||
|
|
||||||
|
if not self.cache.isNil:
|
||||||
|
trace "Putting block into filestore and cache", cid = blk.cid
|
||||||
|
else:
|
||||||
|
trace "Putting block into filestore", cid = blk.cid
|
||||||
|
|
||||||
if blk.isEmpty:
|
if blk.isEmpty:
|
||||||
trace "Empty block, ignoring"
|
trace "Empty block, ignoring"
|
||||||
return success()
|
return success()
|
||||||
|
@ -98,20 +121,35 @@ method putBlock*(self: FSStore, blk: Block): Future[?!void] {.async.} =
|
||||||
trace "Unable to store block", path, cid = blk.cid, error
|
trace "Unable to store block", path, cid = blk.cid, error
|
||||||
return failure("Unable to store block")
|
return failure("Unable to store block")
|
||||||
|
|
||||||
if isErr (await self.cache.putBlock(blk)):
|
if not self.cache.isNil:
|
||||||
trace "Unable to store block in cache", cid = blk.cid
|
let
|
||||||
|
putCachedRes = await self.cache.putBlock(blk)
|
||||||
|
|
||||||
|
if putCachedRes.isErr:
|
||||||
|
trace "Unable to store block in cache", cid = blk.cid, error = putCachedRes.error.msg
|
||||||
|
|
||||||
return success()
|
return success()
|
||||||
|
|
||||||
method delBlock*(self: FSStore, cid: Cid): Future[?!void] {.async.} =
|
method delBlock*(self: FSStore, cid: Cid): Future[?!void] {.async.} =
|
||||||
## Delete a block from the blockstore
|
## Delete a block from the cache and filestore
|
||||||
##
|
##
|
||||||
|
|
||||||
trace "Deleting block from filestore", cid
|
if not self.cache.isNil:
|
||||||
|
trace "Deleting block from cache and filestore", cid
|
||||||
|
else:
|
||||||
|
trace "Deleting block from filestore", cid
|
||||||
|
|
||||||
if cid.isEmpty:
|
if cid.isEmpty:
|
||||||
trace "Empty block, ignoring"
|
trace "Empty block, ignoring"
|
||||||
return success()
|
return success()
|
||||||
|
|
||||||
|
if not self.cache.isNil:
|
||||||
|
let
|
||||||
|
delCachedRes = await self.cache.delBlock(cid)
|
||||||
|
|
||||||
|
if delCachedRes.isErr:
|
||||||
|
trace "Unable to delete block from cache", cid, error = delCachedRes.error.msg
|
||||||
|
|
||||||
let
|
let
|
||||||
path = self.blockPath(cid)
|
path = self.blockPath(cid)
|
||||||
res = io2.removeFile(path)
|
res = io2.removeFile(path)
|
||||||
|
@ -121,10 +159,10 @@ method delBlock*(self: FSStore, cid: Cid): Future[?!void] {.async.} =
|
||||||
trace "Unable to delete block", path, cid, error
|
trace "Unable to delete block", path, cid, error
|
||||||
return error.failure
|
return error.failure
|
||||||
|
|
||||||
return await self.cache.delBlock(cid)
|
return success()
|
||||||
|
|
||||||
method hasBlock*(self: FSStore, cid: Cid): Future[?!bool] {.async.} =
|
method hasBlock*(self: FSStore, cid: Cid): Future[?!bool] {.async.} =
|
||||||
## Check if the block exists in the blockstore
|
## Check if a block exists in the filestore
|
||||||
##
|
##
|
||||||
|
|
||||||
trace "Checking filestore for block existence", cid
|
trace "Checking filestore for block existence", cid
|
||||||
|
@ -135,7 +173,8 @@ method hasBlock*(self: FSStore, cid: Cid): Future[?!bool] {.async.} =
|
||||||
return self.blockPath(cid).isFile().success
|
return self.blockPath(cid).isFile().success
|
||||||
|
|
||||||
method listBlocks*(self: FSStore, onBlock: OnBlock): Future[?!void] {.async.} =
|
method listBlocks*(self: FSStore, onBlock: OnBlock): Future[?!void] {.async.} =
|
||||||
## Get the list of blocks in the BlockStore. This is an intensive operation
|
## Process list of all blocks in the filestore via callback.
|
||||||
|
## This is an intensive operation
|
||||||
##
|
##
|
||||||
|
|
||||||
trace "Listing all blocks in filestore"
|
trace "Listing all blocks in filestore"
|
||||||
|
|
|
@ -31,28 +31,20 @@ type
|
||||||
engine*: BlockExcEngine # blockexc decision engine
|
engine*: BlockExcEngine # blockexc decision engine
|
||||||
localStore*: BlockStore # local block store
|
localStore*: BlockStore # local block store
|
||||||
|
|
||||||
method getBlock*(self: NetworkStore, cid: Cid): Future[?! (? bt.Block)] {.async.} =
|
method getBlock*(self: NetworkStore, cid: Cid): Future[?!bt.Block] {.async.} =
|
||||||
## Get a block from a remote peer
|
## Get a block from a remote peer
|
||||||
##
|
##
|
||||||
|
|
||||||
trace "Getting block from network store", cid
|
trace "Getting block from local store or network", cid
|
||||||
|
|
||||||
let blk = await self.localStore.getBlock(cid)
|
without blk =? await self.localStore.getBlock(cid), error:
|
||||||
if blk.isErr:
|
if not (error of BlockNotFoundError): return failure error
|
||||||
return blk
|
trace "Block not in local store", cid
|
||||||
if blk.get.isSome:
|
|
||||||
trace "Retrieved block from local store", cid
|
|
||||||
return blk
|
|
||||||
|
|
||||||
trace "Block not found in local store", cid
|
|
||||||
try:
|
|
||||||
# TODO: What if block isn't available in the engine too?
|
# TODO: What if block isn't available in the engine too?
|
||||||
let blk = await self.engine.requestBlock(cid)
|
# TODO: add retrieved block to the local store
|
||||||
# TODO: add block to the local store
|
return (await self.engine.requestBlock(cid)).catch
|
||||||
return blk.some.success
|
|
||||||
except CatchableError as exc:
|
return success blk
|
||||||
trace "Exception requesting block", cid, exc = exc.msg
|
|
||||||
return failure(exc)
|
|
||||||
|
|
||||||
method putBlock*(self: NetworkStore, blk: bt.Block): Future[?!void] {.async.} =
|
method putBlock*(self: NetworkStore, blk: bt.Block): Future[?!void] {.async.} =
|
||||||
## Store block locally and notify the network
|
## Store block locally and notify the network
|
||||||
|
|
|
@ -11,8 +11,6 @@ import pkg/upraises
|
||||||
|
|
||||||
push: {.upraises: [].}
|
push: {.upraises: [].}
|
||||||
|
|
||||||
import std/options
|
|
||||||
|
|
||||||
import pkg/chronos
|
import pkg/chronos
|
||||||
import pkg/chronicles
|
import pkg/chronicles
|
||||||
import pkg/datastore/sqlite_datastore
|
import pkg/datastore/sqlite_datastore
|
||||||
|
@ -72,7 +70,7 @@ proc blockKey*(blockCid: Cid): ?!Key =
|
||||||
|
|
||||||
method getBlock*(
|
method getBlock*(
|
||||||
self: SQLiteStore,
|
self: SQLiteStore,
|
||||||
cid: Cid): Future[?!(?Block)] {.async.} =
|
cid: Cid): Future[?!Block] {.async.} =
|
||||||
## Get a block from the cache or database.
|
## Get a block from the cache or database.
|
||||||
## Save a copy to the cache if present in the database but not in the cache
|
## Save a copy to the cache if present in the database but not in the cache
|
||||||
##
|
##
|
||||||
|
@ -84,24 +82,26 @@ method getBlock*(
|
||||||
|
|
||||||
if cid.isEmpty:
|
if cid.isEmpty:
|
||||||
trace "Empty block, ignoring"
|
trace "Empty block, ignoring"
|
||||||
return success cid.emptyBlock.some
|
return success cid.emptyBlock
|
||||||
|
|
||||||
if not self.cache.isNil:
|
if not self.cache.isNil:
|
||||||
without cachedBlkOpt =? await self.cache.getBlock(cid), error:
|
let
|
||||||
trace "Unable to read block from cache", cid, error = error.msg
|
cachedBlockRes = await self.cache.getBlock(cid)
|
||||||
|
|
||||||
if cachedBlkOpt.isSome:
|
if cachedBlockRes.isOk:
|
||||||
return success cachedBlkOpt
|
return success cachedBlockRes.get
|
||||||
|
else:
|
||||||
|
trace "Unable to read block from cache", cid, error = cachedBlockRes.error.msg
|
||||||
|
|
||||||
without blkKey =? blockKey(cid), error:
|
without blkKey =? blockKey(cid), error:
|
||||||
return failure error
|
return failure error
|
||||||
|
|
||||||
without dataOpt =? await self.datastore.get(blkKey), error:
|
without dataOpt =? await self.datastore.get(blkKey), error:
|
||||||
trace "Unable to read block from database", key = blkKey.id, error = error.msg
|
trace "Error requesting block from database", key = blkKey.id, error = error.msg
|
||||||
return failure error
|
return failure error
|
||||||
|
|
||||||
without data =? dataOpt:
|
without data =? dataOpt:
|
||||||
return success Block.none
|
return failure (ref BlockNotFoundError)(msg: "Block not in database")
|
||||||
|
|
||||||
without blk =? Block.new(cid, data), error:
|
without blk =? Block.new(cid, data), error:
|
||||||
trace "Unable to construct block from data", cid, error = error.msg
|
trace "Unable to construct block from data", cid, error = error.msg
|
||||||
|
@ -114,7 +114,7 @@ method getBlock*(
|
||||||
if putCachedRes.isErr:
|
if putCachedRes.isErr:
|
||||||
trace "Unable to store block in cache", cid, error = putCachedRes.error.msg
|
trace "Unable to store block in cache", cid, error = putCachedRes.error.msg
|
||||||
|
|
||||||
return success blk.some
|
return success blk
|
||||||
|
|
||||||
method putBlock*(
|
method putBlock*(
|
||||||
self: SQLiteStore,
|
self: SQLiteStore,
|
||||||
|
@ -154,7 +154,7 @@ method putBlock*(
|
||||||
method delBlock*(
|
method delBlock*(
|
||||||
self: SQLiteStore,
|
self: SQLiteStore,
|
||||||
cid: Cid): Future[?!void] {.async.} =
|
cid: Cid): Future[?!void] {.async.} =
|
||||||
## Delete a block from the database and cache
|
## Delete a block from the cache and database
|
||||||
##
|
##
|
||||||
|
|
||||||
if not self.cache.isNil:
|
if not self.cache.isNil:
|
||||||
|
|
|
@ -81,10 +81,9 @@ method readOnce*(
|
||||||
readBytes = min(nbytes - read, self.manifest.blockSize - blockOffset)
|
readBytes = min(nbytes - read, self.manifest.blockSize - blockOffset)
|
||||||
|
|
||||||
# Read contents of block `blockNum`
|
# Read contents of block `blockNum`
|
||||||
without blkOrNone =? await self.store.getBlock(self.manifest[blockNum]), error:
|
without blk =? await self.store.getBlock(self.manifest[blockNum]), error:
|
||||||
raise newLPStreamReadError(error)
|
raise newLPStreamReadError(error)
|
||||||
without blk =? blkOrNone:
|
|
||||||
raise newLPStreamReadError("Block not found")
|
|
||||||
trace "Reading bytes from store stream", blockNum, cid = blk.cid, bytes = readBytes, blockOffset
|
trace "Reading bytes from store stream", blockNum, cid = blk.cid, bytes = readBytes, blockOffset
|
||||||
|
|
||||||
# Copy `readBytes` bytes starting at `blockOffset` from the block into the outbuf
|
# Copy `readBytes` bytes starting at `blockOffset` from the block into the outbuf
|
||||||
|
|
|
@ -126,7 +126,7 @@ suite "NetworkStore engine - 2 nodes":
|
||||||
test "Should get blocks from remote":
|
test "Should get blocks from remote":
|
||||||
let blocks = await allFinished(
|
let blocks = await allFinished(
|
||||||
blocks2.mapIt( nodeCmps1.networkStore.getBlock(it.cid) ))
|
blocks2.mapIt( nodeCmps1.networkStore.getBlock(it.cid) ))
|
||||||
check blocks.mapIt( it.read().tryGet().get() ) == blocks2
|
check blocks.mapIt( it.read().tryGet() ) == blocks2
|
||||||
|
|
||||||
test "Remote should send blocks when available":
|
test "Remote should send blocks when available":
|
||||||
let blk = bt.Block.new("Block 1".toBytes).tryGet()
|
let blk = bt.Block.new("Block 1".toBytes).tryGet()
|
||||||
|
|
|
@ -47,7 +47,7 @@ proc corruptBlocks*(
|
||||||
|
|
||||||
pos.add(i)
|
pos.add(i)
|
||||||
var
|
var
|
||||||
blk = (await store.getBlock(manifest[i])).tryGet().get()
|
blk = (await store.getBlock(manifest[i])).tryGet()
|
||||||
bytePos: seq[int]
|
bytePos: seq[int]
|
||||||
|
|
||||||
while true:
|
while true:
|
||||||
|
|
|
@ -72,11 +72,13 @@ suite "Cache Store":
|
||||||
store = CacheStore.new(@[newBlock])
|
store = CacheStore.new(@[newBlock])
|
||||||
|
|
||||||
let blk = await store.getBlock(newBlock.cid)
|
let blk = await store.getBlock(newBlock.cid)
|
||||||
check blk.tryGet().get() == newBlock
|
check blk.tryGet() == newBlock
|
||||||
|
|
||||||
test "fail getBlock":
|
test "fail getBlock":
|
||||||
let blk = await store.getBlock(newBlock.cid)
|
let blk = await store.getBlock(newBlock.cid)
|
||||||
check blk.tryGet().isNone()
|
check:
|
||||||
|
blk.isErr
|
||||||
|
blk.error of BlockNotFoundError
|
||||||
|
|
||||||
test "hasBlock":
|
test "hasBlock":
|
||||||
let store = CacheStore.new(@[newBlock])
|
let store = CacheStore.new(@[newBlock])
|
||||||
|
|
|
@ -16,62 +16,73 @@ import pkg/codex/blocktype as bt
|
||||||
|
|
||||||
import ../helpers
|
import ../helpers
|
||||||
|
|
||||||
suite "FS Store":
|
proc runSuite(cache: bool) =
|
||||||
var
|
suite "FS Store " & (if cache: "(cache enabled)" else: "(cache disabled)"):
|
||||||
store: FSStore
|
var
|
||||||
repoDir: string
|
store: FSStore
|
||||||
newBlock = bt.Block.new("New Block".toBytes()).tryGet()
|
repoDir: string
|
||||||
|
newBlock = bt.Block.new("New Block".toBytes()).tryGet()
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
repoDir = getAppDir() / "repo"
|
repoDir = getAppDir() / "repo"
|
||||||
createDir(repoDir)
|
createDir(repoDir)
|
||||||
store = FSStore.new(repoDir)
|
|
||||||
|
|
||||||
teardown:
|
if cache:
|
||||||
removeDir(repoDir)
|
store = FSStore.new(repoDir)
|
||||||
|
else:
|
||||||
|
store = FSStore.new(repoDir, postfixLen = 2, cache = nil)
|
||||||
|
|
||||||
test "putBlock":
|
teardown:
|
||||||
(await store.putBlock(newBlock)).tryGet()
|
removeDir(repoDir)
|
||||||
check:
|
|
||||||
fileExists(store.blockPath(newBlock.cid))
|
|
||||||
(await store.hasBlock(newBlock.cid)).tryGet()
|
|
||||||
await newBlock.cid in store
|
|
||||||
|
|
||||||
test "getBlock":
|
test "putBlock":
|
||||||
createDir(store.blockPath(newBlock.cid).parentDir)
|
(await store.putBlock(newBlock)).tryGet()
|
||||||
writeFile(store.blockPath(newBlock.cid), newBlock.data)
|
check:
|
||||||
let blk = await store.getBlock(newBlock.cid)
|
fileExists(store.blockPath(newBlock.cid))
|
||||||
check blk.tryGet().get() == newBlock
|
(await store.hasBlock(newBlock.cid)).tryGet()
|
||||||
|
await newBlock.cid in store
|
||||||
|
|
||||||
test "fail getBlock":
|
test "getBlock":
|
||||||
let blk = await store.getBlock(newBlock.cid)
|
createDir(store.blockPath(newBlock.cid).parentDir)
|
||||||
check blk.tryGet().isNone
|
writeFile(store.blockPath(newBlock.cid), newBlock.data)
|
||||||
|
let blk = await store.getBlock(newBlock.cid)
|
||||||
|
check blk.tryGet() == newBlock
|
||||||
|
|
||||||
test "hasBlock":
|
test "fail getBlock":
|
||||||
createDir(store.blockPath(newBlock.cid).parentDir)
|
let blk = await store.getBlock(newBlock.cid)
|
||||||
writeFile(store.blockPath(newBlock.cid), newBlock.data)
|
check:
|
||||||
|
blk.isErr
|
||||||
|
blk.error of BlockNotFoundError
|
||||||
|
|
||||||
check:
|
test "hasBlock":
|
||||||
(await store.hasBlock(newBlock.cid)).tryGet()
|
createDir(store.blockPath(newBlock.cid).parentDir)
|
||||||
await newBlock.cid in store
|
writeFile(store.blockPath(newBlock.cid), newBlock.data)
|
||||||
|
|
||||||
test "fail hasBlock":
|
check:
|
||||||
check:
|
(await store.hasBlock(newBlock.cid)).tryGet()
|
||||||
not (await store.hasBlock(newBlock.cid)).tryGet()
|
await newBlock.cid in store
|
||||||
not (await newBlock.cid in store)
|
|
||||||
|
|
||||||
test "listBlocks":
|
test "fail hasBlock":
|
||||||
createDir(store.blockPath(newBlock.cid).parentDir)
|
check:
|
||||||
writeFile(store.blockPath(newBlock.cid), newBlock.data)
|
not (await store.hasBlock(newBlock.cid)).tryGet()
|
||||||
|
not (await newBlock.cid in store)
|
||||||
|
|
||||||
(await store.listBlocks(
|
test "listBlocks":
|
||||||
proc(cid: Cid) {.gcsafe, async.} =
|
createDir(store.blockPath(newBlock.cid).parentDir)
|
||||||
check cid == newBlock.cid
|
writeFile(store.blockPath(newBlock.cid), newBlock.data)
|
||||||
)).tryGet()
|
|
||||||
|
|
||||||
test "delBlock":
|
(await store.listBlocks(
|
||||||
createDir(store.blockPath(newBlock.cid).parentDir)
|
proc(cid: Cid) {.gcsafe, async.} =
|
||||||
writeFile(store.blockPath(newBlock.cid), newBlock.data)
|
check cid == newBlock.cid
|
||||||
|
)).tryGet()
|
||||||
|
|
||||||
(await store.delBlock(newBlock.cid)).tryGet()
|
test "delBlock":
|
||||||
check not fileExists(store.blockPath(newBlock.cid))
|
createDir(store.blockPath(newBlock.cid).parentDir)
|
||||||
|
writeFile(store.blockPath(newBlock.cid), newBlock.data)
|
||||||
|
|
||||||
|
(await store.delBlock(newBlock.cid)).tryGet()
|
||||||
|
|
||||||
|
check not fileExists(store.blockPath(newBlock.cid))
|
||||||
|
|
||||||
|
runSuite(cache = true)
|
||||||
|
runSuite(cache = false)
|
||||||
|
|
|
@ -43,7 +43,7 @@ proc runSuite(cache: bool) =
|
||||||
if cache:
|
if cache:
|
||||||
store = SQLiteStore.new(repoDir)
|
store = SQLiteStore.new(repoDir)
|
||||||
else:
|
else:
|
||||||
store = SQLiteStore.new(repoDir, nil)
|
store = SQLiteStore.new(repoDir, cache = nil)
|
||||||
|
|
||||||
newBlock = randomBlock()
|
newBlock = randomBlock()
|
||||||
|
|
||||||
|
@ -132,37 +132,24 @@ proc runSuite(cache: bool) =
|
||||||
# get from database
|
# get from database
|
||||||
getRes = await store.getBlock(newBlock.cid)
|
getRes = await store.getBlock(newBlock.cid)
|
||||||
|
|
||||||
check: getRes.isOk
|
|
||||||
|
|
||||||
var
|
|
||||||
blkOpt = getRes.get
|
|
||||||
|
|
||||||
check:
|
check:
|
||||||
blkOpt.isSome
|
getRes.isOk
|
||||||
blkOpt.get == newBlock
|
getRes.get == newBlock
|
||||||
|
|
||||||
# get from enabled cache
|
# get from enabled cache
|
||||||
getRes = await store.getBlock(newBlock.cid)
|
getRes = await store.getBlock(newBlock.cid)
|
||||||
|
|
||||||
check: getRes.isOk
|
|
||||||
|
|
||||||
blkOpt = getRes.get
|
|
||||||
|
|
||||||
check:
|
check:
|
||||||
blkOpt.isSome
|
getRes.isOk
|
||||||
blkOpt.get == newBlock
|
getRes.get == newBlock
|
||||||
|
|
||||||
test "fail getBlock":
|
test "fail getBlock":
|
||||||
let
|
let
|
||||||
getRes = await store.getBlock(newBlock.cid)
|
blkRes = await store.getBlock(newBlock.cid)
|
||||||
|
|
||||||
assert getRes.isOk
|
|
||||||
|
|
||||||
let
|
|
||||||
blkOpt = getRes.get
|
|
||||||
|
|
||||||
check: blkOpt.isNone
|
|
||||||
|
|
||||||
|
check:
|
||||||
|
blkRes.isErr
|
||||||
|
blkRes.error of BlockNotFoundError
|
||||||
|
|
||||||
test "hasBlock":
|
test "hasBlock":
|
||||||
let
|
let
|
||||||
|
|
|
@ -158,7 +158,7 @@ suite "Test Node":
|
||||||
(await localStore.hasBlock(manifestCid)).tryGet()
|
(await localStore.hasBlock(manifestCid)).tryGet()
|
||||||
|
|
||||||
var
|
var
|
||||||
manifestBlock = (await localStore.getBlock(manifestCid)).tryGet().get()
|
manifestBlock = (await localStore.getBlock(manifestCid)).tryGet()
|
||||||
localManifest = Manifest.decode(manifestBlock).tryGet()
|
localManifest = Manifest.decode(manifestBlock).tryGet()
|
||||||
|
|
||||||
check:
|
check:
|
||||||
|
|
Loading…
Reference in New Issue