Add background sync worker and complete local-first architecture
Implements automatic background synchronization every 5 minutes: - Worker pushes pending changes to server (PushPendingChanges) - Worker pulls new pricelists (SyncPricelistsIfNeeded) - Graceful shutdown with context cancellation - Automatic online/offline detection via DB ping New files: - internal/services/sync/worker.go - Background sync worker - internal/services/local_configuration.go - Local-first CRUD - internal/localdb/converters.go - MariaDB ↔ SQLite converters Extended sync infrastructure: - Pending changes queue (pending_changes table) - Push/pull sync endpoints (/api/sync/push, /pending) - ConfigurationGetter interface for handler compatibility - LocalConfigurationService replaces ConfigurationService All configuration operations now run through SQLite with automatic background sync to MariaDB when online. Phase 2.5 nearly complete. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
41
CLAUDE.md
41
CLAUDE.md
@@ -9,26 +9,33 @@
|
||||
### Phase 2: Local SQLite Database ✅ DONE
|
||||
|
||||
### Phase 2.5: Full Offline Mode 🔶 IN PROGRESS
|
||||
Приложение должно полностью работать без MariaDB, синхронизация при восстановлении связи.
|
||||
**Local-first architecture:** приложение ВСЕГДА работает с SQLite, MariaDB только для синхронизации.
|
||||
|
||||
**Architecture:**
|
||||
- Dual-source pattern: все операции идут через unified service layer
|
||||
- Online: read/write MariaDB, async cache to SQLite
|
||||
- Offline: read/write SQLite, queue changes for sync
|
||||
**Принцип работы:**
|
||||
- ВСЕ операции (CRUD) выполняются в SQLite
|
||||
- При создании конфигурации:
|
||||
1. Если online → проверить новые прайслисты на сервере → скачать если есть
|
||||
2. Далее работаем с local_pricelists (и online, и offline одинаково)
|
||||
- Background sync: push pending_changes → pull updates
|
||||
|
||||
**DONE:**
|
||||
- ✅ Sync queue table (pending_changes) - `internal/localdb/models.go`
|
||||
- ✅ Model converters: MariaDB ↔ SQLite - `internal/localdb/converters.go`
|
||||
- ✅ LocalConfigurationService: все CRUD через SQLite - `internal/services/local_configuration.go`
|
||||
- ✅ Pre-create pricelist check: `SyncPricelistsIfNeeded()` - `internal/services/sync/service.go`
|
||||
- ✅ Push pending changes: `PushPendingChanges()` - sync service + handlers
|
||||
- ✅ Sync API endpoints: `/api/sync/push`, `/pending/count`, `/pending`
|
||||
- ✅ Integrate LocalConfigurationService in main.go (replace ConfigurationService)
|
||||
- ✅ Add routes for new sync endpoints (`/api/sync/push`, `/pending/count`, `/pending`)
|
||||
- ✅ ConfigurationGetter interface for handler compatibility
|
||||
- ✅ Background sync worker: auto-sync every 5min (push + pull) - `internal/services/sync/worker.go`
|
||||
|
||||
**TODO:**
|
||||
- ❌ Unified repository interface (online/offline transparent switching)
|
||||
- ❌ Sync queue table (pending_changes: entity_type, entity_uuid, operation, payload, created_at)
|
||||
- ❌ Background sync worker (push local changes when online)
|
||||
- ❌ Conflict resolution (last-write-wins by updated_at, or manual)
|
||||
- ❌ Initial data bootstrap (first sync downloads all needed data)
|
||||
- ❌ Handlers use context.IsOffline to choose data source
|
||||
- ❌ UI: pending changes counter, manual sync button, conflict alerts
|
||||
|
||||
**Sync flow:**
|
||||
1. Online → Offline: continue work, changes saved locally with sync_status='pending'
|
||||
2. Offline → Online: background worker pushes pending_changes, pulls updates
|
||||
3. Conflict: if server version newer, mark as 'conflict' for manual resolution
|
||||
- ❌ Conflict resolution (last-write-wins or manual)
|
||||
- ❌ UI: pending counter in header
|
||||
- ❌ UI: manual sync button
|
||||
- ❌ UI: offline indicator (middleware already exists)
|
||||
- ❌ RefreshPrices for local mode (via local_components)
|
||||
|
||||
### Phase 3: Projects and Specifications
|
||||
- qt_projects, qt_specifications tables (MariaDB)
|
||||
|
||||
Reference in New Issue
Block a user