Skip to content

Commit 8e1699b

Browse files
committed
Expiry per dataset
1 parent 4f56f2a commit 8e1699b

22 files changed

+467
-639
lines changed

README.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,9 @@ The following options are available:
8888
--api-bindaddr The REST API bind address [=127.0.0.1].
8989
-p, --api-port The REST Api port [=8080].
9090
--repo-kind Backend for main repo store (fs, sqlite) [=fs].
91-
-q, --storage-quota The size of the total storage quota dedicated to the node [=8589934592].
92-
-t, --block-ttl Default block timeout in seconds - 0 disables the ttl [=$DefaultBlockTtl].
93-
--block-mi Time interval in seconds - determines frequency of block maintenance cycle: how
94-
often blocks are checked for expiration and cleanup
95-
[=$DefaultBlockMaintenanceInterval].
96-
--block-mn Number of blocks to check every maintenance cycle [=1000].
91+
-q, --storage-quota The size in bytes of the total storage quota dedicated to the node [=8589934592].
92+
-t, --default-ttl Default dataset expiry [=1d].
93+
--maintenance-interval Determines how frequently datasets are checked for expiration and cleanup [=5m].
9794
-c, --cache-size The size of the block cache, 0 disables the cache - might help on slow hardrives
9895
[=0].
9996

codex/codex.nim

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ type
5454
restServer: RestServerRef
5555
codexNode: CodexNodeRef
5656
repoStore: RepoStore
57-
maintenance: BlockMaintainer
57+
maintenance: DatasetMaintainer
5858
taskpool: Taskpool
5959

