Universal SQLite Synchronization Core - A dependency-grade, local-first, offline-first SQLite synchronization primitive
Project description
Universal SQLite Synchronization Core
A product of VisionQuantech, India ๐ฎ๐ณ
A dependency-grade, local-first, offline-first SQLite synchronization primitive.
Captures database changes as structured operations, packages them into self-contained bundles, and applies them deterministically across disconnected devices.
Features
- ๐ Append-only log โ Operations are immutable history
- ๐ Vector clocks โ Causality tracking across devices
- โ๏ธ Conflict detection โ Never auto-merges, preserves conflicts
- ๐ Deterministic replay โ Same operations = same result everywhere
- ๐ฆ Transport agnostic โ Bundles work over USB, email, Bluetooth, anything
- ๐ซ Zero infrastructure โ No servers, no cloud, no network required
Installation
From PyPI
pip install sqlite-sync-core
From GitHub (Development)
git clone https://github.com/shivay00001/sqlite-sync-core.git
cd sqlite-sync-core
pip install -e .
Real-Time Network Sync
SQLite Sync Core now supports real-time synchronization over WebSockets.
Start the Reference Server
python -m sqlite_sync.network.server
Connect a Client
from sqlite_sync import SyncEngine
from sqlite_sync.network.client import SyncClient
engine = SyncEngine("my_app.db")
engine.initialize()
client = SyncClient(engine, "ws://localhost:8765")
await client.connect()
# Listen for remote changes
asyncio.create_task(client.listen())
# Send local changes
ops = engine.get_new_operations()
for op in ops:
await client.send_operation(op)
Integration Examples
See the examples/ directory for full integration samples:
basic_usage.py: Simple CLI setup.network_sync.py: Real-time sync between two peers.desktop_example.py: Coming soon (GUI integration).
Requirements
- Python 3.11+
msgpack(auto-installed)
Quick Start
from sqlite_sync import SyncEngine
# Initialize sync-enabled database
engine = SyncEngine("my_database.db")
engine.initialize()
# Create a user table
engine.connection.execute("""
CREATE TABLE todos (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
done INTEGER DEFAULT 0
)
""")
# Enable sync for the table
engine.enable_sync_for_table("todos")
# Now any INSERT/UPDATE/DELETE is automatically captured!
engine.connection.execute("INSERT INTO todos (title) VALUES ('Buy milk')")
Syncing Between Devices
Device A: Generate a bundle
from sqlite_sync import SyncEngine
engine_a = SyncEngine("device_a.db")
engine_a.initialize()
# Generate bundle for Device B
bundle_path = engine_a.generate_bundle(
peer_device_id=device_b_id, # 16-byte UUID
output_path="sync_bundle.db"
)
# Send bundle_path to Device B (USB, email, cloud, etc.)
Device B: Import the bundle
engine_b = SyncEngine("device_b.db")
engine_b.initialize()
# Import received bundle
result = engine_b.import_bundle("sync_bundle.db")
print(f"Applied: {result.applied_count}")
print(f"Conflicts: {result.conflict_count}")
print(f"Duplicates: {result.duplicate_count}")
Handling Conflicts
Conflicts occur when two devices modify the same row independently.
# Get all unresolved conflicts
conflicts = engine.get_unresolved_conflicts()
for conflict in conflicts:
print(f"Table: {conflict.table_name}")
print(f"Row PK: {conflict.row_pk}")
print(f"Local op: {conflict.local_op_id.hex()}")
print(f"Remote op: {conflict.remote_op_id.hex()}")
Note: This library intentionally does NOT auto-resolve conflicts. You must implement your own resolution strategy.
Core Invariants
| # | Invariant | Description |
|---|---|---|
| 1 | Append-only | sync_operations only grows, never modified |
| 2 | Causal consistency | Vector clocks ensure happens-before |
| 3 | Deterministic ordering | Same operations always sort identically |
| 4 | Explicit conflicts | Concurrent writes preserved as records |
| 5 | Idempotent import | Same bundle ร N imports = same result |
| 6 | Transport independence | Bundles are self-contained SQLite files |
API Reference
SyncEngine
| Method | Description |
|---|---|
initialize() |
Initialize sync tables, returns device ID |
enable_sync_for_table(name) |
Install triggers for a table |
generate_bundle(peer_id, path) |
Create bundle for peer |
import_bundle(path) |
Import bundle, returns ImportResult |
get_unresolved_conflicts() |
Get all pending conflicts |
get_vector_clock() |
Get current vector clock |
close() |
Close database connection |
ImportResult
| Field | Type | Description |
|---|---|---|
bundle_id |
bytes | UUID of imported bundle |
source_device_id |
bytes | Device that created bundle |
total_operations |
int | Total ops in bundle |
applied_count |
int | Successfully applied |
conflict_count |
int | Conflicts detected |
duplicate_count |
int | Already had these ops |
skipped |
bool | True if bundle already imported |
Project Structure
sqlite_sync_core/
โโโ src/sqlite_sync/
โ โโโ engine.py # Main SyncEngine class
โ โโโ config.py # Configuration constants
โ โโโ errors.py # Exception classes
โ โโโ invariants.py # Core invariant enforcement
โ โโโ db/ # Database layer
โ โ โโโ schema.py # Table definitions
โ โ โโโ migrations.py # Initialization
โ โ โโโ triggers.py # Change capture triggers
โ โ โโโ connection.py # Connection management
โ โโโ bundle/ # Bundle operations
โ โ โโโ generate.py # Bundle creation
โ โ โโโ validate.py # Bundle validation
โ โ โโโ format.py # Bundle metadata
โ โโโ import_apply/ # Import pipeline
โ โ โโโ apply.py # Apply operations
โ โ โโโ conflict.py # Conflict detection
โ โ โโโ ordering.py # Deterministic sort
โ โ โโโ dedup.py # Deduplication
โ โโโ log/ # Operation log
โ โ โโโ operations.py # SyncOperation dataclass
โ โ โโโ vector_clock.py# Vector clock logic
โ โโโ utils/ # Utilities
โ โโโ uuid7.py # UUID v7 generation
โ โโโ hashing.py # SHA-256 utilities
โ โโโ msgpack_codec.py# Serialization
โโโ tests/ # Test suite
โโโ pyproject.toml # Package config
โโโ README.md
Running Tests
# Using the custom test runner (no pytest required)
python run_verification.py
# Or with pytest
pip install pytest
pytest tests/ -v
License
Dual License Model:
| Use Case | License | Cost |
|---|---|---|
| Personal projects | AGPL-3.0 | Free |
| Open-source projects | AGPL-3.0 | Free |
| Educational/Research | AGPL-3.0 | Free |
| Commercial / Proprietary | Commercial License | Paid |
Commercial use (closed-source, SaaS, proprietary) requires a paid license.
Contact for licensing:
See LICENSE for full terms.
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Run the test suite
- Submit a pull request
Built with โค๏ธ for offline-first applications
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sqlite_sync_core-0.1.0.tar.gz.
File metadata
- Download URL: sqlite_sync_core-0.1.0.tar.gz
- Upload date:
- Size: 45.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bccc68fc1926124ce98824b849a9a80b93c8d3bf5bdb62dd3bb058b17a83c233
|
|
| MD5 |
89ee38d0928aab83ca6d2c1fa5f19535
|
|
| BLAKE2b-256 |
71db38329e7dcf98f441d68441a2457d8b0e3263a66e25279c40667364237265
|
File details
Details for the file sqlite_sync_core-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sqlite_sync_core-0.1.0-py3-none-any.whl
- Upload date:
- Size: 47.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d6218eea5628fe2f54aefc34a7cbb2ce0f678efe46d8d95c9b1ab3ade9c1ae58
|
|
| MD5 |
03ec986a58348ada9ca78833908ff4de
|
|
| BLAKE2b-256 |
d4497de0cde538e34404c5830276a6c4c53e6b6a91151bca2859992e5e2cc554
|