nim-datastore/datastore/tieredds.nim

153 lines
3.0 KiB
Nim
Raw Normal View History

{.push raises: [].}
import std/sequtils
import pkg/chronos
2022-05-11 15:50:05 +00:00
import pkg/questionable
import pkg/questionable/results
import ./datastore
export datastore
type
TieredDatastore* = ref object of Datastore
stores: seq[Datastore]
proc new*(
T: type TieredDatastore,
stores: varargs[Datastore]): ?!T =
if stores.len == 0:
failure "stores must contain at least one Datastore"
else:
success T(stores: @stores)
proc stores*(self: TieredDatastore): seq[Datastore] =
self.stores
2022-12-02 22:25:44 +00:00
method has*(
2022-05-11 15:50:05 +00:00
self: TieredDatastore,
2022-12-02 22:25:44 +00:00
key: Key): Future[?!bool] {.async.} =
2022-05-11 15:50:05 +00:00
for store in self.stores:
2022-12-02 22:25:44 +00:00
without res =? (await store.has(key)), err:
return failure(err)
2022-05-11 15:50:05 +00:00
2022-12-02 22:25:44 +00:00
if res:
return success true
return success false
2022-05-11 15:50:05 +00:00
method delete*(
self: TieredDatastore,
2022-12-02 22:25:44 +00:00
key: Key): Future[?!void] {.async.} =
2022-05-11 15:50:05 +00:00
let
pending = await allFinished(self.stores.mapIt(it.delete(key)))
for fut in pending:
if fut.read().isErr: return fut.read()
2022-05-11 15:50:05 +00:00
return success()
2022-05-11 15:50:05 +00:00
method delete*(
self: TieredDatastore,
2022-12-02 22:25:44 +00:00
keys: seq[Key]): Future[?!void] {.async.} =
for key in keys:
let
pending = await allFinished(self.stores.mapIt(it.delete(key)))
for fut in pending:
if fut.read().isErr: return fut.read()
return success()
2022-05-11 15:50:05 +00:00
method get*(
self: TieredDatastore,
2022-12-02 22:25:44 +00:00
key: Key): Future[?!seq[byte]] {.async.} =
2022-05-11 15:50:05 +00:00
var
2022-09-19 23:13:34 +00:00
bytes: seq[byte]
2022-05-11 15:50:05 +00:00
for store in self.stores:
2022-09-19 23:13:34 +00:00
without bytes =? (await store.get(key)):
continue
2022-09-19 23:13:34 +00:00
if bytes.len <= 0:
continue
2022-05-11 15:50:05 +00:00
# put found data into stores logically in front of the current store
2022-09-19 23:13:34 +00:00
for s in self.stores:
if s == store: break
if(
2022-09-20 04:31:24 +00:00
let res = (await s.put(key, bytes));
res.isErr):
2022-09-19 23:13:34 +00:00
return failure res.error
2022-05-11 15:50:05 +00:00
2022-09-19 23:13:34 +00:00
return success bytes
2022-05-11 15:50:05 +00:00
method put*(
self: TieredDatastore,
key: Key,
2022-12-02 22:25:44 +00:00
data: seq[byte]): Future[?!void] {.async.} =
2022-05-11 15:50:05 +00:00
let
pending = await allFinished(self.stores.mapIt(it.put(key, data)))
for fut in pending:
if fut.read().isErr: return fut.read()
2022-05-11 15:50:05 +00:00
return success()
2022-05-11 15:50:05 +00:00
method put*(
self: TieredDatastore,
2022-12-02 22:25:44 +00:00
batch: seq[BatchEntry]): Future[?!void] {.async.} =
for entry in batch:
let
pending = await allFinished(self.stores.mapIt(it.put(entry.key, entry.data)))
for fut in pending:
if fut.read().isErr: return fut.read()
return success()
method modifyGet*(
self: TieredDatastore,
key: Key,
fn: ModifyGet): Future[?!seq[byte]] {.async.} =
let
pending = await allFinished(self.stores.mapIt(it.modifyGet(key, fn)))
var aux = newSeq[byte]()
for fut in pending:
if fut.read().isErr:
return fut.read()
else:
aux.add(fut.read().get)
return success(aux)
method modify*(
self: TieredDatastore,
key: Key,
fn: Modify): Future[?!void] {.async.} =
let
pending = await allFinished(self.stores.mapIt(it.modify(key, fn)))
for fut in pending:
if fut.read().isErr: return fut.read()
return success()
2022-05-11 15:50:05 +00:00
# method query*(
# self: TieredDatastore,
2022-12-02 22:25:44 +00:00
# query: ...): Future[?!(?...)] {.async.} =
2022-05-11 15:50:05 +00:00
#
# return success ....some