Add read cache
authorNick Downing <nick@ndcode.org>
Fri, 7 Jan 2022 04:10:16 +0000 (15:10 +1100)
committerNick Downing <nick@ndcode.org>
Fri, 7 Jan 2022 04:28:35 +0000 (15:28 +1100)
a.mjs
logjson.mjs

diff --git a/a.mjs b/a.mjs
index bdebdf2..3b27c31 100755 (executable)
--- a/a.mjs
+++ b/a.mjs
@@ -3,8 +3,9 @@
 import logjson from './logjson.mjs'
 import fsPromises from 'fs/promises'
 
-let database = new logjson.Database()
+let database = new logjson.Database(5)
 await database.open('a.logjson')
+
 let transaction = database.Transaction()
 transaction.set(
   transaction.json_to_logjson(
@@ -12,4 +13,38 @@ transaction.set(
   )
 )
 await transaction.commit()
+
+/*let*/ transaction = database.Transaction()
+await fsPromises.writeFile(
+  'a.json',
+  Buffer.from(
+    JSON.stringify(
+      await logjson.logjson_to_json(await transaction.get()),
+      null,
+      2
+    ) + '\n',
+    'utf-8'
+  )
+)
+
+await database.kick()
+await database.kick()
+await database.kick()
+await database.kick()
+await database.kick()
+
+/*let*/ transaction = database.Transaction()
+await fsPromises.writeFile(
+  'b.json',
+  Buffer.from(
+    JSON.stringify(
+      await logjson.logjson_to_json(await transaction.get()),
+      null,
+      2
+    ) + '\n',
+    'utf-8'
+  )
+)
+transaction.rollback()
+
 await database.close()
index 63d3195..4a3d09d 100644 (file)
@@ -2,20 +2,33 @@ import assert from 'assert'
 import fsPromises from 'fs/promises'
 import Mutex from './Mutex.mjs'
 
+class CachedValue {
+  constructor(value, stale_count) {
+    this.value = value
+    this.stale_count = stale_count
+  }
+}
+
 let open_angle = Buffer.from('\n<', 'utf-8')
 let close_angle = Buffer.from('>\n', 'utf-8')
 class Database {
-  constructor() {
+  constructor(read_timeout) {
+    this.read_timeout = read_timeout || 3600
     this.mutex = new Mutex()
     this.log = null
     this.eof = 0
     this.value = undefined
+    this.read_cache = {}
   }
 
   async open(path) {
     await this.mutex.acquire()
     assert(this.log === null)
 
+    this.eof = 0
+    this.value = undefined
+    this.read_cache = {}
+
     try {
       this.log = await fsPromises.open(path, 'r+')
     }
@@ -24,10 +37,7 @@ class Database {
         throw error
 
       console.log('warning: can\'t find database file, creating')
-
       this.log = await fsPromises.open(path, 'w+')
-      this.eof = 0
-      this.value = undefined
 
       this.mutex.release()
       return
@@ -98,10 +108,7 @@ class Database {
     }
     catch (error) {
       console.log('warning: can\'t find root, truncating database file')
-
       await this.log.truncate(0)
-      this.eof = 0
-      this.value = undefined
 
       this.mutex.release()
       return
@@ -112,7 +119,6 @@ class Database {
     // optional: trim any garbage off the end of the database file
     if (eof < this.eof) {
       console.log('warning: garbage after root, truncating database file')
-
       await this.log.truncate(eof)
       this.eof = eof
     }
@@ -133,11 +139,24 @@ class Database {
   async read(ptr_len) {
     let [ptr, len] = ptr_len
 
+    if (Object.prototype.hasOwnProperty.call(this.read_cache, ptr)) {
+      //console.log('hit', ptr)
+      let cached_value = this.read_cache[ptr]
+      cached_value.stale_count = this.read_timeout
+      return cached_value.value
+    }
+
     let buffer = Buffer.alloc(len)
     assert(
       (await this.log.read(buffer, 0, len, ptr)).bytesRead === len
     )
-    return JSON.parse(buffer.toString('utf-8'))
+    let value = JSON.parse(buffer.toString('utf-8'))
+
+    if (this.read_timeout) //{
+      //console.log('add', ptr)
+      this.read_cache[ptr] = new CachedValue(value, this.read_timeout)
+    //}
+    return value
   }
 
   async write(value) {
@@ -148,6 +167,13 @@ class Database {
 
     let ptr = this.eof
     let len = buffer.length
+
+    if (this.read_timeout) {
+      //console.log('addw', ptr)
+      assert(!Object.prototype.hasOwnProperty.call(this.read_cache, ptr))
+      this.read_cache[ptr] = new CachedValue(value, this.read_timeout)
+    }
+
     assert(
       (await this.log.write(buffer, 0, len, ptr)).bytesWritten === len
     )
@@ -176,6 +202,16 @@ class Database {
     this.mutex.acquire()
     return new Transaction(this, this.value)
   }
+
+  async kick() {
+    for (let i in this.read_cache) {
+      let cached_value = this.read_cache[i]
+      if (--cached_value.stale_count === 0) //{
+        //console.log('stale', i)
+        delete this.read_cache[i]
+      //}
+    }
+  }
 }
 
 class Transaction {