Skip to Content
LearnArchitectureSystem Overview

System Overview

High-level architecture of Gluonic sync engine.

Three-Layer Architecture

Gluonic is organized into three distinct layers, each with clear responsibilities:

Layer 1: Data Store (Foundation)

Responsibilities:

  • Manage observable data pool
  • Coordinate server synchronization
  • Persist confirmed data locally
  • Queue and retry mutations
  • Handle network connectivity

Key Components:

  • Store - Central coordinator
  • ObjectPool - In-memory observable cache
  • StorageAdapter - Local database interface
  • MutationAdapter - Server API interface

Layer 2: Reactive Models (Abstraction)

Responsibilities:

  • Instantiate model instances from pool data
  • Provide identity mapping (same ID = same instance)
  • Enable lazy loading for relationships
  • Track optimistic updates
  • Implement field-level reactivity

Key Components:

  • Model - Base class for all models
  • IdentityMap - Identity map and cache
  • LazyReference - Lazy single relationship
  • LazyCollection - Lazy collection relationship
  • JavaScript Proxy - Transparent field access

Layer 3: React Integration (UI)

Responsibilities:

  • Integrate with React components
  • Provide hooks for data access
  • Trigger re-renders on data changes
  • Manage component lifecycle

Key Components:

  • useModel() - Get single model
  • useCollectionModels() - Get collection
  • GraphProvider - Context provider
  • observer() - MobX-React integration

Data Flow

Read Path (UI → Data)

Component calls useModel('post', '123') IdentityMap.getModel('post', '123') Check identity map cache If cached: return instance If not: instantiateModel(store, 'post', '123') Create Proxy wrapping Post instance Store in cache Return to component Component reads post.title (via Proxy GET) Proxy → store.pool.get('post', '123').p.title MobX tracks access Return value to component

Write Path (User Action → Server)

User action: store.save('post', '123', { title: 'New' }) 1. Apply optimistically to pool store.pool.upsert({ t: 'post', id: '123', p: { title: 'New' } }) 2. MobX triggers UI re-render Components update immediately ✓ 3. Queue mutation storage.enqueueTx(tx) 4. Send to server POST /sync/v1/tx 5. Server responds ├─ Success → persist + dequeue └─ Error → rollback + dequeue

Sync Path (Server → Client)

Server has new data WebSocket frame arrives OR delta sync pulls Store.applyFrames(frames) For each frame: ├─ Update pool ├─ Persist to storage └─ Invalidate cache MobX reacts to pool changes Components re-render with new data ✓

Synchronization Strategy

1. Bootstrap (Initial Load)

App starts lastSyncId = 0 Fetch all data from server Write to pool + storage Set lastSyncId

2. Delta Sync (Incremental)

Periodic or on reconnect Fetch changes since lastSyncId Apply to pool + storage Update lastSyncId

3. Queue Replay (Restore Optimistic State)

App restarts Bootstrap (load confirmed data) Replay queued transactions Apply optimistic updates to pool User sees pending edits ✓

4. Real-Time (WebSocket)

Connection established Server pushes SyncFrames Apply immediately UI updates in real-time ✓

Next Steps

Last updated on