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)