feat: create highlight sync manager with queue logic

Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-12 06:59:10 +00:00
parent 90208808a2
commit 409675bf73
2 changed files with 205 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
import { BibleHighlight, HighlightSyncQueueItem } from '@/types'
import {
initHighlightsDatabase,
updateHighlight,
getHighlight
} from './highlight-manager'
const SYNC_QUEUE_STORE = 'highlight_sync_queue'
export class HighlightSyncManager {
private db: IDBDatabase | null = null
private syncInterval: NodeJS.Timeout | null = null
async init() {
this.db = await initHighlightsDatabase()
// Create sync queue store if it doesn't exist
if (!this.db.objectStoreNames.contains(SYNC_QUEUE_STORE)) {
// Note: In real app, this would be done in onupgradeneeded
// For this implementation, assume schema is managed separately
}
}
async queueHighlight(highlight: BibleHighlight): Promise<void> {
if (!this.db) await this.init()
const queueItem: HighlightSyncQueueItem = {
highlightId: highlight.id,
action: highlight.syncStatus === 'synced' ? 'update' : 'create',
highlight,
retryCount: 0
}
await updateHighlight({
...highlight,
syncStatus: 'pending'
})
}
async getPendingSyncItems(): Promise<BibleHighlight[]> {
if (!this.db) await this.init()
return new Promise((resolve, reject) => {
const tx = this.db!.transaction('highlights', 'readonly')
const store = tx.objectStore('highlights')
const index = store.index('syncStatus')
const request = index.getAll('pending')
request.onsuccess = () => resolve(request.result || [])
request.onerror = () => reject(new Error('Failed to get pending items'))
})
}
async getSyncingItems(): Promise<BibleHighlight[]> {
if (!this.db) await this.init()
return new Promise((resolve, reject) => {
const tx = this.db!.transaction('highlights', 'readonly')
const store = tx.objectStore('highlights')
const index = store.index('syncStatus')
const request = index.getAll('syncing')
request.onsuccess = () => resolve(request.result || [])
request.onerror = () => reject(new Error('Failed to get syncing items'))
})
}
async markSyncing(highlightIds: string[]): Promise<void> {
if (!this.db) await this.init()
for (const id of highlightIds) {
const highlight = await getHighlight(id)
if (highlight) {
await updateHighlight({
...highlight,
syncStatus: 'syncing'
})
}
}
}
async markSynced(highlightIds: string[]): Promise<void> {
if (!this.db) await this.init()
for (const id of highlightIds) {
const highlight = await getHighlight(id)
if (highlight) {
await updateHighlight({
...highlight,
syncStatus: 'synced'
})
}
}
}
async markError(highlightIds: string[], errorMsg: string): Promise<void> {
if (!this.db) await this.init()
for (const id of highlightIds) {
const highlight = await getHighlight(id)
if (highlight) {
await updateHighlight({
...highlight,
syncStatus: 'error',
syncErrorMsg: errorMsg
})
}
}
}
startAutoSync(intervalMs: number = 30000, onSyncNeeded?: () => void) {
this.syncInterval = setInterval(async () => {
const pending = await this.getPendingSyncItems()
if (pending.length > 0 && onSyncNeeded) {
onSyncNeeded()
}
}, intervalMs)
}
stopAutoSync() {
if (this.syncInterval) {
clearInterval(this.syncInterval)
this.syncInterval = null
}
}
}