mirror of
https://github.com/logos-storage/logos-storage-nim.git
synced 2026-05-04 02:23:13 +00:00
* initial implementation of repo store * allow isManifest on multicodec * rework with new blockstore * add raw codec * rework listBlocks * remove fsstore * reworking with repostore * bump datastore * fix listBlocks iterator * adding store's common tests * run common store tests * remove fsstore backend tests * bump datastore * add `listBlocks` tests * listBlocks filter based on block type * disabling tests in need of rewriting * allow passing block type * move BlockNotFoundError definition * fix tests * increase default advertise loop sleep to 10 mins * use `self` * add cache quota functionality * pass meta store and start repo * add `CacheQuotaNamespace` * pass meta store * bump datastore to latest master * don't use os `/` as key separator * Added quota limits support * tests for quota limits * add block expiration key * remove unnesesary space * use idleAsync in listBlocks * proper test name * re-add contrlC try/except * add storage quota and block ttl config options * clarify comments * change expires key format * check for block presence before storing * bump datastore * use dht with fixed datastore `has` * bump datastore to latest master * bump dht to latest master
171 lines
4.3 KiB
Nim
171 lines
4.3 KiB
Nim
import std/os
|
|
import std/options
|
|
import std/strutils
|
|
|
|
import pkg/questionable
|
|
import pkg/questionable/results
|
|
|
|
import pkg/chronos
|
|
import pkg/asynctest
|
|
import pkg/libp2p
|
|
import pkg/stew/byteutils
|
|
import pkg/stew/endians2
|
|
import pkg/datastore
|
|
|
|
import pkg/codex/stores/cachestore
|
|
import pkg/codex/chunker
|
|
import pkg/codex/stores
|
|
import pkg/codex/blocktype as bt
|
|
|
|
import ../helpers
|
|
import ./commonstoretests
|
|
|
|
suite "Test RepoStore Quota":
|
|
|
|
var
|
|
repoDs: Datastore
|
|
metaDs: Datastore
|
|
|
|
setup:
|
|
repoDs = SQLiteDatastore.new(Memory).tryGet()
|
|
metaDs = SQLiteDatastore.new(Memory).tryGet()
|
|
|
|
teardown:
|
|
(await repoDs.close()).tryGet
|
|
(await metaDs.close()).tryGet
|
|
|
|
test "Should update current used bytes on block put":
|
|
let
|
|
blk = bt.Block.new('a'.repeat(100).toBytes).tryGet()
|
|
repo = RepoStore.new(repoDs, metaDs, quotaMaxBytes = 100)
|
|
|
|
check repo.quotaUsedBytes == 0
|
|
(await repo.putBlock(blk)).tryGet
|
|
|
|
check:
|
|
repo.quotaUsedBytes == 100
|
|
uint64.fromBytesBE((await metaDs.get(QuotaUsedKey)).tryGet) == 100'u
|
|
|
|
test "Should update current used bytes on block delete":
|
|
let
|
|
blk = bt.Block.new('a'.repeat(100).toBytes).tryGet()
|
|
repo = RepoStore.new(repoDs, metaDs, quotaMaxBytes = 100)
|
|
|
|
check repo.quotaUsedBytes == 0
|
|
(await repo.putBlock(blk)).tryGet
|
|
check repo.quotaUsedBytes == 100
|
|
|
|
(await repo.delBlock(blk.cid)).tryGet
|
|
|
|
check:
|
|
repo.quotaUsedBytes == 0
|
|
uint64.fromBytesBE((await metaDs.get(QuotaUsedKey)).tryGet) == 0'u
|
|
|
|
test "Should fail storing passed the quota":
|
|
let
|
|
blk = bt.Block.new('a'.repeat(200).toBytes).tryGet()
|
|
repo = RepoStore.new(repoDs, metaDs, quotaMaxBytes = 100)
|
|
|
|
check repo.totalUsed == 0
|
|
expect QuotaUsedError:
|
|
(await repo.putBlock(blk)).tryGet
|
|
|
|
test "Should reserve bytes":
|
|
let
|
|
blk = bt.Block.new('a'.repeat(100).toBytes).tryGet()
|
|
repo = RepoStore.new(repoDs, metaDs, quotaMaxBytes = 200)
|
|
|
|
check repo.totalUsed == 0
|
|
(await repo.putBlock(blk)).tryGet
|
|
check repo.totalUsed == 100
|
|
|
|
(await repo.reserve(100)).tryGet
|
|
|
|
check:
|
|
repo.totalUsed == 200
|
|
repo.quotaUsedBytes == 100
|
|
repo.quotaReservedBytes == 100
|
|
uint64.fromBytesBE((await metaDs.get(QuotaReservedKey)).tryGet) == 100'u
|
|
|
|
test "Should not reserve bytes over max quota":
|
|
let
|
|
blk = bt.Block.new('a'.repeat(100).toBytes).tryGet()
|
|
repo = RepoStore.new(repoDs, metaDs, quotaMaxBytes = 200)
|
|
|
|
check repo.totalUsed == 0
|
|
(await repo.putBlock(blk)).tryGet
|
|
check repo.totalUsed == 100
|
|
|
|
expect QuotaNotEnoughError:
|
|
(await repo.reserve(101)).tryGet
|
|
|
|
check:
|
|
repo.totalUsed == 100
|
|
repo.quotaUsedBytes == 100
|
|
repo.quotaReservedBytes == 0
|
|
|
|
expect DatastoreKeyNotFound:
|
|
discard (await metaDs.get(QuotaReservedKey)).tryGet
|
|
|
|
test "Should release bytes":
|
|
let
|
|
blk = bt.Block.new('a'.repeat(100).toBytes).tryGet()
|
|
repo = RepoStore.new(repoDs, metaDs, quotaMaxBytes = 200)
|
|
|
|
check repo.totalUsed == 0
|
|
(await repo.reserve(100)).tryGet
|
|
check repo.totalUsed == 100
|
|
|
|
(await repo.release(100)).tryGet
|
|
|
|
check:
|
|
repo.totalUsed == 0
|
|
repo.quotaUsedBytes == 0
|
|
repo.quotaReservedBytes == 0
|
|
uint64.fromBytesBE((await metaDs.get(QuotaReservedKey)).tryGet) == 0'u
|
|
|
|
test "Should not release bytes less than quota":
|
|
let
|
|
repo = RepoStore.new(repoDs, metaDs, quotaMaxBytes = 200)
|
|
|
|
check repo.totalUsed == 0
|
|
(await repo.reserve(100)).tryGet
|
|
check repo.totalUsed == 100
|
|
|
|
expect CatchableError:
|
|
(await repo.release(101)).tryGet
|
|
|
|
check:
|
|
repo.totalUsed == 100
|
|
repo.quotaUsedBytes == 0
|
|
repo.quotaReservedBytes == 100
|
|
uint64.fromBytesBE((await metaDs.get(QuotaReservedKey)).tryGet) == 100'u
|
|
|
|
commonBlockStoreTests(
|
|
"RepoStore Sql backend", proc: BlockStore =
|
|
BlockStore(
|
|
RepoStore.new(
|
|
SQLiteDatastore.new(Memory).tryGet(),
|
|
SQLiteDatastore.new(Memory).tryGet())))
|
|
|
|
const
|
|
path = currentSourcePath().parentDir / "test"
|
|
|
|
proc before() {.async.} =
|
|
createDir(path)
|
|
|
|
proc after() {.async.} =
|
|
removeDir(path)
|
|
|
|
let
|
|
depth = path.split(DirSep).len
|
|
|
|
commonBlockStoreTests(
|
|
"RepoStore FS backend", proc: BlockStore =
|
|
BlockStore(
|
|
RepoStore.new(
|
|
FSDatastore.new(path, depth).tryGet(),
|
|
SQLiteDatastore.new(Memory).tryGet())),
|
|
before = before,
|
|
after = after)
|