LogoPear Docs
ReferenceBuilding blocks

Autobase

Multi-writer linearization layer for building deterministic views from many Hypercores.

stable

Autobase is a higher-level composition over underlying Hypercores. Writers append causal nodes to local cores, Autobase linearizes that graph into an eventually consistent order, and your apply handler materializes a deterministic view, often into a Hyperbee.

Install

npm i autobase

Quickstart

This minimal flow opens a view, appends one record, updates the linearizer, and reads the materialized value back from base.view.

import Corestore from 'corestore'
import Autobase from 'autobase'

const store = new Corestore('./autobase-demo')
const base = new Autobase(store, null, {
  open: (viewStore) => viewStore.get({ name: 'messages', valueEncoding: 'json' }),
  apply: async (nodes, view) => {
    for (const { value } of nodes) await view.append(value)
  }
})

await base.ready()
await base.append({ type: 'message', text: 'hello from Autobase' })
await base.update()

console.log(await base.view.get(0))
// { type: 'message', text: 'hello from Autobase' }

Autobase can reorder previously seen nodes as new causal information arrives. Keep open and apply deterministic, derive state from the provided store, and mutate only the provided view inside apply.

API Reference

Constructor and lifecycle

new Autobase(store, bootstrap, opts)

  • Signature: const base = new Autobase(store, bootstrap, opts)
  • Parameters:
    • store: the Corestore that manages Autobase system, writer, and view cores.
    • bootstrap: an existing Autobase key when reopening a base; omit it or pass null to create a new one.
    • opts: configuration for view creation and linearization.
      • open(store, host): creates the view from the passed store.
      • apply(nodes, view, host): deterministically applies linearized nodes into the view.
      • optimistic: enables optimistic appends from non-writers that are later acknowledged.
      • close(view): closes the view when Autobase closes it.
      • valueEncoding: encoding for appended values.
      • ackInterval: auto-ack interval in milliseconds.
      • encryptionKey: promise or buffer used to encrypt the base.
      • encrypt: encrypt the base if it is currently unencrypted and no key is provided.
      • encrypted: require the base to be encrypted.
      • fastForward: enable fast-forwarding to a quorum-signed state.
      • wakeup: custom wakeup protocol implementation.
      • bigBatches: enables larger apply batches.
  • Returns: a new Autobase instance.
  • Example: const base = new Autobase(store, null, { open, apply })

When optimistic is enabled, validate optimistic blocks inside apply before calling host.ackWriter(key). Otherwise any peer that can write to the underlying network path could attempt to inject values.

await base.ready()

  • Signature: await base.ready()
  • Parameters: none.
  • Returns: a promise that resolves when the base and its view are ready to use.
  • Example: await base.ready()

State and derived view

  • base.key: primary key for the Autobase. Example: const bootstrap = base.key
  • base.discoveryKey: discovery key associated with the Autobase. Example: swarm.join(base.discoveryKey)
  • base.isIndexer: true when this instance is acting as an indexer. Example: if (base.isIndexer) await base.ack()
  • base.writable: true when this instance can append as a writer. Example: if (base.writable) await base.append(value)
  • base.view: the materialized view returned by open. Example: const row = await base.view.get(0)
  • base.length: length of the Autobase system core, not the writer or view length. Example: console.log(base.length)
  • base.signedLength: highest quorum-signed system index that will not be reordered. Example: console.log(base.signedLength)
  • base.paused: whether Autobase is currently paused. Example: if (base.paused) await base.resume()

Writes and linearization

await base.append(value, opts)

  • Signature: await base.append(value, opts)
  • Parameters:
    • value: the entry to append to the local writer.
    • opts: append options.
      • optimistic: allows an optimistic append from a non-writer when the base was created with optimistic: true.
  • Returns: a promise that resolves when the append has been written locally.
  • Example: await base.append({ type: 'message', text: 'hi' })

await base.update()

  • Signature: await base.update()
  • Parameters: none.
  • Returns: a promise that resolves after Autobase fetches available data and reruns linearization.
  • Example: await base.update()

await base.ack(bg = false)

  • Signature: await base.ack(bg = false)
  • Parameters:
    • bg: when true, schedules the ack through the automatic ack timer instead of appending immediately.
  • Returns: a promise that resolves after the acknowledgement has been appended or scheduled.
  • Example: await base.ack(true)

Only indexers can acknowledge. An ack appends a null node that references the known heads so peers can converge faster without changing the view.

const heads = base.heads()

  • Signature: const heads = base.heads()
  • Parameters: none.
  • Returns: the current writer-head nodes with no causal dependents.
  • Example: const heads = base.heads()

await base.pause()

  • Signature: await base.pause()
  • Parameters: none.
  • Returns: a promise that resolves when Autobase has paused before the next apply.
  • Example: await base.pause()

await base.resume()

  • Signature: await base.resume()
  • Parameters: none.
  • Returns: a promise that resolves after Autobase resumes and checks for updates.
  • Example: await base.resume()

base.setBigBatches(enable = true)

  • Signature: base.setBigBatches(enable = true)
  • Parameters:
    • enable: whether to enable larger apply batches.
  • Returns: nothing.
  • Example: base.setBigBatches(true)

Big batches let Autobase call apply with more nodes at once, trading responsiveness for larger deterministic batches.

Replication and metadata