6060
CodexPrivateKey* = libp2p.PrivateKey # alias
@@ -246,6 +246,9 @@ proc new*(
246246
wallet = WalletRef.new(EthPrivateKey.random())
247247
network = BlockExcNetwork.new(switch)
248248

249+
metaDs = LevelDbDatastore.new(config.dataDir / CodexMetaNamespace)
250+
.expect("Should create metadata store!")
251+
249252
repoData = case config.repoKind
250253
of repoFS: Datastore(FSDatastore.new($config.dataDir, depth = 5)
251254
.expect("Should create repo file data store!"))
@@ -256,21 +259,21 @@ proc new*(
256259

257260
repoStore = RepoStore.new(
258261
repoDs = repoData,
259-
metaDs = LevelDbDatastore.new(config.dataDir / CodexMetaNamespace)
260-
.expect("Should create metadata store!"),
261-
quotaMaxBytes = config.storageQuota,
262-
blockTtl = config.blockTtl)
262+
metaDs = metaDs,
263+
quotaMaxBytes = config.storageQuota)
263264

264-
maintenance = BlockMaintainer.new(
265+
maintenance = DatasetMaintainer.new(
265266
repoStore,
266-
interval = config.blockMaintenanceInterval,
267-
numberOfBlocksPerInterval = config.blockMaintenanceNumberOfBlocks)
267+
metaDs,
268+
defaultExpiry = config.defaultExpiry,
269+
interval = config.maintenanceInterval)
268270

269271
peerStore = PeerCtxStore.new()
270272
pendingBlocks = PendingBlocksManager.new()
271273
blockDiscovery = DiscoveryEngine.new(repoStore, peerStore, network, discovery, pendingBlocks)
272274
engine = BlockExcEngine.new(repoStore, wallet, network, blockDiscovery, peerStore, pendingBlocks)
273275
store = NetworkStore.new(engine, repoStore)
276+
274277
prover = if config.prover:
275278
if not fileAccessible($config.circomR1cs, {AccessFlags.Read}) and
276279
endsWith($config.circomR1cs, ".r1cs"):
@@ -306,6 +309,7 @@ proc new*(
306309
codexNode = CodexNodeRef.new(
307310
switch = switch,
308311
networkStore = store,
312+
maintenance = maintenance,
309313
engine = engine,
310314
prover = prover,
311315
discovery = discovery,

codex/conf.nim

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ export units, net, codextypes, logutils
4242

4343
export
4444
DefaultQuotaBytes,
45-
DefaultBlockTtl,
46-
DefaultBlockMaintenanceInterval,
47-
DefaultNumberOfBlocksToMaintainPerInterval
45+
DefaultDefaultExpiry,
46+
DefaultMaintenanceInterval
4847

4948
proc defaultDataDir*(): string =
5049
let dataDir = when defined(windows):
@@ -209,24 +208,18 @@ type
209208
name: "storage-quota"
210209
abbr: "q" }: NBytes
211210

212-
blockTtl* {.
213-
desc: "Default block timeout in seconds - 0 disables the ttl"
214-
defaultValue: DefaultBlockTtl
215-
defaultValueDesc: $DefaultBlockTtl
216-
name: "block-ttl"
211+
defaultExpiry* {.
212+
desc: "Default dataset expiry in seconds"
213+
defaultValue: DefaultDefaultExpiry
214+
defaultValueDesc: $DefaultDefaultExpiry
215+
name: "default-ttl"
217216
abbr: "t" }: Duration
218217

219-
blockMaintenanceInterval* {.
220-
desc: "Time interval in seconds - determines frequency of block maintenance cycle: how often blocks are checked for expiration and cleanup"
221-
defaultValue: DefaultBlockMaintenanceInterval
222-
defaultValueDesc: $DefaultBlockMaintenanceInterval
223-
name: "block-mi" }: Duration
224-
225-
blockMaintenanceNumberOfBlocks* {.
226-
desc: "Number of blocks to check every maintenance cycle"
227-
defaultValue: DefaultNumberOfBlocksToMaintainPerInterval
228-
defaultValueDesc: $DefaultNumberOfBlocksToMaintainPerInterval
229-
name: "block-mn" }: int
218+
maintenanceInterval* {.
219+
desc: "Determines how frequently datasets are checked for expiration and cleanup"
220+
defaultValue: DefaultMaintenanceInterval
221+
defaultValueDesc: $DefaultMaintenanceInterval
222+
name: "maintenance-interval" }: Duration
230223

231224
cacheSize* {.
232225
desc: "The size of the block cache, 0 disables the cache - might help on slow hardrives"

codex/namespaces.nim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ const
1818
CodexMetaNamespace & "/ttl"
1919
CodexBlockProofNamespace* = # Cid and Proof
2020
CodexMetaNamespace & "/proof"
21+
CodexDatasetMetadataNamespace* = # Dataset
22+
CodexMetaNamespace & "/dataset"
2123
CodexDhtNamespace* = "dht" # Dht namespace
2224
CodexDhtProvidersNamespace* = # Dht providers namespace
2325
CodexDhtNamespace & "/providers"

codex/node.nim

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ type
6565
switch: Switch
6666
networkId: PeerId
6767
networkStore: NetworkStore
68+
maintenance: DatasetMaintainer
6869
engine: BlockExcEngine
6970
prover: ?Prover
7071
discovery: Discovery
@@ -155,17 +156,8 @@ proc updateExpiry*(
155156
trace "Unable to fetch manifest for cid", manifestCid
156157
return failure(error)
157158

158-
try:
159-
let
160-
ensuringFutures = Iter[int].new(0..<manifest.blocksCount)
161-
.mapIt(self.networkStore.localStore.ensureExpiry( manifest.treeCid, it, expiry ))
162-
await allFuturesThrowing(ensuringFutures)
163-
except CancelledError as exc:
164-
raise exc
165-
except CatchableError as exc:
166-
return failure(exc.msg)
159+
await self.maintenance.ensureExpiry(manifest.treeCid, expiry)
167160

168-
return success()
169161

170162
proc fetchBatched*(
171163
self: CodexNodeRef,
@@ -274,6 +266,13 @@ proc streamEntireDataset(
274266

275267
# Retrieve all blocks of the dataset sequentially from the local store or network
276268
trace "Creating store stream for manifest", manifestCid
269+
270+
if err =? (await self.maintenance.trackExpiry(
271+
manifest.treeCid,
272+
manifest.blocksCount,
273+
manifestsCids = @[manifestCid])).errorOption:
274+
return failure(err)
275+
277276
LPStream(StoreStream.new(self.networkStore, manifest, pad = false)).success
278277

279278
proc retrieve*(
@@ -361,6 +360,12 @@ proc store*(
361360
error "Unable to store manifest"
362361
return failure(err)
363362

363+
if err =? (await self.maintenance.trackExpiry(
364+
treeCid,
365+
manifest.blocksCount,
366+
manifestsCids = @[manifestBlk.cid])).errorOption:
367+
return failure(err)
368+
364369
info "Stored data", manifestCid = manifestBlk.cid,
365370
treeCid = treeCid,
366371
blocks = manifest.blocksCount,
@@ -566,18 +571,17 @@ proc onStore(
566571
trace "Slot index not in manifest", slotIdx
567572
return failure(newException(CodexError, "Slot index not in manifest"))
568573

569-
proc updateExpiry(blocks: seq[bt.Block]): Future[?!void] {.async.} =
570-
trace "Updating expiry for blocks", blocks = blocks.len
571-
572-
let ensureExpiryFutures = blocks.mapIt(self.networkStore.ensureExpiry(it.cid, expiry))
573-
if updateExpiryErr =? (await allFutureResult(ensureExpiryFutures)).errorOption:
574-
return failure(updateExpiryErr)
575-
576-
if not blocksCb.isNil and err =? (await blocksCb(blocks)).errorOption:
577-
trace "Unable to process blocks", err = err.msg
578-
return failure(err)
574+
proc onBatch(blocks: seq[bt.Block]): Future[?!void] {.async.} =
575+
if not blocksCb.isNil:
576+
await blocksCb(blocks)
577+
else:
578+
success()
579579

580-
return success()
580+
if err =? (await self.maintenance.trackExpiry(
581+
manifest.treeCid,
582+
manifest.blocksCount,
583+
manifestsCids = @[cid])).errorOption:
584+
return failure(err)
581585

582586
without indexer =? manifest.verifiableStrategy.init(
583587
0, manifest.blocksCount - 1, manifest.numSlots).catch, err:
@@ -591,7 +595,7 @@ proc onStore(
591595
if err =? (await self.fetchBatched(
592596
manifest.treeCid,
593597
blksIter,
594-
onBatch = updateExpiry)).errorOption:
598+
onBatch = onBatch)).errorOption:
595599
trace "Unable to fetch blocks", err = err.msg
596600
return failure(err)
597601

@@ -607,6 +611,11 @@ proc onStore(
607611

608612
trace "Slot successfully retrieved and reconstructed"
609613

614+
if err =? (await self.maintenance.ensureExpiry(
615+
manifest.treeCid,
616+
expiry)).errorOption:
617+
return failure(err)
618+
610619
return success()
611620

612621
proc onProve(
@@ -771,6 +780,7 @@ proc new*(
771780
T: type CodexNodeRef,
772781
switch: Switch,
773782
networkStore: NetworkStore,
783+
maintenance: DatasetMaintainer,
774784
engine: BlockExcEngine,
775785
discovery: Discovery,
776786
prover = Prover.none,
@@ -782,6 +792,7 @@ proc new*(
782792
CodexNodeRef(
783793
switch: switch,
784794
networkStore: networkStore,
795+
maintenance: maintenance,
785796
engine: engine,
786797
prover: prover,
787798
discovery: discovery,

codex/stores/blockstore.nim

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ method getBlockAndProof*(self: BlockStore, treeCid: Cid, index: Natural): Future
6161
raiseAssert("getBlockAndProof not implemented!")
6262

6363
method putBlock*(
64-
self: BlockStore,
65-
blk: Block,
66-
ttl = Duration.none): Future[?!void] {.base.} =
64+
self: BlockStore,
65+
blk: Block
66+
): Future[?!void] {.base.} =
6767
## Put a block to the blockstore
6868
##
6969

@@ -89,27 +89,6 @@ method getCidAndProof*(
8989

9090
raiseAssert("getCidAndProof not implemented!")
9191

92-
method ensureExpiry*(
93-
self: BlockStore,
94-
cid: Cid,
95-
expiry: SecondsSince1970): Future[?!void] {.base.} =
96-
## Ensure that block's assosicated expiry is at least given timestamp
97-
## If the current expiry is lower then it is updated to the given one, otherwise it is left intact
98-
##
99-
100-
raiseAssert("Not implemented!")
101-
102-
method ensureExpiry*(
103-
self: BlockStore,
104-
treeCid: Cid,
105-
index: Natural,
106-
expiry: SecondsSince1970): Future[?!void] {.base.} =
107-
## Ensure that block's associated expiry is at least given timestamp
108-
## If the current expiry is lower then it is updated to the given one, otherwise it is left intact
109-
##
110-
111-
raiseAssert("Not implemented!")
112-
11392
method delBlock*(self: BlockStore, cid: Cid): Future[?!void] {.base.} =
11493
## Delete a block from the blockstore
11594
##

codex/stores/cachestore.nim

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,7 @@ func putBlockSync(self: CacheStore, blk: Block): bool =
186186
187187
method putBlock*(
188188
self: CacheStore,
189-
blk: Block,
190-
ttl = Duration.none): Future[?!void] {.async.} =
189+
blk: Block): Future[?!void] {.async.} =
191190
## Put a block to the blockstore
192191
##
193192
@@ -209,27 +208,6 @@ method putCidAndProof*(
209208
self.cidAndProofCache[(treeCid, index)] = (blockCid, proof)
210209
success()
211210

212-
method ensureExpiry*(
213-
self: CacheStore,
214-
cid: Cid,
215-
expiry: SecondsSince1970
216-
): Future[?!void] {.async.} =
217-
## Updates block's assosicated TTL in store - not applicable for CacheStore
218-
##
219-
220-
discard # CacheStore does not have notion of TTL
221-
222-
method ensureExpiry*(
223-
self: CacheStore,
224-
treeCid: Cid,
225-
index: Natural,
226-
expiry: SecondsSince1970
227-
): Future[?!void] {.async.} =
228-
## Updates block's associated TTL in store - not applicable for CacheStore
229-
##
230-
231-
discard # CacheStore does not have notion of TTL
232-
233211
method delBlock*(self: CacheStore, cid: Cid): Future[?!void] {.async.} =
234212
## Delete a block from the blockstore
235213
##

codex/stores/keyutils.nim

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const
2525
CodexManifestKey* = Key.init(CodexManifestNamespace).tryGet
2626
BlocksTtlKey* = Key.init(CodexBlocksTtlNamespace).tryGet
2727
BlockProofKey* = Key.init(CodexBlockProofNamespace).tryGet
28+
DatasetMetadataKey* = Key.init(CodexDatasetMetadataNamespace).tryGet
2829
QuotaKey* = Key.init(CodexQuotaNamespace).tryGet
2930
QuotaUsedKey* = (QuotaKey / "used").tryGet
3031
QuotaReservedKey* = (QuotaKey / "reserved").tryGet
@@ -47,3 +48,10 @@ proc createBlockExpirationMetadataQueryKey*(): ?!Key =
4748

4849
proc createBlockCidAndProofMetadataKey*(treeCid: Cid, index: Natural): ?!Key =
4950
(BlockProofKey / $treeCid).flatMap((k: Key) => k / $index)
51+
52+
proc createDatasetMetadataKey*(treeCid: Cid): ?!Key =
53+
DatasetMetadataKey / $treeCid
54+
55+
proc createDatasetMetadataQueryKey*(): ?!Key =
56+
let queryString = ? (DatasetMetadataKey / "*")
57+
Key.init(queryString)

0 commit comments

Comments
 (0)