glindex/transaction

Build and start IndexedDB transactions over one or more object stores.

All database operations run inside a transaction. Build one with prepare, register the stores you need with store, then await the Promise returned by begin. Store and index operations are then performed via the glindex/store and glindex/index modules.

Example

import gleam/javascript/promise
import glindex
import glindex/store
import glindex/transaction

pub fn get_track(db, id) {
  let tx = transaction.prepare(db, transaction.read_only)
  let #(tx, s) = transaction.store(tx, track_store())
  use tx <- promise.await(transaction.begin(tx))
  case tx {
    Ok(tx) -> store.get(tx, s, glindex.Only(id))
    Error(e) -> promise.resolve(Error(e))
  }
}

Transaction lifetime

IndexedDB auto-commits a transaction as soon as it has no pending requests and all microtasks have been processed. Do not await anything unrelated to the database inside a transaction - for example, an HTTP request or a timer. If the event loop goes idle between two database operations, the transaction will have already committed and the next operation will fail with TransactionInactiveError.

You generally do not need to call commit explicitly. Call abort to roll back all changes made in the transaction.

Types

Handle to an active transaction.

pub type Transaction(readonly, upgrade)

Builder used to declare which stores a transaction will access before it is started. Obtain one from prepare, add stores with store, then call begin to open the transaction.

pub type TransactionBuilder(readonly)

Durability hint passed to the browser when creating the transaction.

  • DurabilityDefault - let the browser choose.
  • DurabilityStrict - guarantee writes are flushed to disk before on_complete fires (slower, safer).
  • DurabilityRelaxed - allow the OS to decide when to flush (faster, risks data loss on power failure).
pub type TransactionDurability {
  DurabilityDefault
  DurabilityStrict
  DurabilityRelaxed
}

Constructors

  • DurabilityDefault
  • DurabilityStrict
  • DurabilityRelaxed

Errors returned by store and index operations.

  • ConstraintError - a uniqueness constraint was violated.
  • DataError - the key or value was invalid for the operation.
  • InvalidStateError - the transaction or store is in an unexpected state.
  • NotFoundError - no record matched the query.
  • QuotaExceededError - the browser’s storage quota has been reached.
  • TransactionInactiveError - the transaction has already committed or aborted.
  • UnableToDecode - the record was found but the decoder failed.
  • UnknownError - an unexpected browser error occurred.
pub type TransactionError {
  ConstraintError
  DataError
  InvalidStateError
  NotFoundError
  QuotaExceededError
  TransactionInactiveError
  UnableToDecode(List(decode.DecodeError))
  UnknownError(String)
}

Constructors

  • ConstraintError
  • DataError
  • InvalidStateError
  • NotFoundError
  • QuotaExceededError
  • TransactionInactiveError
  • UnableToDecode(List(decode.DecodeError))
  • UnknownError(String)

Handle to an index obtained via transaction.index.

pub type TransactionIndex(t, k, i)

The access mode of a transaction, carried as a phantom type.

Use the pre-built constants read_only and read_write instead of constructing these directly.

pub type TransactionMode(readonly) {
  TransactionReadOnly
  TransactionReadWrite
}

Constructors

  • TransactionReadOnly
  • TransactionReadWrite

Handle to an object store obtained after store is called on a builder.

The phantom type store_type must match the Store used to obtain it, preventing indexes from one store being used with another store’s handle.

pub type TransactionStore(store_type, key_mode, t, k)

Values

pub fn abort(tx: Transaction(rw, upgrade)) -> Nil

Abort the transaction, rolling back all writes made so far.

pub fn begin(
  builder: TransactionBuilder(readonly),
) -> promise.Promise(
  Result(
    Transaction(readonly, @internal Normal),
    TransactionError,
  ),
)

Start the transaction and return a Promise resolving to the active handle.

Resolves to Ok(transaction) if the transaction was opened successfully, or Error(TransactionError) if it could not be started.

pub fn commit(tx: Transaction(rw, upgrade)) -> Nil

Commit the transaction immediately without waiting for all pending requests to settle.

In most cases you do not need to call this - IndexedDB commits automatically once there are no more pending requests.

pub fn index(
  store: TransactionStore(store_type, key_mode, t, k),
  name: glindex.Index(store_type, t, k, i),
) -> TransactionIndex(t, k, i)

Obtain an index handle from a store handle.

The Index(store_type) and TransactionStore(store_type) must share the same phantom type.

pub fn on_abort(
  builder: TransactionBuilder(readonly),
  handler: fn(option.Option(String)) -> Nil,
) -> TransactionBuilder(readonly)

Register a handler called when the transaction is aborted.

The handler receives Some(error_name) if the abort was triggered by an error, or None if it was triggered by abort.

pub fn on_complete(
  builder: TransactionBuilder(readonly),
  handler: fn() -> Nil,
) -> TransactionBuilder(readonly)

Register a handler called when the transaction completes successfully.

pub fn on_error(
  builder: TransactionBuilder(readonly),
  handler: fn(String) -> Nil,
) -> TransactionBuilder(readonly)

Register a handler called when the transaction fails with an error.

The handler receives the browser error name as a string.

pub fn prepare(
  db: glindex.Database,
  mode: TransactionMode(readonly),
) -> TransactionBuilder(readonly)

Create a transaction builder for the given database and access mode.

Chain store calls to register every store you will access, then call begin to start the transaction.

pub const read_only: TransactionMode(@internal ReadOnly)

Pre-built constant for a read-only transaction.

Multiple read-only transactions can run concurrently; prefer this mode whenever you do not need to write.

pub const read_write: TransactionMode(@internal ReadWrite)

Pre-built constant for a read-write transaction.

pub fn store(
  builder: TransactionBuilder(readonly),
  store: glindex.Store(store_type, key_mode, t, k),
) -> #(
  TransactionBuilder(readonly),
  TransactionStore(store_type, key_mode, t, k),
)

Register an object store on the builder and receive a typed handle.

Returns a tuple of #(updated_builder, store_handle). Chain multiple calls to register all stores the transaction will access before calling begin.

let tx = transaction.prepare(db, transaction.read_write)
let #(tx, tracks) = transaction.store(tx, track_store())
let #(tx, artists) = transaction.store(tx, artist_store())
use tx <- promise.await(transaction.begin(tx))
pub fn with_durability(
  builder: TransactionBuilder(readonly),
  durability: TransactionDurability,
) -> TransactionBuilder(readonly)

Set the durability hint for the transaction.

Search Document