Skip to main content

Offline-first sync primitives for FastAPI and MongoDB applications.

Project description

fastapi-offline-sync

fastapi-offline-sync is a robust, production-ready offline-first sync layer for FastAPI applications backed by MongoDB. It provides high-performance synchronization endpoints and live WebSocket updates with built-in conflict resolution, multi-worker safety, and atomic transactions.

Features

  • Incremental Pull: Efficient retrieval of incremental data changes using Hybrid Logical Clocks (HLC).
  • Atomic Push Batches: Safely apply client mutations in atomic MongoDB transactions, preventing partial state corruption.
  • WebSocket Streaming: Live Change Stream propagation for real-time document updates.
  • Distributed Multi-Worker Safety: Custom HLC node namespaces derived automatically or configured via container metadata to eliminate collision risks.
  • Soft-Delete Propagation: Seamless tombstones on full resyncs to clear obsolete client-side records.

Installation

pip install fastapi-offline-sync

Quick Start

Initialize and mount the router with production configurations:

import os
from fastapi import FastAPI
from fastapi_offline_sync import SyncConfig, SyncRouter

app = FastAPI(title="Production Sync Service")

config = SyncConfig(
    mongodb_uri=os.environ["MONGODB_URI"],
    database_name=os.environ["MONGODB_DATABASE"],
    collections=("tasks", "inventory_items"),
    # Set unique HLC node ID (e.g., container hostname / Pod IP) for multi-worker safety
    hlc_node_id=os.environ.get("HOSTNAME"),
)

app.include_router(SyncRouter(config))

Authentication & Identity Resolution

Configure a JWT dependency to verify credentials and return authenticated user properties.

from fastapi import Header, HTTPException, status

async def verify_jwt(
    authorization: str | None = Header(default=None),
) -> dict[str, str]:
    if not authorization or not authorization.startswith("Bearer "):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Missing or invalid authentication header",
        )
    
    token = authorization.removeprefix("Bearer ")
    # Decode and verify the JWT with your auth provider
    # Extract identity fields:
    return {
        "user_id": "user-unique-identifier",
        "business_id": "business-tenant-identifier"
    }

Then register the dependency with SyncConfig:

config = SyncConfig(
    mongodb_uri=os.environ["MONGODB_URI"],
    database_name=os.environ["MONGODB_DATABASE"],
    collections=("tasks",),
    jwt_dependency=verify_jwt,
)

Fisco Integration

For Fisco-style backends where data is scoped by business/tenant rather than individual user, configure the sync engine to scope operations by business_id while keeping the acting identity as user_id.

from fastapi_offline_sync import SyncConfig, SyncRouter, SyncService

config = SyncConfig(
    mongodb_uri=os.environ["MONGODB_URI"],
    database_name="Fisco",
    collections=(
        "inventory_items",
        "categories",
        "orders",
        "customers",
        "sales",
    ),
    actor_id_field="user_id",
    scope_id_field="business_id",
    jwt_dependency=verify_jwt,
)

router = SyncRouter(config)
sync_service = SyncService(config)

Server-Layer Writes

For existing service-layer database writes, ensure that you append HLC metadata and oplog entries in the same session:

  1. Retrieve sync metadata with sync_service.build_sync_metadata(actor=user, scope_id=business_id).
  2. Persist the metadata fields _sync_version, _sync_actor_id, _sync_scope_id, and _sync_deleted with the document.
  3. Record the change using sync_service.record_server_change(...).

Deploying to Production

Run the application using a production-grade ASGI server:

uvicorn examples.app:app --host 0.0.0.0 --port 8000 --workers 4

API Reference

1. Push Client Changes (POST /sync/push)

Pushes client-side mutations to the server.

curl -X POST https://api.yourservice.com/sync/push \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <JWT_TOKEN>' \
  -d '{
    "client_id": "device-client-uuid",
    "changes": [
      {
        "collection": "tasks",
        "operation": "upsert",
        "doc_id": "task-abc-123",
        "data": {"title": "Acquire inventory", "done": false},
        "parent_version": "20260502T120000.000Z-0001-a1b2"
      }
    ]
  }'

2. Incremental Pull (GET /sync/pull)

Fetches operations since a specific HLC token.

curl -H 'Authorization: Bearer <JWT_TOKEN>' \
  'https://api.yourservice.com/sync/pull?since=20260502T120000.000Z-0001-a1b2&collections=tasks&limit=100'

3. Full Resync (GET /sync/full)

Triggers a complete sync with Gzip compression and tombstones for soft-deleted documents.

curl -H 'Authorization: Bearer <JWT_TOKEN>' \
  --compressed \
  'https://api.yourservice.com/sync/full?collections=tasks&limit=1000'

4. Live Updates WebSocket (WS /sync/stream)

Subscribes to live database modifications via a persistent WebSocket connection.

{
  "type": "subscribe",
  "since": "20260502T120000.000Z-0001-a1b2",
  "collections": ["tasks"],
  "token": "<JWT_TOKEN>"
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi_offline_sync-0.1.2.tar.gz (35.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapi_offline_sync-0.1.2-py3-none-any.whl (21.6 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_offline_sync-0.1.2.tar.gz.

File metadata

  • Download URL: fastapi_offline_sync-0.1.2.tar.gz
  • Upload date:
  • Size: 35.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for fastapi_offline_sync-0.1.2.tar.gz
Algorithm Hash digest
SHA256 eabe67e9c53ea2c792764bfb6b3e9bf9c096efe4053f8ae5929441b348a7e43a
MD5 4351023d235bad5774f6a2b924256a34
BLAKE2b-256 ee95f30f50f5e49069e6940c9b32e1ec980c42475a0834c26add487c09ccfe17

See more details on using hashes here.

File details

Details for the file fastapi_offline_sync-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for fastapi_offline_sync-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 96ef0affc58a257161ef0f21a6180ffd7d1b1e5690efd9776701c8ee40c8968e
MD5 954e945aa3d371a373d2f739439303ca
BLAKE2b-256 f7c260c2ad13dc435c8e77f6892495bba3fcddce4ff638a1642af60f57a538af

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page