OverviewFilesCommitsIssuesDocsReleasesPeers

autobase-doctor / node_modules / autobase / lib / append-batch.js

52 lines · javascript ref:
const SignalPromise = require('signal-promise')

module.exports = class AppendBatch {
  constructor(base) {
    this.base = base
    this.blocks = []
    this.closed = false
    this.flushing = false
    this._flushed = null
  }

  async _acquire() {
    while (this.base.activeBatch !== null && this.base.activeBatch !== this)
      await this.base.activeBatch.flushed()
    this.base.activeBatch = this
  }

  async append(value) {
    if (this.base.opened === false) await this.base.ready()
    if (this.base._advancing !== null) await this.base._advancing

    if (this.closed) throw new Error('Batch is closed')
    if (this.base.activeBatch !== this) await this._acquire()
    if (this.closed) throw new Error('Batch is closed')

    this.blocks.push(value)
    return this.base.local.length + this.blocks.length
  }

  async flush() {
    if (this.closed) throw new Error('Batch is closed')
    if (this.flushing) return this.flushed()
    this.flushing = true
    if (this.blocks.length) await this.base._appendBatch(this.blocks)
    return this.close()
  }

  flushed() {
    if (this.closed) return Promise.resolve()
    if (this._flushed) return this._flushed.wait()
    this._flushed = new SignalPromise()
    return this._flushed.wait()
  }

  close() {
    if (this.base.activeBatch !== this) return
    this.base.activeBatch = null
    this.closed = true
    if (this._flushed) this._flushed.notify(null)
  }
}