const hash = await base.hash()

  • Signature: const hash = await base.hash()
  • Parameters: none.
  • Returns: the hash of the system core Merkle tree roots.
  • Example: const hash = await base.hash()

const stream = base.replicate(isInitiator || stream, opts)

  • Signature: const stream = base.replicate(isInitiator || stream, opts)
  • Parameters:
    • isInitiator || stream: either an initiator boolean or an existing replication stream.
    • opts: the same replication options accepted by Corestore#replicate().
  • Returns: a replication stream for the Autobase.
  • Example: const stream = base.replicate(true)

await base.setUserData(key, value)

  • Signature: await base.setUserData(key, value)
  • Parameters:
    • key: user-data key as a string.
    • value: string or buffer value to store.
  • Returns: a promise that resolves after the value is stored.
  • Example: await base.setUserData('app', 'chat')

const value = await base.getUserData(key)

  • Signature: const value = await base.getUserData(key)
  • Parameters:
    • key: user-data key as a string.
  • Returns: the stored string or buffer value for that key.
  • Example: const appName = await base.getUserData('app')

Static helpers

const core = Autobase.getLocalCore(store, handlers, encryptionKey)

  • Signature: const core = Autobase.getLocalCore(store, handlers, encryptionKey)
  • Parameters:
    • store: the store used to create the local writer core.
    • handlers: handler options passed through to store.
    • encryptionKey: optional encryption key for the local core.
  • Returns: a local core suitable for an Autobase writer.
  • Example: const core = Autobase.getLocalCore(store, { name: 'local-writer' })

const { referrer, view } = Autobase.getUserData(core)

  • Signature: const { referrer, view } = Autobase.getUserData(core)
  • Parameters:
    • core: an Autobase-related core.
  • Returns: user-data metadata, including the Autobase referrer key and the view name.
  • Example: const meta = Autobase.getUserData(core)

const isBase = Autobase.isAutobase(core, opts)

  • Signature: const isBase = Autobase.isAutobase(core, opts)
  • Parameters:
    • core: the core to inspect.
    • opts: the same options accepted by core.get(index, opts).
  • Returns: whether the core is an Autobase core.
  • Example: const isBase = Autobase.isAutobase(core)

View store helper

const core = store.get(name || { name, valueEncoding })

  • Signature: const core = store.get(name || { name, valueEncoding })
  • Parameters:
    • name: view name as a string, or an options object with name and valueEncoding.
  • Returns: a Hypercore loaded from the Autobase view store.
  • Example: const view = store.get({ name: 'messages', valueEncoding: 'json' })

This store instance is the AutoStore passed into open, and it is the intended place to create the cores that make up your deterministic view.

Apply host calls

await host.addWriter(key, { indexer = true })

  • Signature: await host.addWriter(key, { indexer = true })
  • Parameters:
    • key: writer key to add to the Autobase.
    • indexer: when true, adds the writer as an indexer as well.
  • Returns: a promise that resolves after the writer has been added.
  • Example: await host.addWriter(newWriterKey, { indexer: true })

await host.removeWriter(key)

  • Signature: await host.removeWriter(key)
  • Parameters:
    • key: writer key to remove.
  • Returns: a promise that resolves after the writer has been removed.
  • Example: await host.removeWriter(oldWriterKey)

This throws when the writer cannot be removed, such as when it would leave the system without a removable indexer set.

await host.ackWriter(key)

  • Signature: await host.ackWriter(key)
  • Parameters:
    • key: writer key to acknowledge.
  • Returns: a promise that resolves after the writer has been acknowledged for optimistic application.
  • Example: await host.ackWriter(node.from.key)

host.interrupt(reason)

  • Signature: host.interrupt(reason)
  • Parameters:
    • reason: optional reason explaining why apply must stop.
  • Returns: nothing.
  • Example: host.interrupt('unsupported block type')

Interrupting closes the Autobase and emits the interrupt event so the application can upgrade its apply logic or recover intentionally.

host.removeable(key)

  • Signature: host.removeable(key)
  • Parameters:
    • key: writer key to inspect.
  • Returns: whether that writer can be removed.
  • Example: if (host.removeable(key)) await host.removeWriter(key)

The last indexer cannot be removed.

Events

  • base.on('update', () => {}): emitted after apply finishes and the view has updated.
  • base.on('interrupt', (reason) => {}): emitted when host.interrupt(reason) stops apply.
  • base.on('fast-forward', (to, from) => {}): emitted when Autobase fast-forwards from from to to signed length.
  • base.on('is-indexer', () => {}): emitted when this instance becomes an indexer.
  • base.on('is-non-indexer', () => {}): emitted when this instance is not an indexer.
  • base.on('writable', () => {}): emitted when this instance becomes writable.
  • base.on('unwritable', () => {}): emitted when this instance is no longer writable.
  • base.on('warning', (warning) => {}): emitted when Autobase raises a warning.
  • base.on('error', (err) => {}): emitted when updating the Autobase raises an error.

See also

  • Work with many Hypercores using Corestore — manage the groups of cores that Autobase coordinates.
  • Corestore — storage and replication manager typically used for Autobase system, writer, and view cores.
  • Hypercore — append-only log primitive that Autobase writers build on.
  • Hyperbee — common materialized-view target for deterministic indexed state.

On this page