Skip to content

VSKI v0.6.6

Replicas can now identify themselves with a unique ID and public URL, enabling proper routing by load balancer and workflow executors.

  1. Replica Identification: Replicas send X-Replica-Id and X-Replica-Public-Url headers to master during sync
  2. Master Tracking: Master stores known replicas in _known_replicas table with their public URLs
  3. Response Headers: Replicas include X-Replica-Id header in all response
  4. Client SDK: Client automatically captures X-Replica-Id from responses and includes it in subsequent request
  5. Workflow Routing: Workers can specify replicaId when subscribing to workflows to route job to specific replicas

Replicas now use SQLite changesets for incremental synchronization instead of full database downloads, dramatically reducing sync time and bandwidth.

  1. Initial Sync: Fresh replicas download the full database from master
  2. Session Reset: After full download, replica resets master’s session to ensure clean changeset tracking
  3. Schema Comparison: Replicas compute and compare schema hashes with master before attempting incremental sync
  4. Schema Migration: If schemas differ, replica fetches master schema and applies migrations (CREATE TABLE, ALTER TABLE, indexes, triggers, views)
  5. Changeset Application: After schema sync, replicas apply changesets for data changes (INSERT, UPDATE, DELETE)
  6. Automatic Fallback: If replica has no replication state, it downloads full database

When schema changes are detected (new collections, field changes, indexes), replicas automatically migrate their schema:

  1. Hash-Based Detection: Schema hashes are computed from sqlite_master (tables, indexes, triggers, views)
  2. Schema Fetch: Replica fetches full schema from master via /api/replica/schema-sync
  3. Diff Computation: Replica computes schema diff (new tables, altered tables, new/dropped indexes, triggers, views)
  4. Migration Application: Replica applies schema migrations:
    • CREATE TABLE for new collections
    • ALTER TABLE ADD COLUMN for new fields (columns are never deleted or renamed)
    • CREATE INDEX, CREATE TRIGGER, CREATE VIEW for new objects
    • DROP INDEX, DROP TRIGGER, DROP VIEW for removed objects
    • Tables are never dropped on replica
Terminal window
# Replica server configuration
REPLICA_MODE=replica
REPLICA_ID=my-replica-001 # Unique identifier for this replica
PUBLIC_URL=https://replica.example.com # Public URL for routing
MASTER_URL=https://master.example.com
SYNC_INTERVAL=60
EndpointDescription
GET /api/admin/known-replicasList all known replicas that have synced with master
GET /api/admin/known-replicas?with_public_url=trueFilter replicas by presence of public URL
// Health check endpoint
const isHealthy = await client.health();
// Get list of known replicas from master
const replicas = await client.replicas.listKnown();
// Filter by those with public URLs
const publicReplicas = await client.replicas.listKnown({ withPublicUrl: true });
// Client automatically captures replicaId from responses
const records = await client.collection('posts').getList(1, 10);
console.log(client.replicaId); // Set from X-Replica-Id header
// Route workflow to specific replica
await client.workflow.start('my-workflow', { arg1: 'value' }, { replicaId: 'replica-001' });
  • Connection modal displays known replicas with their IDs for allowing quick switching between master and replica servers
  • Health check endpoint used for connectivity verification
VariableDefaultDescription
REPLICA_ID(none)Unique identifier for this replica instance
PUBLIC_URL(none)Public URL for routing requests to this replica
EndpointMethodDescription
/api/replica/schema-syncGETGet full schema from master for migration (internal)
/api/replica/reset-sessionPOSTReset master’s SQLite session after full download (internal)
  • internal/replica/syncer.go - Incremental sync logic, schema comparison and migration, hash-based change detection
  • internal/replica/session_manager.go - Session management, ResetSession() method, schema hash computation, GetFullSchema()
  • internal/api/replica.go - ResetSession endpoint, SchemaSync endpoint, changeset generation
  • internal/config/config.go - Added ReplicaID and PublicURL config fields
  • internal/replica/middleware.go - Added X-Replica-Id to ReplicaStatusMiddleware
  • internal/replica/types.go - Added KnownReplica struct
  • internal/replica/registry.go - Added UpsertKnownReplica, ListKnownReplicas with filter
  • internal/db/db.go - Added _known_replicas table schema
  • internal/app/bootstrap.go - Pass cfg.ReplicaID to syncer and middleware
  • client/src/client.ts - Added replicaId property, health() method, capture from response headers
  • client/src/types.ts - Added replicaId to WorkflowOptions
  • client/src/api/replicas.ts - New namespace for known replicas management
  • web/lib/sdk.tsx - Use /health endpoint for connectivity check
  • web/components/layout/ConnectionBadge.tsx - Display known replicas in server list

None

No migration required. The _known_replicas table is created automatically on startup.