async-storage-sync 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -8
- package/dist/index.d.mts +22 -3
- package/dist/index.d.ts +22 -3
- package/dist/index.js +118 -12
- package/dist/index.mjs +118 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,8 +48,9 @@ await store.save('forms', {
|
|
|
48
48
|
timestamp: new Date().toISOString()
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
-
// Sync
|
|
52
|
-
await store.
|
|
51
|
+
// Sync and get summary result
|
|
52
|
+
const result = await store.flushWithResult();
|
|
53
|
+
console.log(`Synced: ${result.synced}, Failed: ${result.failed}, Remaining: ${result.remainingPending}`);
|
|
53
54
|
|
|
54
55
|
// List pending records
|
|
55
56
|
const pending = await store.getAll('forms');
|
|
@@ -62,8 +63,8 @@ console.log(`${pending.length} forms waiting to sync`);
|
|
|
62
63
|
- `autoSync: true` also listens for reconnect events and retries pending items automatically.
|
|
63
64
|
- `autoSync: false`: no automatic syncing; call sync methods manually when you choose.
|
|
64
65
|
- Manual methods:
|
|
65
|
-
- `store.
|
|
66
|
-
- `store.
|
|
66
|
+
- `store.flushWithResult()` → sync all pending and return summary counts
|
|
67
|
+
- `store.syncWithResult(collection)` → sync one collection and return summary counts
|
|
67
68
|
- `store.syncById(collection, id)` → sync one record
|
|
68
69
|
- Sync destination is controlled by your config: `serverUrl + endpoint`.
|
|
69
70
|
|
|
@@ -86,8 +87,8 @@ console.log(`${pending.length} forms waiting to sync`);
|
|
|
86
87
|
| `store.getById(collection, id)` | Get one record by internal `_id` |
|
|
87
88
|
| `store.deleteById(collection, id)` | Delete one record by internal `_id` |
|
|
88
89
|
| `store.deleteCollection(collection)` | Delete all records in one collection |
|
|
89
|
-
| `store.
|
|
90
|
-
| `store.
|
|
90
|
+
| `store.flushWithResult()` | Sync all pending and return detailed summary (`attempted`, `synced`, `failed`, `retried`, `remainingPending`, `items`) |
|
|
91
|
+
| `store.syncWithResult(collection)` | Sync collection and return detailed summary (same format as `flushWithResult()`) |
|
|
91
92
|
| `store.syncById(collection, id)` | Sync one specific record by internal `_id` |
|
|
92
93
|
| `store.requeueFailed()` | Move `failed` records back to pending queue for retry |
|
|
93
94
|
| `store.onSynced(callback)` | Event callback for successful sync of each item |
|
|
@@ -105,7 +106,7 @@ import { getSyncQueue } from 'async-storage-sync';
|
|
|
105
106
|
|
|
106
107
|
NetInfo.addEventListener(state => {
|
|
107
108
|
if (state.isConnected) {
|
|
108
|
-
void getSyncQueue().
|
|
109
|
+
void getSyncQueue().flushWithResult();
|
|
109
110
|
}
|
|
110
111
|
});
|
|
111
112
|
```
|
|
@@ -190,7 +191,7 @@ Notes:
|
|
|
190
191
|
|
|
191
192
|
1. **Save** — Records written to AsyncStorage immediately
|
|
192
193
|
2. **Queue** — Each save queued for syncing
|
|
193
|
-
3. **Sync** — `
|
|
194
|
+
3. **Sync** — `flushWithResult()` POSTs all pending to your server and returns summary output
|
|
194
195
|
4. **Status** — Records marked synced, then kept or deleted
|
|
195
196
|
5. **Retry** — Failed syncs retry automatically (max 5x)
|
|
196
197
|
6. **Persist** — Everything survives app restart
|
package/dist/index.d.mts
CHANGED
|
@@ -42,6 +42,25 @@ interface SaveOptions {
|
|
|
42
42
|
onSyncSuccess?: OnSyncSuccess;
|
|
43
43
|
duplicateStrategy?: DuplicateStrategy;
|
|
44
44
|
}
|
|
45
|
+
type FlushItemStatus = 'synced' | 'failed' | 'retried' | 'deferred-backoff' | 'network-error';
|
|
46
|
+
interface FlushItemResult {
|
|
47
|
+
itemId: string;
|
|
48
|
+
collection: string;
|
|
49
|
+
recordId: string;
|
|
50
|
+
status: FlushItemStatus;
|
|
51
|
+
httpStatus?: number;
|
|
52
|
+
}
|
|
53
|
+
interface FlushResult {
|
|
54
|
+
attempted: number;
|
|
55
|
+
synced: number;
|
|
56
|
+
failed: number;
|
|
57
|
+
retried: number;
|
|
58
|
+
deferred: number;
|
|
59
|
+
networkErrors: number;
|
|
60
|
+
remainingPending: number;
|
|
61
|
+
skippedAlreadyFlushing: boolean;
|
|
62
|
+
items: FlushItemResult[];
|
|
63
|
+
}
|
|
45
64
|
type SyncedCallback = (item: QueueItem) => void;
|
|
46
65
|
type AuthErrorCallback = (statusCode: number, item: QueueItem) => void;
|
|
47
66
|
type StorageFullCallback = () => void;
|
|
@@ -61,9 +80,9 @@ declare class AsyncStorageSync {
|
|
|
61
80
|
getById<T extends Record<string, unknown>>(name: string, id: string): Promise<StoredRecord<T> | null>;
|
|
62
81
|
deleteById(name: string, id: string): Promise<void>;
|
|
63
82
|
deleteCollection(name: string): Promise<void>;
|
|
64
|
-
|
|
83
|
+
syncWithResult(name: string): Promise<FlushResult>;
|
|
65
84
|
syncById(_name: string, id: string): Promise<void>;
|
|
66
|
-
|
|
85
|
+
flushWithResult(): Promise<FlushResult>;
|
|
67
86
|
/**
|
|
68
87
|
* Re-enqueue any records marked as 'failed' so they are retried on next flush.
|
|
69
88
|
* Called automatically on init to recover from previous 4xx/500 failures.
|
|
@@ -99,4 +118,4 @@ declare function getSyncQueue(): AsyncStorageSync;
|
|
|
99
118
|
*/
|
|
100
119
|
declare function setStorageDriver(storage: AsyncStorageClient): void;
|
|
101
120
|
|
|
102
|
-
export { AsyncStorageSync, type AuthErrorCallback, type DriverName, type DuplicateStrategy, type InitConfig, type OnSyncSuccess, type QueueItem, type RecordMeta, type SaveOptions, type StorageFullCallback, type StoredRecord, type SyncStatus, type SyncedCallback, getSyncQueue, initSyncQueue, setStorageDriver };
|
|
121
|
+
export { AsyncStorageSync, type AuthErrorCallback, type DriverName, type DuplicateStrategy, type FlushItemResult, type FlushItemStatus, type FlushResult, type InitConfig, type OnSyncSuccess, type QueueItem, type RecordMeta, type SaveOptions, type StorageFullCallback, type StoredRecord, type SyncStatus, type SyncedCallback, getSyncQueue, initSyncQueue, setStorageDriver };
|
package/dist/index.d.ts
CHANGED
|
@@ -42,6 +42,25 @@ interface SaveOptions {
|
|
|
42
42
|
onSyncSuccess?: OnSyncSuccess;
|
|
43
43
|
duplicateStrategy?: DuplicateStrategy;
|
|
44
44
|
}
|
|
45
|
+
type FlushItemStatus = 'synced' | 'failed' | 'retried' | 'deferred-backoff' | 'network-error';
|
|
46
|
+
interface FlushItemResult {
|
|
47
|
+
itemId: string;
|
|
48
|
+
collection: string;
|
|
49
|
+
recordId: string;
|
|
50
|
+
status: FlushItemStatus;
|
|
51
|
+
httpStatus?: number;
|
|
52
|
+
}
|
|
53
|
+
interface FlushResult {
|
|
54
|
+
attempted: number;
|
|
55
|
+
synced: number;
|
|
56
|
+
failed: number;
|
|
57
|
+
retried: number;
|
|
58
|
+
deferred: number;
|
|
59
|
+
networkErrors: number;
|
|
60
|
+
remainingPending: number;
|
|
61
|
+
skippedAlreadyFlushing: boolean;
|
|
62
|
+
items: FlushItemResult[];
|
|
63
|
+
}
|
|
45
64
|
type SyncedCallback = (item: QueueItem) => void;
|
|
46
65
|
type AuthErrorCallback = (statusCode: number, item: QueueItem) => void;
|
|
47
66
|
type StorageFullCallback = () => void;
|
|
@@ -61,9 +80,9 @@ declare class AsyncStorageSync {
|
|
|
61
80
|
getById<T extends Record<string, unknown>>(name: string, id: string): Promise<StoredRecord<T> | null>;
|
|
62
81
|
deleteById(name: string, id: string): Promise<void>;
|
|
63
82
|
deleteCollection(name: string): Promise<void>;
|
|
64
|
-
|
|
83
|
+
syncWithResult(name: string): Promise<FlushResult>;
|
|
65
84
|
syncById(_name: string, id: string): Promise<void>;
|
|
66
|
-
|
|
85
|
+
flushWithResult(): Promise<FlushResult>;
|
|
67
86
|
/**
|
|
68
87
|
* Re-enqueue any records marked as 'failed' so they are retried on next flush.
|
|
69
88
|
* Called automatically on init to recover from previous 4xx/500 failures.
|
|
@@ -99,4 +118,4 @@ declare function getSyncQueue(): AsyncStorageSync;
|
|
|
99
118
|
*/
|
|
100
119
|
declare function setStorageDriver(storage: AsyncStorageClient): void;
|
|
101
120
|
|
|
102
|
-
export { AsyncStorageSync, type AuthErrorCallback, type DriverName, type DuplicateStrategy, type InitConfig, type OnSyncSuccess, type QueueItem, type RecordMeta, type SaveOptions, type StorageFullCallback, type StoredRecord, type SyncStatus, type SyncedCallback, getSyncQueue, initSyncQueue, setStorageDriver };
|
|
121
|
+
export { AsyncStorageSync, type AuthErrorCallback, type DriverName, type DuplicateStrategy, type FlushItemResult, type FlushItemStatus, type FlushResult, type InitConfig, type OnSyncSuccess, type QueueItem, type RecordMeta, type SaveOptions, type StorageFullCallback, type StoredRecord, type SyncStatus, type SyncedCallback, getSyncQueue, initSyncQueue, setStorageDriver };
|
package/dist/index.js
CHANGED
|
@@ -221,34 +221,101 @@ var SyncEngine = class {
|
|
|
221
221
|
clearTimeout(this.debounceTimer);
|
|
222
222
|
}
|
|
223
223
|
this.debounceTimer = setTimeout(() => {
|
|
224
|
-
void this.
|
|
224
|
+
void this.flushWithResult();
|
|
225
225
|
}, DEBOUNCE_MS);
|
|
226
226
|
}
|
|
227
|
-
async
|
|
227
|
+
async flushWithResult() {
|
|
228
228
|
if (this.isFlushing) {
|
|
229
229
|
console.log("[SyncEngine] flush() skipped \u2014 already flushing");
|
|
230
|
-
return
|
|
230
|
+
return {
|
|
231
|
+
attempted: 0,
|
|
232
|
+
synced: 0,
|
|
233
|
+
failed: 0,
|
|
234
|
+
retried: 0,
|
|
235
|
+
deferred: 0,
|
|
236
|
+
networkErrors: 0,
|
|
237
|
+
remainingPending: this.queue.getPending().length,
|
|
238
|
+
skippedAlreadyFlushing: true,
|
|
239
|
+
items: []
|
|
240
|
+
};
|
|
231
241
|
}
|
|
232
242
|
this.isFlushing = true;
|
|
243
|
+
const result = {
|
|
244
|
+
attempted: 0,
|
|
245
|
+
synced: 0,
|
|
246
|
+
failed: 0,
|
|
247
|
+
retried: 0,
|
|
248
|
+
deferred: 0,
|
|
249
|
+
networkErrors: 0,
|
|
250
|
+
remainingPending: 0,
|
|
251
|
+
skippedAlreadyFlushing: false,
|
|
252
|
+
items: []
|
|
253
|
+
};
|
|
233
254
|
try {
|
|
234
255
|
const pending = this.queue.getPending();
|
|
235
256
|
console.log("[SyncEngine] flush() \u2014 pending items:", pending.length);
|
|
236
257
|
if (pending.length === 0) {
|
|
237
258
|
console.log("[SyncEngine] Nothing to sync.");
|
|
238
|
-
|
|
259
|
+
result.remainingPending = 0;
|
|
260
|
+
return result;
|
|
239
261
|
}
|
|
240
262
|
for (const item of pending) {
|
|
241
|
-
|
|
263
|
+
result.attempted += 1;
|
|
264
|
+
const itemResult = await this.syncItem(item);
|
|
265
|
+
result.items.push(itemResult);
|
|
266
|
+
if (itemResult.status === "synced") {
|
|
267
|
+
result.synced += 1;
|
|
268
|
+
} else if (itemResult.status === "failed") {
|
|
269
|
+
result.failed += 1;
|
|
270
|
+
} else if (itemResult.status === "retried") {
|
|
271
|
+
result.retried += 1;
|
|
272
|
+
} else if (itemResult.status === "deferred-backoff") {
|
|
273
|
+
result.deferred += 1;
|
|
274
|
+
} else if (itemResult.status === "network-error") {
|
|
275
|
+
result.networkErrors += 1;
|
|
276
|
+
}
|
|
242
277
|
}
|
|
278
|
+
result.remainingPending = this.queue.getPending().length;
|
|
279
|
+
return result;
|
|
243
280
|
} finally {
|
|
244
281
|
this.isFlushing = false;
|
|
245
282
|
}
|
|
246
283
|
}
|
|
247
|
-
async
|
|
284
|
+
async flushCollectionWithResult(collectionName) {
|
|
285
|
+
const result = {
|
|
286
|
+
attempted: 0,
|
|
287
|
+
synced: 0,
|
|
288
|
+
failed: 0,
|
|
289
|
+
retried: 0,
|
|
290
|
+
deferred: 0,
|
|
291
|
+
networkErrors: 0,
|
|
292
|
+
remainingPending: 0,
|
|
293
|
+
skippedAlreadyFlushing: false,
|
|
294
|
+
items: []
|
|
295
|
+
};
|
|
248
296
|
const pending = this.queue.getPendingForCollection(collectionName);
|
|
297
|
+
if (pending.length === 0) {
|
|
298
|
+
result.remainingPending = this.queue.getPendingForCollection(collectionName).length;
|
|
299
|
+
return result;
|
|
300
|
+
}
|
|
249
301
|
for (const item of pending) {
|
|
250
|
-
|
|
302
|
+
result.attempted += 1;
|
|
303
|
+
const itemResult = await this.syncItem(item);
|
|
304
|
+
result.items.push(itemResult);
|
|
305
|
+
if (itemResult.status === "synced") {
|
|
306
|
+
result.synced += 1;
|
|
307
|
+
} else if (itemResult.status === "failed") {
|
|
308
|
+
result.failed += 1;
|
|
309
|
+
} else if (itemResult.status === "retried") {
|
|
310
|
+
result.retried += 1;
|
|
311
|
+
} else if (itemResult.status === "deferred-backoff") {
|
|
312
|
+
result.deferred += 1;
|
|
313
|
+
} else if (itemResult.status === "network-error") {
|
|
314
|
+
result.networkErrors += 1;
|
|
315
|
+
}
|
|
251
316
|
}
|
|
317
|
+
result.remainingPending = this.queue.getPendingForCollection(collectionName).length;
|
|
318
|
+
return result;
|
|
252
319
|
}
|
|
253
320
|
async flushRecord(recordId) {
|
|
254
321
|
const item = this.queue.getPendingForRecord(recordId);
|
|
@@ -262,7 +329,12 @@ var SyncEngine = class {
|
|
|
262
329
|
const elapsed = Date.now() - item.ts;
|
|
263
330
|
if (elapsed < backoffMs) {
|
|
264
331
|
console.log(`[SyncEngine] syncItem backoff \u2014 retries: ${item.retries}, wait: ${backoffMs - elapsed}ms remaining`);
|
|
265
|
-
return
|
|
332
|
+
return {
|
|
333
|
+
itemId: item.id,
|
|
334
|
+
collection: item.key,
|
|
335
|
+
recordId: item.recordId,
|
|
336
|
+
status: "deferred-backoff"
|
|
337
|
+
};
|
|
266
338
|
}
|
|
267
339
|
}
|
|
268
340
|
try {
|
|
@@ -281,13 +353,47 @@ var SyncEngine = class {
|
|
|
281
353
|
console.log(`[SyncEngine] Response: ${response.status} ${response.statusText}`);
|
|
282
354
|
if (response.ok) {
|
|
283
355
|
await this.handleSuccess(item);
|
|
356
|
+
return {
|
|
357
|
+
itemId: item.id,
|
|
358
|
+
collection: item.key,
|
|
359
|
+
recordId: item.recordId,
|
|
360
|
+
status: "synced",
|
|
361
|
+
httpStatus: response.status
|
|
362
|
+
};
|
|
284
363
|
} else if (response.status >= 400 && response.status < 500) {
|
|
285
364
|
await this.handleClientError(item, response.status);
|
|
365
|
+
return {
|
|
366
|
+
itemId: item.id,
|
|
367
|
+
collection: item.key,
|
|
368
|
+
recordId: item.recordId,
|
|
369
|
+
status: "failed",
|
|
370
|
+
httpStatus: response.status
|
|
371
|
+
};
|
|
286
372
|
} else if (response.status >= 500) {
|
|
287
373
|
await this.handleServerError(item);
|
|
374
|
+
return {
|
|
375
|
+
itemId: item.id,
|
|
376
|
+
collection: item.key,
|
|
377
|
+
recordId: item.recordId,
|
|
378
|
+
status: "retried",
|
|
379
|
+
httpStatus: response.status
|
|
380
|
+
};
|
|
288
381
|
}
|
|
382
|
+
return {
|
|
383
|
+
itemId: item.id,
|
|
384
|
+
collection: item.key,
|
|
385
|
+
recordId: item.recordId,
|
|
386
|
+
status: "failed",
|
|
387
|
+
httpStatus: response.status
|
|
388
|
+
};
|
|
289
389
|
} catch (e) {
|
|
290
390
|
console.warn("[SyncEngine] \u{1F50C} Network error (offline?) \u2014 will retry on next flush:", e);
|
|
391
|
+
return {
|
|
392
|
+
itemId: item.id,
|
|
393
|
+
collection: item.key,
|
|
394
|
+
recordId: item.recordId,
|
|
395
|
+
status: "network-error"
|
|
396
|
+
};
|
|
291
397
|
}
|
|
292
398
|
}
|
|
293
399
|
async handleSuccess(item) {
|
|
@@ -480,14 +586,14 @@ var _AsyncStorageSync = class _AsyncStorageSync {
|
|
|
480
586
|
async deleteCollection(name) {
|
|
481
587
|
await this.driver.remove(collectionKey(name));
|
|
482
588
|
}
|
|
483
|
-
async
|
|
484
|
-
|
|
589
|
+
async syncWithResult(name) {
|
|
590
|
+
return this.engine.flushCollectionWithResult(name);
|
|
485
591
|
}
|
|
486
592
|
async syncById(_name, id) {
|
|
487
593
|
await this.engine.flushRecord(id);
|
|
488
594
|
}
|
|
489
|
-
async
|
|
490
|
-
|
|
595
|
+
async flushWithResult() {
|
|
596
|
+
return this.engine.flushWithResult();
|
|
491
597
|
}
|
|
492
598
|
/**
|
|
493
599
|
* Re-enqueue any records marked as 'failed' so they are retried on next flush.
|
package/dist/index.mjs
CHANGED
|
@@ -199,34 +199,101 @@ var SyncEngine = class {
|
|
|
199
199
|
clearTimeout(this.debounceTimer);
|
|
200
200
|
}
|
|
201
201
|
this.debounceTimer = setTimeout(() => {
|
|
202
|
-
void this.
|
|
202
|
+
void this.flushWithResult();
|
|
203
203
|
}, DEBOUNCE_MS);
|
|
204
204
|
}
|
|
205
|
-
async
|
|
205
|
+
async flushWithResult() {
|
|
206
206
|
if (this.isFlushing) {
|
|
207
207
|
console.log("[SyncEngine] flush() skipped \u2014 already flushing");
|
|
208
|
-
return
|
|
208
|
+
return {
|
|
209
|
+
attempted: 0,
|
|
210
|
+
synced: 0,
|
|
211
|
+
failed: 0,
|
|
212
|
+
retried: 0,
|
|
213
|
+
deferred: 0,
|
|
214
|
+
networkErrors: 0,
|
|
215
|
+
remainingPending: this.queue.getPending().length,
|
|
216
|
+
skippedAlreadyFlushing: true,
|
|
217
|
+
items: []
|
|
218
|
+
};
|
|
209
219
|
}
|
|
210
220
|
this.isFlushing = true;
|
|
221
|
+
const result = {
|
|
222
|
+
attempted: 0,
|
|
223
|
+
synced: 0,
|
|
224
|
+
failed: 0,
|
|
225
|
+
retried: 0,
|
|
226
|
+
deferred: 0,
|
|
227
|
+
networkErrors: 0,
|
|
228
|
+
remainingPending: 0,
|
|
229
|
+
skippedAlreadyFlushing: false,
|
|
230
|
+
items: []
|
|
231
|
+
};
|
|
211
232
|
try {
|
|
212
233
|
const pending = this.queue.getPending();
|
|
213
234
|
console.log("[SyncEngine] flush() \u2014 pending items:", pending.length);
|
|
214
235
|
if (pending.length === 0) {
|
|
215
236
|
console.log("[SyncEngine] Nothing to sync.");
|
|
216
|
-
|
|
237
|
+
result.remainingPending = 0;
|
|
238
|
+
return result;
|
|
217
239
|
}
|
|
218
240
|
for (const item of pending) {
|
|
219
|
-
|
|
241
|
+
result.attempted += 1;
|
|
242
|
+
const itemResult = await this.syncItem(item);
|
|
243
|
+
result.items.push(itemResult);
|
|
244
|
+
if (itemResult.status === "synced") {
|
|
245
|
+
result.synced += 1;
|
|
246
|
+
} else if (itemResult.status === "failed") {
|
|
247
|
+
result.failed += 1;
|
|
248
|
+
} else if (itemResult.status === "retried") {
|
|
249
|
+
result.retried += 1;
|
|
250
|
+
} else if (itemResult.status === "deferred-backoff") {
|
|
251
|
+
result.deferred += 1;
|
|
252
|
+
} else if (itemResult.status === "network-error") {
|
|
253
|
+
result.networkErrors += 1;
|
|
254
|
+
}
|
|
220
255
|
}
|
|
256
|
+
result.remainingPending = this.queue.getPending().length;
|
|
257
|
+
return result;
|
|
221
258
|
} finally {
|
|
222
259
|
this.isFlushing = false;
|
|
223
260
|
}
|
|
224
261
|
}
|
|
225
|
-
async
|
|
262
|
+
async flushCollectionWithResult(collectionName) {
|
|
263
|
+
const result = {
|
|
264
|
+
attempted: 0,
|
|
265
|
+
synced: 0,
|
|
266
|
+
failed: 0,
|
|
267
|
+
retried: 0,
|
|
268
|
+
deferred: 0,
|
|
269
|
+
networkErrors: 0,
|
|
270
|
+
remainingPending: 0,
|
|
271
|
+
skippedAlreadyFlushing: false,
|
|
272
|
+
items: []
|
|
273
|
+
};
|
|
226
274
|
const pending = this.queue.getPendingForCollection(collectionName);
|
|
275
|
+
if (pending.length === 0) {
|
|
276
|
+
result.remainingPending = this.queue.getPendingForCollection(collectionName).length;
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
227
279
|
for (const item of pending) {
|
|
228
|
-
|
|
280
|
+
result.attempted += 1;
|
|
281
|
+
const itemResult = await this.syncItem(item);
|
|
282
|
+
result.items.push(itemResult);
|
|
283
|
+
if (itemResult.status === "synced") {
|
|
284
|
+
result.synced += 1;
|
|
285
|
+
} else if (itemResult.status === "failed") {
|
|
286
|
+
result.failed += 1;
|
|
287
|
+
} else if (itemResult.status === "retried") {
|
|
288
|
+
result.retried += 1;
|
|
289
|
+
} else if (itemResult.status === "deferred-backoff") {
|
|
290
|
+
result.deferred += 1;
|
|
291
|
+
} else if (itemResult.status === "network-error") {
|
|
292
|
+
result.networkErrors += 1;
|
|
293
|
+
}
|
|
229
294
|
}
|
|
295
|
+
result.remainingPending = this.queue.getPendingForCollection(collectionName).length;
|
|
296
|
+
return result;
|
|
230
297
|
}
|
|
231
298
|
async flushRecord(recordId) {
|
|
232
299
|
const item = this.queue.getPendingForRecord(recordId);
|
|
@@ -240,7 +307,12 @@ var SyncEngine = class {
|
|
|
240
307
|
const elapsed = Date.now() - item.ts;
|
|
241
308
|
if (elapsed < backoffMs) {
|
|
242
309
|
console.log(`[SyncEngine] syncItem backoff \u2014 retries: ${item.retries}, wait: ${backoffMs - elapsed}ms remaining`);
|
|
243
|
-
return
|
|
310
|
+
return {
|
|
311
|
+
itemId: item.id,
|
|
312
|
+
collection: item.key,
|
|
313
|
+
recordId: item.recordId,
|
|
314
|
+
status: "deferred-backoff"
|
|
315
|
+
};
|
|
244
316
|
}
|
|
245
317
|
}
|
|
246
318
|
try {
|
|
@@ -259,13 +331,47 @@ var SyncEngine = class {
|
|
|
259
331
|
console.log(`[SyncEngine] Response: ${response.status} ${response.statusText}`);
|
|
260
332
|
if (response.ok) {
|
|
261
333
|
await this.handleSuccess(item);
|
|
334
|
+
return {
|
|
335
|
+
itemId: item.id,
|
|
336
|
+
collection: item.key,
|
|
337
|
+
recordId: item.recordId,
|
|
338
|
+
status: "synced",
|
|
339
|
+
httpStatus: response.status
|
|
340
|
+
};
|
|
262
341
|
} else if (response.status >= 400 && response.status < 500) {
|
|
263
342
|
await this.handleClientError(item, response.status);
|
|
343
|
+
return {
|
|
344
|
+
itemId: item.id,
|
|
345
|
+
collection: item.key,
|
|
346
|
+
recordId: item.recordId,
|
|
347
|
+
status: "failed",
|
|
348
|
+
httpStatus: response.status
|
|
349
|
+
};
|
|
264
350
|
} else if (response.status >= 500) {
|
|
265
351
|
await this.handleServerError(item);
|
|
352
|
+
return {
|
|
353
|
+
itemId: item.id,
|
|
354
|
+
collection: item.key,
|
|
355
|
+
recordId: item.recordId,
|
|
356
|
+
status: "retried",
|
|
357
|
+
httpStatus: response.status
|
|
358
|
+
};
|
|
266
359
|
}
|
|
360
|
+
return {
|
|
361
|
+
itemId: item.id,
|
|
362
|
+
collection: item.key,
|
|
363
|
+
recordId: item.recordId,
|
|
364
|
+
status: "failed",
|
|
365
|
+
httpStatus: response.status
|
|
366
|
+
};
|
|
267
367
|
} catch (e) {
|
|
268
368
|
console.warn("[SyncEngine] \u{1F50C} Network error (offline?) \u2014 will retry on next flush:", e);
|
|
369
|
+
return {
|
|
370
|
+
itemId: item.id,
|
|
371
|
+
collection: item.key,
|
|
372
|
+
recordId: item.recordId,
|
|
373
|
+
status: "network-error"
|
|
374
|
+
};
|
|
269
375
|
}
|
|
270
376
|
}
|
|
271
377
|
async handleSuccess(item) {
|
|
@@ -458,14 +564,14 @@ var _AsyncStorageSync = class _AsyncStorageSync {
|
|
|
458
564
|
async deleteCollection(name) {
|
|
459
565
|
await this.driver.remove(collectionKey(name));
|
|
460
566
|
}
|
|
461
|
-
async
|
|
462
|
-
|
|
567
|
+
async syncWithResult(name) {
|
|
568
|
+
return this.engine.flushCollectionWithResult(name);
|
|
463
569
|
}
|
|
464
570
|
async syncById(_name, id) {
|
|
465
571
|
await this.engine.flushRecord(id);
|
|
466
572
|
}
|
|
467
|
-
async
|
|
468
|
-
|
|
573
|
+
async flushWithResult() {
|
|
574
|
+
return this.engine.flushWithResult();
|
|
469
575
|
}
|
|
470
576
|
/**
|
|
471
577
|
* Re-enqueue any records marked as 'failed' so they are retried on next flush.
|
package/package.json
CHANGED