Skip to content

Commit f37b8a7

Browse files
committed
feat(offline): pause cache while syncing to prevent flickering
1 parent fcbd41e commit f37b8a7

File tree

1 file changed

+91
-82
lines changed

1 file changed

+91
-82
lines changed

packages/offline/src/plugin.ts

Lines changed: 91 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -90,98 +90,107 @@ export function createOfflinePlugin(options: CreateOfflinePluginOptions = {}) {
9090
// CRDT State Synchronization
9191

9292
hook('sync', async ({ store, setProgress, setCollectionLoaded, setCollectionSynced }) => {
93-
let completed = 0
94-
await Promise.all(store.$collections.map(async (collection) => {
95-
if (!isCollectionIncluded(collection)) {
96-
return
97-
}
93+
// Pause cache updates to prevent flickering while syncing
94+
store.$cache.pause()
95+
96+
try {
97+
let completed = 0
98+
await Promise.all(store.$collections.map(async (collection) => {
99+
if (!isCollectionIncluded(collection)) {
100+
return
101+
}
98102

99-
// Load metadata
100-
const metadataKey = getMetadataKey(collection)
101-
const metadata: OfflineCollectionMetadata | null = getLocalStorageItem(metadataKey)
103+
// Load metadata
104+
const metadataKey = getMetadataKey(collection)
105+
const metadata: OfflineCollectionMetadata | null = getLocalStorageItem(metadataKey)
102106

103-
// Get last updatedAt
104-
let lastUpdatedAtRaw = 0
105-
if (metadata) {
106-
lastUpdatedAtRaw = metadata.updatedAt
107-
}
108-
const lastUpdatedAt = new Date(lastUpdatedAtRaw)
109-
110-
// Load local items into the cache
111-
const loadedItems = await db.readAllItems(collection.name)
112-
for (const item of loadedItems) {
113-
const key = collection.getKey(item)
114-
if (key == null) {
115-
continue
107+
// Get last updatedAt
108+
let lastUpdatedAtRaw = 0
109+
if (metadata) {
110+
lastUpdatedAtRaw = metadata.updatedAt
116111
}
117-
store.$cache.writeItem({
118-
collection,
119-
item,
120-
key,
121-
})
122-
}
123-
setCollectionLoaded(collection.name)
124-
125-
// Fetch new/updated items since last sync
126-
const newItems: Array<any> = []
127-
const deleteKeys: Array<string | number> = []
128-
await store.$hooks.callHook('syncCollection', {
129-
store,
130-
meta: {},
131-
collection,
132-
lastUpdatedAt,
133-
loadedItems: () => loadedItems,
134-
storeItems: (items) => {
135-
newItems.push(...items)
136-
},
137-
deleteItems: (keys) => {
138-
deleteKeys.push(...keys)
139-
},
140-
})
141-
142-
// Cleanup deleted items
143-
for (const key of deleteKeys) {
144-
await db.deleteItem(collection.name, String(key))
145-
store.$cache.deleteItem({
112+
const lastUpdatedAt = new Date(lastUpdatedAtRaw)
113+
114+
// Load local items into the cache
115+
const loadedItems = await db.readAllItems(collection.name)
116+
for (const item of loadedItems) {
117+
const key = collection.getKey(item)
118+
if (key == null) {
119+
continue
120+
}
121+
store.$cache.writeItem({
122+
collection,
123+
item,
124+
key,
125+
})
126+
}
127+
setCollectionLoaded(collection.name)
128+
129+
// Fetch new/updated items since last sync
130+
const newItems: Array<any> = []
131+
const deleteKeys: Array<string | number> = []
132+
await store.$hooks.callHook('syncCollection', {
133+
store,
134+
meta: {},
146135
collection,
147-
key,
136+
lastUpdatedAt,
137+
loadedItems: () => loadedItems,
138+
storeItems: (items) => {
139+
newItems.push(...items)
140+
},
141+
deleteItems: (keys) => {
142+
deleteKeys.push(...keys)
143+
},
148144
})
149-
}
150145

151-
// Store new/updated items
152-
for (const item of newItems) {
153-
const key = collection.getKey(item)
154-
if (key == null) {
155-
continue
146+
// Cleanup deleted items
147+
for (const key of deleteKeys) {
148+
await db.deleteItem(collection.name, String(key))
149+
store.$cache.deleteItem({
150+
collection,
151+
key,
152+
})
153+
}
154+
155+
// Store new/updated items
156+
for (const item of newItems) {
157+
const key = collection.getKey(item)
158+
if (key == null) {
159+
continue
160+
}
161+
await db.writeItem(collection.name, String(key), item)
162+
store.$cache.writeItem({
163+
collection,
164+
item,
165+
key,
166+
})
156167
}
157-
await db.writeItem(collection.name, String(key), item)
158-
store.$cache.writeItem({
159-
collection,
160-
item,
161-
key,
162-
})
163-
}
164168

165-
setCollectionSynced(collection.name)
169+
setCollectionSynced(collection.name)
166170

167-
// Update metadata
168-
const newMetadata: OfflineCollectionMetadata = {
169-
updatedAt: Date.now(),
170-
}
171-
setLocalStorageItem(metadataKey, newMetadata)
172-
173-
completed++
174-
setProgress({
175-
percent: completed / store.$collections.length,
176-
})
177-
}))
178-
179-
// Update global metadata
180-
if (options.version) {
181-
const newGlobalMetadata: OfflineMetadata = {
182-
version: options.version,
171+
// Update metadata
172+
const newMetadata: OfflineCollectionMetadata = {
173+
updatedAt: Date.now(),
174+
}
175+
setLocalStorageItem(metadataKey, newMetadata)
176+
177+
completed++
178+
setProgress({
179+
percent: completed / store.$collections.length,
180+
})
181+
}))
182+
183+
// Update global metadata
184+
if (options.version) {
185+
const newGlobalMetadata: OfflineMetadata = {
186+
version: options.version,
187+
}
188+
setLocalStorageItem(globalMetadataKey, newGlobalMetadata)
183189
}
184-
setLocalStorageItem(globalMetadataKey, newGlobalMetadata)
190+
}
191+
finally {
192+
// Resume cache updates to apply all changes at once
193+
store.$cache.resume()
185194
}
186195
})
187196

0 commit comments

Comments
 (0)