Skip to main content

Node API

The Node class represents a single dqlite node.

Node

A dqlite node that participates in a distributed SQLite cluster.

The Node class provides a Pythonic interface to the dqlite C library, enabling you to create distributed, fault-tolerant SQLite databases with Raft consensus. Each node can act as a standalone database or join a cluster for high availability and automatic replication.

The node manages:

  • Raft consensus protocol for leader election
  • SQLite database operations with cluster-wide replication
  • Automatic failover and data consistency
  • Network communication with other cluster members

Example:

>>> # Single node
>>> node = Node("127.0.0.1:9001", "/tmp/dqlite-data")
>>> node.start()
>>> node.open_db("myapp.db")
>>> node.exec("CREATE TABLE users (id INTEGER, name TEXT)")
>>>
>>> # Cluster node
>>> node = Node(
... address="172.20.0.11:9001",
... data_dir="/data/node1",
... cluster=["172.20.0.11:9001", "172.20.0.12:9001", "172.20.0.13:9001"]
... )
>>> node.start() # Automatically joins or forms cluster

Note: Always use specific IP addresses, not 0.0.0.0, for cluster communication. The node must be started before performing database operations.

Properties

address

Get the cluster communication address for this node.

Returns: str: Address in "IP:PORT" format.

bind_address

Get the bind address if different from the cluster address.

Returns: Optional[str]: Bind address or None if using cluster address.

data_dir

Get the data directory path.

Returns: Path: Directory containing Raft logs and snapshots.

id

Get the unique identifier for this node.

Returns: int: The node's unique ID (uint64 internally).

is_running

Check if the node is currently running.

Returns: bool: True if node has been started and not stopped.

Methods

__enter__(self) -> "'Node'"

__exit__(self, exc_type: 'Optional[Type[BaseException]]', exc: 'Optional[BaseException]', tb: 'Optional[TracebackType]') -> 'None'

Context manager exit with safe cleanup.

begin(self) -> 'None'

Begin an explicit transaction.

Executes BEGIN TRANSACTION to start a transaction block. All subsequent operations will be part of this transaction until commit() or rollback() is called.

Raises: DatabaseError: If BEGIN fails

close(self) -> 'None'

Close the node and release resources.

This method ensures safe cleanup even if stop() encounters issues.

commit(self) -> 'None'

Commit the current transaction.

Executes COMMIT to commit all changes made in the current transaction.

Raises: DatabaseError: If COMMIT fails

exec(self, sql: 'str') -> 'tuple[int, int]'

Execute SQL statement that doesn't return rows (INSERT, UPDATE, DELETE, etc.).

Uses dqlite's distributed protocol to ensure the operation is replicated across all nodes in the cluster via Raft consensus.

Args: sql: SQL statement to execute

Returns: Tuple of (last_insert_id, rows_affected)

Raises: DatabaseError: If SQL execution fails

handover(self) -> 'None'

Gracefully hand over leadership to another node.

Raises: NodeNotRunningError: If node is not running NodeError: If handover fails

open_db(self, db_name: 'str' = 'db.sqlite') -> 'None'

Open a database connection using the dqlite driver.

This opens a connection that uses dqlite's Raft-based replication for all SQL operations, ensuring data is replicated across the cluster.

Args: db_name: Name of the database file (default: "db.sqlite")

Raises: NodeNotRunningError: If node is not started DatabaseError: If database fails to open

query(self, sql: 'str') -> 'list[dict[str, Any]]'

Execute SQL query that returns rows (SELECT).

Uses dqlite's distributed protocol to query data that has been replicated across the cluster.

Args: sql: SQL query to execute

Returns: List of dictionaries, one per row, with column names as keys

Raises: DatabaseError: If query execution fails

rollback(self) -> 'None'

Roll back the current transaction.

Executes ROLLBACK to undo all changes made in the current transaction.

Raises: DatabaseError: If ROLLBACK fails

start(self) -> 'None'

Start the dqlite node.

Raises: NodeAlreadyRunningError: If node is already running NodeStartError: If node fails to start

stop(self) -> 'None'

Stop the dqlite node using safe shutdown guard.

This method uses the ShutdownSafetyGuard to handle known issues like assertion failures in dqlite_node_stop.

Set DQLITEPY_BYPASS_STOP=1 to skip calling the C stop function entirely, which avoids the segfault bug at the cost of not doing graceful shutdown.

Raises: NodeStopError: If node fails to stop (only if unrecoverable)