Implement Database.(read|write)() to reduce duplication and allow caching later
authorNick Downing <nick@ndcode.org>
Thu, 6 Jan 2022 08:32:13 +0000 (19:32 +1100)
committerNick Downing <nick@ndcode.org>
Thu, 6 Jan 2022 08:47:41 +0000 (19:47 +1100)
logjson.mjs

index aaf1726..bc5c971 100644 (file)
@@ -128,6 +128,46 @@ class Database {
     throw new Error('can\'t find logjson end marker')
   }
 
+  async read(ptr, len) {
+    let buffer = Buffer.alloc(len)
+    assert(
+      (await this.log.read(buffer, 0, len, ptr)).bytesRead === len
+    )
+    return JSON.parse(buffer.toString('utf-8'))
+  }
+
+  async write(value) {
+    let buffer = Buffer.from(
+      JSON.stringify(value, null, 2) + '\n',
+      'utf-8'
+    )
+
+    let ptr = this.eof
+    let len = buffer.length
+    assert(
+      (await this.log.write(buffer, 0, len, ptr)).bytesWritten === len
+    )
+    this.eof += len
+
+    return [ptr, len - 1]
+  }
+
+  async write_root(value) {
+    let buffer = Buffer.from(
+      `<${JSON.stringify(value, null, 2)}>\n`,
+      'utf-8'
+    )
+
+    let ptr = this.eof
+    let len = buffer.length
+    assert(
+      (await this.log.write(buffer, 0, len, ptr)).bytesWritten === len
+    )
+    this.eof += len
+
+    return [ptr + 1, len - 3]
+  }
+
   Transaction() {
     this.mutex.acquire()
     return new Transaction(this, this.value)
@@ -136,6 +176,7 @@ class Database {
 
 class Transaction {
   constructor(database, value) {
+    assert(database instanceof Database)
     this.database = database
     this.dirty = false
     this.value = value
@@ -152,11 +193,7 @@ class Transaction {
     if (value instanceof Array) {
       let [ptr, len, new_value] = value
       if (new_value === undefined) {
-        let buffer = Buffer.alloc(len)
-        assert(
-          (await this.database.log.read(buffer, 0, len, ptr)).bytesRead === len
-        )
-        new_value = JSON.parse(buffer.toString('utf-8'))
+        new_value = await this.database.read(ptr, len)
         if (typeof new_value === 'object' && new_value !== null)
           new_value =
             new_value instanceof Array ?
@@ -191,34 +228,11 @@ class Transaction {
       if ((value instanceof Lazy && await value.flush()) || ptr === -1) {
         if (value instanceof Lazy)
           value = value.pack()
-        let buffer = Buffer.from(
-          `<${JSON.stringify(value, null, 2)}>\n`,
-          'utf-8'
-        )
-
-        ptr = this.database.eof
-        len = buffer.length
-        assert(
-          (await this.database.log.write(buffer, 0, len, ptr)).bytesWritten === len
-        )
-        this.database.eof += len
-  
-        this.database.value = [ptr + 1, len - 3]
+        this.database.value = await this.database.write_root(value)
       }
     }
     else if (this.dirty) {
-      let buffer = Buffer.from(
-        `<${JSON.stringify(this.value, null, 2)}>\n`,
-        'utf-8'
-      )
-
-      ptr = this.database.eof
-      len = buffer.length
-      assert(
-        (await this.database.log.write(buffer, 0, len, ptr)).bytesWritten === len
-      )
-      this.database.eof += len
-
+      await this.database.write_root(value)
       this.database.value = this.value
     }
 
@@ -259,6 +273,7 @@ class Transaction {
 // logjson array or object
 class Lazy {
   constructor(transaction) {
+    assert(transaction instanceof Transaction)
     this.transaction = transaction
     this.dirty = false
   }
@@ -312,11 +327,7 @@ class LazyArray extends Lazy {
     if (value instanceof Array) {
       let [ptr, len, new_value] = value
       if (new_value === undefined) {
-        let buffer = Buffer.alloc(len)
-        assert(
-          (await this.transaction.database.log.read(buffer, 0, len, ptr)).bytesRead === len
-        )
-        new_value = JSON.parse(buffer.toString('utf-8'))
+        new_value = await this.transaction.database.read(ptr, len)
         if (typeof new_value === 'object' && new_value !== null)
           new_value =
             new_value instanceof Array ?
@@ -370,21 +381,10 @@ class LazyArray extends Lazy {
         if ((value instanceof Lazy && await value.flush()) || ptr === -1) {
           if (value instanceof Lazy)
             value = value.pack()
-          let buffer = Buffer.from(
-            JSON.stringify(value, null, 2) + '\n',
-            'utf-8'
-          )
-
-          ptr = this.transaction.database.eof
-          len = buffer.length
-          assert(
-            (await this.transaction.database.log.write(buffer, 0, len, ptr)).bytesWritten ===
-              len
-          )
-          this.transaction.database.eof += len
+          let [ptr, len] = await this.transaction.database.write(value)
 
           item[0] = ptr
-          item[1] = len - 1
+          item[1] = len
           this.dirty = true
         }
       }
@@ -429,11 +429,7 @@ class LazyObject extends Lazy {
     if (value instanceof Array) {
       let [ptr, len, new_value] = value
       if (new_value === undefined) {
-        let buffer = Buffer.alloc(len)
-        assert(
-          (await this.transaction.database.log.read(buffer, 0, len, ptr)).bytesRead === len
-        )
-        new_value = JSON.parse(buffer.toString('utf-8'))
+        new_value = await this.transaction.database.read(ptr, len)
         if (typeof new_value === 'object' && new_value !== null)
           new_value =
             new_value instanceof Array ?
@@ -480,18 +476,7 @@ class LazyObject extends Lazy {
         if ((value instanceof Lazy && await value.flush()) || ptr === -1) {
           if (value instanceof Lazy)
             value = value.pack()
-          let buffer = Buffer.from(
-            JSON.stringify(value, null, 2) + '\n',
-            'utf-8'
-          )
-
-          ptr = this.transaction.database.eof
-          len = buffer.length
-          assert(
-            (await this.transaction.database.log.write(buffer, 0, len, ptr)).bytesWritten ===
-              len
-          )
-          this.transaction.database.eof += len
+          let [ptr, len] = await this.transaction.database.write(value)
 
           item[0] = ptr
           item[1] = len