changeset 989:3e0116b5d2ed

did: undo complicated background storage API, sync is good enough for now
author sam <sam@basx.dev>
date Sun, 07 Apr 2024 21:56:43 +0700
parents 46778940c1d7
children 1705e005cdee
files semicongine/storage.nim tests/test_storage.nim
diffstat 2 files changed, 12 insertions(+), 161 deletions(-) [+]
line wrap: on
line diff
--- a/semicongine/storage.nim	Sun Apr 07 20:12:52 2024 +0700
+++ b/semicongine/storage.nim	Sun Apr 07 21:56:43 2024 +0700
@@ -19,7 +19,6 @@
 
 var db: Table[StorageType, DbConn]
 
-
 proc path(storageType: StorageType): Path =
   case storageType:
     of SystemStorage:
@@ -37,115 +36,20 @@
     value TEXT NOT NULL
   )"""))
 
-proc storeInDb[T](db: DbConn, key: string, value: T) =
+proc store*[T](storageType: StorageType, key: string, value: T) =
+  storageType.setup()
   const KEY_VALUE_TABLE_NAME = "shelf"
-  db.exec(sql(&"""INSERT INTO {KEY_VALUE_TABLE_NAME} VALUES(?, ?)
+  db[storageType].exec(sql(&"""INSERT INTO {KEY_VALUE_TABLE_NAME} VALUES(?, ?)
   ON CONFLICT(key) DO UPDATE SET value=excluded.value
   """), key, $$value)
 
-proc loadFromDb[T](db: DbConn, key: string, default = default(T)): T =
+proc load*[T](storageType: StorageType, key: string, default = default(T)): T =
+  storageType.setup()
   const KEY_VALUE_TABLE_NAME = "shelf"
-  let dbResult = db.getValue(sql(&"""SELECT value FROM {KEY_VALUE_TABLE_NAME} WHERE key = ? """), key)
+  let dbResult = db[storageType].getValue(sql(&"""SELECT value FROM {KEY_VALUE_TABLE_NAME} WHERE key = ? """), key)
   if dbResult == "":
     return default
   return to[T](dbResult)
 
 proc purge*(storageType: StorageType) =
   storageType.path().string.removeFile()
-
-# mini async API
-#
-# LOADING ######################################3333
-#
-#
-type
-  LoadFuture*[T] = object
-    thread: Thread[(DbConn, string, ptr Channel[T])]
-    channel: ptr Channel[T]
-    result: T
-
-proc cleanup*[T](p: var LoadFuture[T]) =
-  if p.channel != nil:
-    p.thread.joinThread()
-    p.channel[].close()
-    deallocShared(p.channel)
-    p.channel = nil
-
-proc awaitResult*[T](p: var LoadFuture[T]): T =
-  if p.channel == nil:
-    return p.result
-  result = p.channel[].recv()
-  p.result = result
-  p.cleanup()
-
-proc hasResult*[T](p: var LoadFuture[T]): bool =
-  let ret = p.channel[].tryRecv()
-  result = ret.dataAvailable
-  if result:
-    p.result = ret.msg
-    p.cleanup()
-
-proc getResult*[T](p: LoadFuture[T]): T =
-  assert p.channel == nil, "Result is not available yet"
-  return p.result
-
-proc loadWorker[T](params: (DbConn, string, ptr Channel[T])) {.thread.} =
-  let ret = loadFromDb[T](params[0], params[1])
-  params[2][].send(ret)
-
-proc load*[T](storageType: StorageType, key: string): LoadFuture[T] =
-  storageType.setup()
-  result.channel = cast[ptr Channel[T]](allocShared0(sizeof(Channel[T])))
-  result.channel[].open()
-  createThread(result.thread, loadWorker[T], (db[storageType], key, result.channel))
-
-# STORING ######################################3333
-#
-type
-  StoreFuture*[T] = object
-    # thread: Thread[(DbConn, string, ptr Channel[T], ptr Channel[bool])]
-    thread: Thread[void]
-    channel: ptr Channel[T]
-    doneChannel: ptr Channel[bool]
-
-proc cleanup*[T](p: var StoreFuture[T]) =
-  if p.channel != nil:
-    p.thread.joinThread()
-    p.channel[].close()
-    p.doneChannel[].close()
-    deallocShared(p.channel)
-    deallocShared(p.doneChannel)
-    p.channel = nil
-    p.doneChannel = nil
-
-proc awaitStored*[T](p: var StoreFuture[T]) =
-  discard p.doneChannel[].recv()
-  p.cleanup()
-
-proc isStored*[T](p: var StoreFuture[T]): bool =
-  let ret = p.doneChannel[].tryRecv()
-  result = ret.dataAvailable
-  if ret.dataAvailable:
-    p.cleanup()
-
-# proc storeWorker[T](params: (DbConn, string, ptr Channel[T], ptr Channel[bool])) {.thread.} =
-  # storeInDb(params[0], params[1], params[2][].recv())
-  # params[3][].send(true)
-
-
-# proc store*[T](storageType: StorageType, key: string, value: T): StoreFuture[T] =
-  # storageType.setup()
-  # result.channel = cast[ptr Channel[T]](allocShared0(sizeof(Channel[T])))
-  # result.channel[].open()
-  # result.doneChannel = cast[ptr Channel[bool]](allocShared0(sizeof(Channel[bool])))
-  # result.doneChannel[].open()
-  # createThread(result.thread, storeWorker[T], (db[storageType], key, result.channel, result.doneChannel))
-  # createThread(result.thread, storeWorker)
-  # result.channel[].send(value)
-
-proc storeWorker() {.thread.} =
-  echo "storeWorker"
-
-proc store*() =
-  var thread: Thread[void]
-  createThread(thread, storeWorker)
--- a/tests/test_storage.nim	Sun Apr 07 20:12:52 2024 +0700
+++ b/tests/test_storage.nim	Sun Apr 07 21:56:43 2024 +0700
@@ -3,78 +3,31 @@
 
 import semicongine
 
-#[
 proc testSimple(storage: StorageType) =
   const TEST_VALUE = 42
   const KEY = "test"
 
   # get default
-  var future1 = load[int](storage, KEY)
-  assert future1.awaitResult() == default(type(TEST_VALUE))
+  assert load[int](storage, KEY) == default(type(TEST_VALUE))
 
   # save and load custom
-  var future2 = store(storage, KEY, TEST_VALUE)
-  future2.awaitStored()
-  future1 = load[int](storage, KEY)
-  assert future1.awaitResult() == TEST_VALUE
-
-proc testBusyWait(storage: StorageType) =
-  const TEST_VALUE = "43"
-  const KEY = "test2"
-
-  # get default
-  var future1 = load[string](storage, KEY)
-  while not future1.hasResult():
-    sleep(1)
-  assert future1.getResult() == default(type(TEST_VALUE))
-
-  # save and load custom
-  var future2 = store(storage, KEY, TEST_VALUE)
-  while not future2.isStored():
-    sleep(1)
-  future1 = load[string](storage, KEY)
-  while not future1.hasResult():
-    sleep(1)
-  assert future1.awaitResult() == TEST_VALUE
+  store(storage, KEY, TEST_VALUE)
+  assert load[int](storage, KEY) == TEST_VALUE
 
 proc stressTest(storage: StorageType) =
   for i in 1 .. 10000:
     let key = &"key-{i}"
-    var p = store(storage, key, i)
-    p.awaitStored()
-    var p1 = load[int](storage, key)
-    assert p1.awaitResult() == i
-]#
-
-proc concurrentStressTest(storage: StorageType) =
-  var storeFutures: seq[StoreFuture[int]]
+    store(storage, key, i)
+    assert load[int](storage, key) == i
 
-  for i in 1 .. 10000:
-    let key = &"key-{i}"
-    echo key
-    store()
-    # storeFutures.add store(storage, key, i)
-
-  for i in 1 .. 10000:
-    echo i
-    let key = &"key-{i}"
-    storeFutures[i - 1].awaitStored()
-    var p1 = load[int](storage, key)
-    assert p1.awaitResult() == i
-
-#[
 proc main() =
   SystemStorage.purge()
   echo "SystemStorage: Testing simple store/load"
   SystemStorage.testSimple()
-  echo "SystemStorage: Testing store/load with busy wait"
-  SystemStorage.testBusyWait()
 
   UserStorage.purge()
   echo "UserStorage: Testing simple store/load"
   UserStorage.testSimple()
-  echo "UserStorage: Testing store/load with busy wait"
-  UserStorage.testBusyWait()
 
   echo "Stress test with 10'000 saves/loads"
   SystemStorage.stressTest()
@@ -82,12 +35,6 @@
   SystemStorage.purge()
   UserStorage.purge()
 
-  # TODO: fails currently, but is likely not too important
-  # echo "Stress test with 10'000 saves/loads and a little concurrency"
-  # SystemStorage.concurrentStressTest()
-]#
 
 when isMainModule:
-  echo "Stress test with 10'000 saves/loads and a little concurrency"
-  SystemStorage.concurrentStressTest()
-  # main()
+  main()