@affectively/aeon 1.0.0 → 1.2.0
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 +10 -0
- package/dist/compression/index.cjs +580 -0
- package/dist/compression/index.cjs.map +1 -0
- package/dist/compression/index.d.cts +189 -0
- package/dist/compression/index.d.ts +189 -0
- package/dist/compression/index.js +573 -0
- package/dist/compression/index.js.map +1 -0
- package/dist/core/index.d.cts +70 -5
- package/dist/core/index.d.ts +70 -5
- package/dist/crypto/index.cjs +100 -0
- package/dist/crypto/index.cjs.map +1 -0
- package/dist/crypto/index.d.cts +407 -0
- package/dist/crypto/index.d.ts +407 -0
- package/dist/crypto/index.js +96 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/distributed/index.cjs +420 -23
- package/dist/distributed/index.cjs.map +1 -1
- package/dist/distributed/index.d.cts +901 -2
- package/dist/distributed/index.d.ts +901 -2
- package/dist/distributed/index.js +420 -23
- package/dist/distributed/index.js.map +1 -1
- package/dist/index.cjs +1222 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -811
- package/dist/index.d.ts +11 -811
- package/dist/index.js +1221 -56
- package/dist/index.js.map +1 -1
- package/dist/offline/index.cjs +419 -0
- package/dist/offline/index.cjs.map +1 -0
- package/dist/offline/index.d.cts +148 -0
- package/dist/offline/index.d.ts +148 -0
- package/dist/offline/index.js +415 -0
- package/dist/offline/index.js.map +1 -0
- package/dist/optimization/index.cjs +797 -0
- package/dist/optimization/index.cjs.map +1 -0
- package/dist/optimization/index.d.cts +347 -0
- package/dist/optimization/index.d.ts +347 -0
- package/dist/optimization/index.js +787 -0
- package/dist/optimization/index.js.map +1 -0
- package/dist/persistence/index.cjs +145 -0
- package/dist/persistence/index.cjs.map +1 -0
- package/dist/persistence/index.d.cts +63 -0
- package/dist/persistence/index.d.ts +63 -0
- package/dist/persistence/index.js +142 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/presence/index.cjs +489 -0
- package/dist/presence/index.cjs.map +1 -0
- package/dist/presence/index.d.cts +283 -0
- package/dist/presence/index.d.ts +283 -0
- package/dist/presence/index.js +485 -0
- package/dist/presence/index.js.map +1 -0
- package/dist/types-CMxO7QF0.d.cts +33 -0
- package/dist/types-CMxO7QF0.d.ts +33 -0
- package/dist/versioning/index.cjs +296 -14
- package/dist/versioning/index.cjs.map +1 -1
- package/dist/versioning/index.d.cts +66 -1
- package/dist/versioning/index.d.ts +66 -1
- package/dist/versioning/index.js +296 -14
- package/dist/versioning/index.js.map +1 -1
- package/package.json +51 -1
- package/dist/index-C_4CMV5c.d.cts +0 -1207
- package/dist/index-C_4CMV5c.d.ts +0 -1207
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var eventemitter3 = require('eventemitter3');
|
|
4
|
+
|
|
5
|
+
// src/offline/OfflineOperationQueue.ts
|
|
6
|
+
|
|
7
|
+
// src/utils/logger.ts
|
|
8
|
+
var consoleLogger = {
|
|
9
|
+
debug: (...args) => {
|
|
10
|
+
console.debug("[AEON:DEBUG]", ...args);
|
|
11
|
+
},
|
|
12
|
+
info: (...args) => {
|
|
13
|
+
console.info("[AEON:INFO]", ...args);
|
|
14
|
+
},
|
|
15
|
+
warn: (...args) => {
|
|
16
|
+
console.warn("[AEON:WARN]", ...args);
|
|
17
|
+
},
|
|
18
|
+
error: (...args) => {
|
|
19
|
+
console.error("[AEON:ERROR]", ...args);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var currentLogger = consoleLogger;
|
|
23
|
+
function getLogger() {
|
|
24
|
+
return currentLogger;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/offline/OfflineOperationQueue.ts
|
|
28
|
+
var logger = getLogger();
|
|
29
|
+
var OfflineOperationQueue = class _OfflineOperationQueue extends eventemitter3.EventEmitter {
|
|
30
|
+
static DEFAULT_PERSIST_KEY = "aeon:offline-queue:v1";
|
|
31
|
+
queue = /* @__PURE__ */ new Map();
|
|
32
|
+
syncingIds = /* @__PURE__ */ new Set();
|
|
33
|
+
maxQueueSize = 1e3;
|
|
34
|
+
defaultMaxRetries = 3;
|
|
35
|
+
persistence = null;
|
|
36
|
+
persistTimer = null;
|
|
37
|
+
persistInFlight = false;
|
|
38
|
+
persistPending = false;
|
|
39
|
+
constructor(maxQueueSizeOrOptions = 1e3, defaultMaxRetries = 3) {
|
|
40
|
+
super();
|
|
41
|
+
if (typeof maxQueueSizeOrOptions === "number") {
|
|
42
|
+
this.maxQueueSize = maxQueueSizeOrOptions;
|
|
43
|
+
this.defaultMaxRetries = defaultMaxRetries;
|
|
44
|
+
} else {
|
|
45
|
+
this.maxQueueSize = maxQueueSizeOrOptions.maxQueueSize ?? 1e3;
|
|
46
|
+
this.defaultMaxRetries = maxQueueSizeOrOptions.defaultMaxRetries ?? 3;
|
|
47
|
+
if (maxQueueSizeOrOptions.persistence) {
|
|
48
|
+
this.persistence = {
|
|
49
|
+
...maxQueueSizeOrOptions.persistence,
|
|
50
|
+
key: maxQueueSizeOrOptions.persistence.key ?? _OfflineOperationQueue.DEFAULT_PERSIST_KEY,
|
|
51
|
+
autoPersist: maxQueueSizeOrOptions.persistence.autoPersist ?? true,
|
|
52
|
+
autoLoad: maxQueueSizeOrOptions.persistence.autoLoad ?? false,
|
|
53
|
+
persistDebounceMs: maxQueueSizeOrOptions.persistence.persistDebounceMs ?? 25
|
|
54
|
+
};
|
|
55
|
+
if (this.persistence.autoLoad) {
|
|
56
|
+
void this.loadFromPersistence().catch((error) => {
|
|
57
|
+
logger.error("[OfflineOperationQueue] Failed to load persistence", {
|
|
58
|
+
key: this.persistence?.key,
|
|
59
|
+
error: error instanceof Error ? error.message : String(error)
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
logger.debug("[OfflineOperationQueue] Initialized", {
|
|
66
|
+
maxQueueSize: this.maxQueueSize,
|
|
67
|
+
defaultMaxRetries: this.defaultMaxRetries,
|
|
68
|
+
persistenceEnabled: this.persistence !== null
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Add operation to the queue
|
|
73
|
+
*/
|
|
74
|
+
enqueue(type, data, sessionId, priority = "normal", maxRetries) {
|
|
75
|
+
if (this.queue.size >= this.maxQueueSize) {
|
|
76
|
+
const oldest = this.findOldestLowPriority();
|
|
77
|
+
if (oldest) {
|
|
78
|
+
this.queue.delete(oldest.id);
|
|
79
|
+
logger.warn("[OfflineOperationQueue] Queue full, removed oldest", {
|
|
80
|
+
removedId: oldest.id
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const operation = {
|
|
85
|
+
id: `op-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
86
|
+
type,
|
|
87
|
+
data,
|
|
88
|
+
sessionId,
|
|
89
|
+
priority,
|
|
90
|
+
createdAt: Date.now(),
|
|
91
|
+
retryCount: 0,
|
|
92
|
+
maxRetries: maxRetries ?? this.defaultMaxRetries,
|
|
93
|
+
status: "pending"
|
|
94
|
+
};
|
|
95
|
+
this.queue.set(operation.id, operation);
|
|
96
|
+
this.emit("operation-added", operation);
|
|
97
|
+
this.schedulePersist();
|
|
98
|
+
logger.debug("[OfflineOperationQueue] Operation enqueued", {
|
|
99
|
+
id: operation.id,
|
|
100
|
+
type,
|
|
101
|
+
priority,
|
|
102
|
+
queueSize: this.queue.size
|
|
103
|
+
});
|
|
104
|
+
return operation;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get next operations to sync (by priority)
|
|
108
|
+
*/
|
|
109
|
+
getNextBatch(batchSize = 10) {
|
|
110
|
+
const pending = Array.from(this.queue.values()).filter((op) => op.status === "pending" && !this.syncingIds.has(op.id)).sort((a, b) => {
|
|
111
|
+
const priorityOrder = { high: 0, normal: 1, low: 2 };
|
|
112
|
+
const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
|
|
113
|
+
if (priorityDiff !== 0) return priorityDiff;
|
|
114
|
+
return a.createdAt - b.createdAt;
|
|
115
|
+
});
|
|
116
|
+
return pending.slice(0, batchSize);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Mark operations as syncing
|
|
120
|
+
*/
|
|
121
|
+
markSyncing(operationIds) {
|
|
122
|
+
let changed = false;
|
|
123
|
+
for (const id of operationIds) {
|
|
124
|
+
const op = this.queue.get(id);
|
|
125
|
+
if (op) {
|
|
126
|
+
op.status = "syncing";
|
|
127
|
+
this.syncingIds.add(id);
|
|
128
|
+
changed = true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (changed) {
|
|
132
|
+
this.schedulePersist();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Mark operation as synced
|
|
137
|
+
*/
|
|
138
|
+
markSynced(operationId) {
|
|
139
|
+
const op = this.queue.get(operationId);
|
|
140
|
+
if (op) {
|
|
141
|
+
op.status = "synced";
|
|
142
|
+
this.syncingIds.delete(operationId);
|
|
143
|
+
this.emit("operation-synced", op);
|
|
144
|
+
this.schedulePersist();
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
this.queue.delete(operationId);
|
|
147
|
+
this.schedulePersist();
|
|
148
|
+
if (this.getPendingCount() === 0) {
|
|
149
|
+
this.emit("queue-empty");
|
|
150
|
+
}
|
|
151
|
+
}, 1e3);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Mark operation as failed
|
|
156
|
+
*/
|
|
157
|
+
markFailed(operationId, error) {
|
|
158
|
+
const op = this.queue.get(operationId);
|
|
159
|
+
if (op) {
|
|
160
|
+
op.retryCount++;
|
|
161
|
+
op.lastError = error.message;
|
|
162
|
+
this.syncingIds.delete(operationId);
|
|
163
|
+
if (op.retryCount >= op.maxRetries) {
|
|
164
|
+
op.status = "failed";
|
|
165
|
+
this.emit("operation-failed", op, error);
|
|
166
|
+
logger.error("[OfflineOperationQueue] Operation permanently failed", {
|
|
167
|
+
id: operationId,
|
|
168
|
+
retries: op.retryCount,
|
|
169
|
+
error: error.message
|
|
170
|
+
});
|
|
171
|
+
} else {
|
|
172
|
+
op.status = "pending";
|
|
173
|
+
logger.warn("[OfflineOperationQueue] Operation failed, will retry", {
|
|
174
|
+
id: operationId,
|
|
175
|
+
retryCount: op.retryCount,
|
|
176
|
+
maxRetries: op.maxRetries
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
this.schedulePersist();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get operation by ID
|
|
184
|
+
*/
|
|
185
|
+
getOperation(operationId) {
|
|
186
|
+
return this.queue.get(operationId);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get all pending operations
|
|
190
|
+
*/
|
|
191
|
+
getPendingOperations() {
|
|
192
|
+
return Array.from(this.queue.values()).filter(
|
|
193
|
+
(op) => op.status === "pending"
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get pending count
|
|
198
|
+
*/
|
|
199
|
+
getPendingCount() {
|
|
200
|
+
return Array.from(this.queue.values()).filter(
|
|
201
|
+
(op) => op.status === "pending"
|
|
202
|
+
).length;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get queue statistics
|
|
206
|
+
*/
|
|
207
|
+
getStats() {
|
|
208
|
+
const operations = Array.from(this.queue.values());
|
|
209
|
+
const pending = operations.filter((op) => op.status === "pending").length;
|
|
210
|
+
const syncing = operations.filter((op) => op.status === "syncing").length;
|
|
211
|
+
const failed = operations.filter((op) => op.status === "failed").length;
|
|
212
|
+
const synced = operations.filter((op) => op.status === "synced").length;
|
|
213
|
+
const pendingOps = operations.filter((op) => op.status === "pending");
|
|
214
|
+
const oldestPendingMs = pendingOps.length > 0 ? Date.now() - Math.min(...pendingOps.map((op) => op.createdAt)) : 0;
|
|
215
|
+
const averageRetries = operations.length > 0 ? operations.reduce((sum, op) => sum + op.retryCount, 0) / operations.length : 0;
|
|
216
|
+
return {
|
|
217
|
+
pending,
|
|
218
|
+
syncing,
|
|
219
|
+
failed,
|
|
220
|
+
synced,
|
|
221
|
+
totalOperations: operations.length,
|
|
222
|
+
oldestPendingMs,
|
|
223
|
+
averageRetries
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Clear all operations
|
|
228
|
+
*/
|
|
229
|
+
clear() {
|
|
230
|
+
this.queue.clear();
|
|
231
|
+
this.syncingIds.clear();
|
|
232
|
+
this.schedulePersist();
|
|
233
|
+
logger.debug("[OfflineOperationQueue] Queue cleared");
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Clear failed operations
|
|
237
|
+
*/
|
|
238
|
+
clearFailed() {
|
|
239
|
+
let changed = false;
|
|
240
|
+
for (const [id, op] of this.queue.entries()) {
|
|
241
|
+
if (op.status === "failed") {
|
|
242
|
+
this.queue.delete(id);
|
|
243
|
+
changed = true;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (changed) {
|
|
247
|
+
this.schedulePersist();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Retry failed operations
|
|
252
|
+
*/
|
|
253
|
+
retryFailed() {
|
|
254
|
+
let changed = false;
|
|
255
|
+
for (const op of this.queue.values()) {
|
|
256
|
+
if (op.status === "failed") {
|
|
257
|
+
op.status = "pending";
|
|
258
|
+
op.retryCount = 0;
|
|
259
|
+
changed = true;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (changed) {
|
|
263
|
+
this.schedulePersist();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Find oldest low-priority operation
|
|
268
|
+
*/
|
|
269
|
+
findOldestLowPriority() {
|
|
270
|
+
const lowPriority = Array.from(this.queue.values()).filter((op) => op.priority === "low" && op.status === "pending").sort((a, b) => a.createdAt - b.createdAt);
|
|
271
|
+
return lowPriority[0] ?? null;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Export queue for persistence
|
|
275
|
+
*/
|
|
276
|
+
export() {
|
|
277
|
+
return Array.from(this.queue.values());
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Import queue from persistence
|
|
281
|
+
*/
|
|
282
|
+
import(operations) {
|
|
283
|
+
this.queue.clear();
|
|
284
|
+
this.syncingIds.clear();
|
|
285
|
+
for (const op of operations) {
|
|
286
|
+
if (this.isValidOfflineOperation(op)) {
|
|
287
|
+
this.queue.set(op.id, {
|
|
288
|
+
...op,
|
|
289
|
+
status: op.status === "syncing" ? "pending" : op.status
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
this.schedulePersist();
|
|
294
|
+
logger.debug("[OfflineOperationQueue] Imported operations", {
|
|
295
|
+
count: this.queue.size
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Persist current queue snapshot.
|
|
300
|
+
*/
|
|
301
|
+
async saveToPersistence() {
|
|
302
|
+
if (!this.persistence) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
const envelope = {
|
|
306
|
+
version: 1,
|
|
307
|
+
updatedAt: Date.now(),
|
|
308
|
+
data: this.export()
|
|
309
|
+
};
|
|
310
|
+
const serialize = this.persistence.serializer ?? ((value) => JSON.stringify(value));
|
|
311
|
+
const raw = serialize(envelope);
|
|
312
|
+
await this.persistence.adapter.setItem(this.persistence.key, raw);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Load queue snapshot from persistence.
|
|
316
|
+
*/
|
|
317
|
+
async loadFromPersistence() {
|
|
318
|
+
if (!this.persistence) {
|
|
319
|
+
return 0;
|
|
320
|
+
}
|
|
321
|
+
const raw = await this.persistence.adapter.getItem(this.persistence.key);
|
|
322
|
+
if (!raw) {
|
|
323
|
+
return 0;
|
|
324
|
+
}
|
|
325
|
+
const deserialize = this.persistence.deserializer ?? ((value) => JSON.parse(value));
|
|
326
|
+
const envelope = deserialize(raw);
|
|
327
|
+
if (envelope.version !== 1 || !Array.isArray(envelope.data)) {
|
|
328
|
+
throw new Error("Invalid offline queue persistence payload");
|
|
329
|
+
}
|
|
330
|
+
this.queue.clear();
|
|
331
|
+
this.syncingIds.clear();
|
|
332
|
+
let imported = 0;
|
|
333
|
+
for (const operation of envelope.data) {
|
|
334
|
+
if (this.isValidOfflineOperation(operation)) {
|
|
335
|
+
this.queue.set(operation.id, {
|
|
336
|
+
...operation,
|
|
337
|
+
status: operation.status === "syncing" ? "pending" : operation.status
|
|
338
|
+
});
|
|
339
|
+
imported++;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
logger.debug("[OfflineOperationQueue] Loaded from persistence", {
|
|
343
|
+
key: this.persistence.key,
|
|
344
|
+
imported
|
|
345
|
+
});
|
|
346
|
+
return imported;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Remove persisted queue snapshot.
|
|
350
|
+
*/
|
|
351
|
+
async clearPersistence() {
|
|
352
|
+
if (!this.persistence) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
await this.persistence.adapter.removeItem(this.persistence.key);
|
|
356
|
+
}
|
|
357
|
+
schedulePersist() {
|
|
358
|
+
if (!this.persistence || this.persistence.autoPersist === false) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
if (this.persistTimer) {
|
|
362
|
+
clearTimeout(this.persistTimer);
|
|
363
|
+
}
|
|
364
|
+
this.persistTimer = setTimeout(() => {
|
|
365
|
+
void this.persistSafely();
|
|
366
|
+
}, this.persistence.persistDebounceMs ?? 25);
|
|
367
|
+
}
|
|
368
|
+
async persistSafely() {
|
|
369
|
+
if (!this.persistence) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
if (this.persistInFlight) {
|
|
373
|
+
this.persistPending = true;
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
this.persistInFlight = true;
|
|
377
|
+
try {
|
|
378
|
+
await this.saveToPersistence();
|
|
379
|
+
} catch (error) {
|
|
380
|
+
logger.error("[OfflineOperationQueue] Persistence write failed", {
|
|
381
|
+
key: this.persistence.key,
|
|
382
|
+
error: error instanceof Error ? error.message : String(error)
|
|
383
|
+
});
|
|
384
|
+
} finally {
|
|
385
|
+
this.persistInFlight = false;
|
|
386
|
+
const shouldRunAgain = this.persistPending;
|
|
387
|
+
this.persistPending = false;
|
|
388
|
+
if (shouldRunAgain) {
|
|
389
|
+
void this.persistSafely();
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
isValidOfflineOperation(value) {
|
|
394
|
+
if (typeof value !== "object" || value === null) {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
const candidate = value;
|
|
398
|
+
const validType = candidate.type === "create" || candidate.type === "update" || candidate.type === "delete" || candidate.type === "sync" || candidate.type === "batch";
|
|
399
|
+
const validPriority = candidate.priority === "high" || candidate.priority === "normal" || candidate.priority === "low";
|
|
400
|
+
const validStatus = candidate.status === "pending" || candidate.status === "syncing" || candidate.status === "failed" || candidate.status === "synced";
|
|
401
|
+
return typeof candidate.id === "string" && validType && typeof candidate.data === "object" && candidate.data !== null && !Array.isArray(candidate.data) && typeof candidate.sessionId === "string" && validPriority && typeof candidate.createdAt === "number" && typeof candidate.retryCount === "number" && typeof candidate.maxRetries === "number" && validStatus;
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
var offlineQueueInstance = null;
|
|
405
|
+
function getOfflineOperationQueue() {
|
|
406
|
+
if (!offlineQueueInstance) {
|
|
407
|
+
offlineQueueInstance = new OfflineOperationQueue();
|
|
408
|
+
}
|
|
409
|
+
return offlineQueueInstance;
|
|
410
|
+
}
|
|
411
|
+
function resetOfflineOperationQueue() {
|
|
412
|
+
offlineQueueInstance = null;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
exports.OfflineOperationQueue = OfflineOperationQueue;
|
|
416
|
+
exports.getOfflineOperationQueue = getOfflineOperationQueue;
|
|
417
|
+
exports.resetOfflineOperationQueue = resetOfflineOperationQueue;
|
|
418
|
+
//# sourceMappingURL=index.cjs.map
|
|
419
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/logger.ts","../../src/offline/OfflineOperationQueue.ts"],"names":["EventEmitter"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Aeon Logger Interface\n *\n * Provides a pluggable logging interface that can be configured\n * by consumers to integrate with their preferred logging solution.\n */\n\n/**\n * Logger interface that consumers can implement\n */\nexport interface Logger {\n debug: (...args: unknown[]) => void;\n info: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n}\n\n/**\n * Default console logger implementation\n */\nconst consoleLogger: Logger = {\n debug: (...args: unknown[]) => {\n // eslint-disable-next-line no-console\n console.debug('[AEON:DEBUG]', ...args);\n },\n info: (...args: unknown[]) => {\n // eslint-disable-next-line no-console\n console.info('[AEON:INFO]', ...args);\n },\n warn: (...args: unknown[]) => {\n // eslint-disable-next-line no-console\n console.warn('[AEON:WARN]', ...args);\n },\n error: (...args: unknown[]) => {\n // eslint-disable-next-line no-console\n console.error('[AEON:ERROR]', ...args);\n },\n};\n\n/**\n * No-op logger for production or when logging is disabled\n */\nconst noopLogger: Logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\n/**\n * Current logger instance\n */\nlet currentLogger: Logger = consoleLogger;\n\n/**\n * Get the current logger instance\n */\nexport function getLogger(): Logger {\n return currentLogger;\n}\n\n/**\n * Set a custom logger implementation\n */\nexport function setLogger(logger: Logger): void {\n currentLogger = logger;\n}\n\n/**\n * Reset to the default console logger\n */\nexport function resetLogger(): void {\n currentLogger = consoleLogger;\n}\n\n/**\n * Disable all logging\n */\nexport function disableLogging(): void {\n currentLogger = noopLogger;\n}\n\n/**\n * Create a namespaced logger\n */\nexport function createNamespacedLogger(namespace: string): Logger {\n const logger = getLogger();\n return {\n debug: (...args: unknown[]) => logger.debug(`[${namespace}]`, ...args),\n info: (...args: unknown[]) => logger.info(`[${namespace}]`, ...args),\n warn: (...args: unknown[]) => logger.warn(`[${namespace}]`, ...args),\n error: (...args: unknown[]) => logger.error(`[${namespace}]`, ...args),\n };\n}\n\n// Export default logger for convenience\nexport const logger: Logger = {\n debug: (...args: unknown[]) => getLogger().debug(...args),\n info: (...args: unknown[]) => getLogger().info(...args),\n warn: (...args: unknown[]) => getLogger().warn(...args),\n error: (...args: unknown[]) => getLogger().error(...args),\n};\n","/**\n * Offline Operation Queue (Phase 11)\n *\n * Manages pending operations for offline-first clients.\n * Provides priority-based queuing, persistence, and retry logic.\n */\n\nimport { EventEmitter } from 'eventemitter3';\nimport { getLogger } from '../utils/logger';\nimport type { Operation, OperationPriority } from '../core/types';\nimport type {\n PersistedEnvelope,\n PersistenceDeserializer,\n PersistenceSerializer,\n StorageAdapter,\n} from '../persistence';\n\nconst logger = getLogger();\n\n// Re-export OperationPriority from core\nexport type { OperationPriority } from '../core/types';\n\nexport interface OfflineOperation {\n id: string;\n type: Operation['type'];\n data: Record<string, unknown>;\n sessionId: string;\n priority: OperationPriority;\n createdAt: number;\n retryCount: number;\n maxRetries: number;\n lastError?: string;\n status: 'pending' | 'syncing' | 'failed' | 'synced';\n}\n\nexport interface OfflineQueueStats {\n pending: number;\n syncing: number;\n failed: number;\n synced: number;\n totalOperations: number;\n oldestPendingMs: number;\n averageRetries: number;\n}\n\nexport interface OfflineQueueEvents {\n 'operation-added': (operation: OfflineOperation) => void;\n 'operation-synced': (operation: OfflineOperation) => void;\n 'operation-failed': (operation: OfflineOperation, error: Error) => void;\n 'queue-empty': () => void;\n 'sync-started': () => void;\n 'sync-completed': (stats: { synced: number; failed: number }) => void;\n}\n\nexport interface OfflineQueuePersistenceConfig {\n adapter: StorageAdapter;\n key?: string;\n autoPersist?: boolean;\n autoLoad?: boolean;\n persistDebounceMs?: number;\n serializer?: PersistenceSerializer<OfflineOperation[]>;\n deserializer?: PersistenceDeserializer<OfflineOperation[]>;\n}\n\nexport interface OfflineOperationQueueOptions {\n maxQueueSize?: number;\n defaultMaxRetries?: number;\n persistence?: OfflineQueuePersistenceConfig;\n}\n\n// ============================================================================\n// Offline Operation Queue\n// ============================================================================\n\nexport class OfflineOperationQueue extends EventEmitter<OfflineQueueEvents> {\n private static readonly DEFAULT_PERSIST_KEY = 'aeon:offline-queue:v1';\n private queue: Map<string, OfflineOperation> = new Map();\n private syncingIds: Set<string> = new Set();\n private maxQueueSize = 1000;\n private defaultMaxRetries = 3;\n private persistence: (OfflineQueuePersistenceConfig & { key: string }) | null =\n null;\n private persistTimer: ReturnType<typeof setTimeout> | null = null;\n private persistInFlight = false;\n private persistPending = false;\n\n constructor(\n maxQueueSizeOrOptions: number | OfflineOperationQueueOptions = 1000,\n defaultMaxRetries = 3,\n ) {\n super();\n\n if (typeof maxQueueSizeOrOptions === 'number') {\n this.maxQueueSize = maxQueueSizeOrOptions;\n this.defaultMaxRetries = defaultMaxRetries;\n } else {\n this.maxQueueSize = maxQueueSizeOrOptions.maxQueueSize ?? 1000;\n this.defaultMaxRetries = maxQueueSizeOrOptions.defaultMaxRetries ?? 3;\n\n if (maxQueueSizeOrOptions.persistence) {\n this.persistence = {\n ...maxQueueSizeOrOptions.persistence,\n key:\n maxQueueSizeOrOptions.persistence.key ??\n OfflineOperationQueue.DEFAULT_PERSIST_KEY,\n autoPersist: maxQueueSizeOrOptions.persistence.autoPersist ?? true,\n autoLoad: maxQueueSizeOrOptions.persistence.autoLoad ?? false,\n persistDebounceMs:\n maxQueueSizeOrOptions.persistence.persistDebounceMs ?? 25,\n };\n\n if (this.persistence.autoLoad) {\n void this.loadFromPersistence().catch((error) => {\n logger.error('[OfflineOperationQueue] Failed to load persistence', {\n key: this.persistence?.key,\n error: error instanceof Error ? error.message : String(error),\n });\n });\n }\n }\n }\n\n logger.debug('[OfflineOperationQueue] Initialized', {\n maxQueueSize: this.maxQueueSize,\n defaultMaxRetries: this.defaultMaxRetries,\n persistenceEnabled: this.persistence !== null,\n });\n }\n\n /**\n * Add operation to the queue\n */\n enqueue(\n type: Operation['type'],\n data: Record<string, unknown>,\n sessionId: string,\n priority: OperationPriority = 'normal',\n maxRetries?: number,\n ): OfflineOperation {\n if (this.queue.size >= this.maxQueueSize) {\n // Remove oldest low-priority operation\n const oldest = this.findOldestLowPriority();\n if (oldest) {\n this.queue.delete(oldest.id);\n logger.warn('[OfflineOperationQueue] Queue full, removed oldest', {\n removedId: oldest.id,\n });\n }\n }\n\n const operation: OfflineOperation = {\n id: `op-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n type,\n data,\n sessionId,\n priority,\n createdAt: Date.now(),\n retryCount: 0,\n maxRetries: maxRetries ?? this.defaultMaxRetries,\n status: 'pending',\n };\n\n this.queue.set(operation.id, operation);\n this.emit('operation-added', operation);\n this.schedulePersist();\n\n logger.debug('[OfflineOperationQueue] Operation enqueued', {\n id: operation.id,\n type,\n priority,\n queueSize: this.queue.size,\n });\n\n return operation;\n }\n\n /**\n * Get next operations to sync (by priority)\n */\n getNextBatch(batchSize = 10): OfflineOperation[] {\n const pending = Array.from(this.queue.values())\n .filter((op) => op.status === 'pending' && !this.syncingIds.has(op.id))\n .sort((a, b) => {\n // Sort by priority first, then by creation time\n const priorityOrder = { high: 0, normal: 1, low: 2 };\n const priorityDiff =\n priorityOrder[a.priority] - priorityOrder[b.priority];\n if (priorityDiff !== 0) return priorityDiff;\n return a.createdAt - b.createdAt;\n });\n\n return pending.slice(0, batchSize);\n }\n\n /**\n * Mark operations as syncing\n */\n markSyncing(operationIds: string[]): void {\n let changed = false;\n for (const id of operationIds) {\n const op = this.queue.get(id);\n if (op) {\n op.status = 'syncing';\n this.syncingIds.add(id);\n changed = true;\n }\n }\n\n if (changed) {\n this.schedulePersist();\n }\n }\n\n /**\n * Mark operation as synced\n */\n markSynced(operationId: string): void {\n const op = this.queue.get(operationId);\n if (op) {\n op.status = 'synced';\n this.syncingIds.delete(operationId);\n this.emit('operation-synced', op);\n this.schedulePersist();\n\n // Remove synced operations after short delay\n setTimeout(() => {\n this.queue.delete(operationId);\n this.schedulePersist();\n if (this.getPendingCount() === 0) {\n this.emit('queue-empty');\n }\n }, 1000);\n }\n }\n\n /**\n * Mark operation as failed\n */\n markFailed(operationId: string, error: Error): void {\n const op = this.queue.get(operationId);\n if (op) {\n op.retryCount++;\n op.lastError = error.message;\n this.syncingIds.delete(operationId);\n\n if (op.retryCount >= op.maxRetries) {\n op.status = 'failed';\n this.emit('operation-failed', op, error);\n logger.error('[OfflineOperationQueue] Operation permanently failed', {\n id: operationId,\n retries: op.retryCount,\n error: error.message,\n });\n } else {\n op.status = 'pending';\n logger.warn('[OfflineOperationQueue] Operation failed, will retry', {\n id: operationId,\n retryCount: op.retryCount,\n maxRetries: op.maxRetries,\n });\n }\n\n this.schedulePersist();\n }\n }\n\n /**\n * Get operation by ID\n */\n getOperation(operationId: string): OfflineOperation | undefined {\n return this.queue.get(operationId);\n }\n\n /**\n * Get all pending operations\n */\n getPendingOperations(): OfflineOperation[] {\n return Array.from(this.queue.values()).filter(\n (op) => op.status === 'pending',\n );\n }\n\n /**\n * Get pending count\n */\n getPendingCount(): number {\n return Array.from(this.queue.values()).filter(\n (op) => op.status === 'pending',\n ).length;\n }\n\n /**\n * Get queue statistics\n */\n getStats(): OfflineQueueStats {\n const operations = Array.from(this.queue.values());\n\n const pending = operations.filter((op) => op.status === 'pending').length;\n const syncing = operations.filter((op) => op.status === 'syncing').length;\n const failed = operations.filter((op) => op.status === 'failed').length;\n const synced = operations.filter((op) => op.status === 'synced').length;\n\n const pendingOps = operations.filter((op) => op.status === 'pending');\n const oldestPendingMs =\n pendingOps.length > 0\n ? Date.now() - Math.min(...pendingOps.map((op) => op.createdAt))\n : 0;\n\n const averageRetries =\n operations.length > 0\n ? operations.reduce((sum, op) => sum + op.retryCount, 0) /\n operations.length\n : 0;\n\n return {\n pending,\n syncing,\n failed,\n synced,\n totalOperations: operations.length,\n oldestPendingMs,\n averageRetries,\n };\n }\n\n /**\n * Clear all operations\n */\n clear(): void {\n this.queue.clear();\n this.syncingIds.clear();\n this.schedulePersist();\n logger.debug('[OfflineOperationQueue] Queue cleared');\n }\n\n /**\n * Clear failed operations\n */\n clearFailed(): void {\n let changed = false;\n for (const [id, op] of this.queue.entries()) {\n if (op.status === 'failed') {\n this.queue.delete(id);\n changed = true;\n }\n }\n\n if (changed) {\n this.schedulePersist();\n }\n }\n\n /**\n * Retry failed operations\n */\n retryFailed(): void {\n let changed = false;\n for (const op of this.queue.values()) {\n if (op.status === 'failed') {\n op.status = 'pending';\n op.retryCount = 0;\n changed = true;\n }\n }\n\n if (changed) {\n this.schedulePersist();\n }\n }\n\n /**\n * Find oldest low-priority operation\n */\n private findOldestLowPriority(): OfflineOperation | null {\n const lowPriority = Array.from(this.queue.values())\n .filter((op) => op.priority === 'low' && op.status === 'pending')\n .sort((a, b) => a.createdAt - b.createdAt);\n\n return lowPriority[0] ?? null;\n }\n\n /**\n * Export queue for persistence\n */\n export(): OfflineOperation[] {\n return Array.from(this.queue.values());\n }\n\n /**\n * Import queue from persistence\n */\n import(operations: OfflineOperation[]): void {\n this.queue.clear();\n this.syncingIds.clear();\n\n for (const op of operations) {\n if (this.isValidOfflineOperation(op)) {\n this.queue.set(op.id, {\n ...op,\n status: op.status === 'syncing' ? 'pending' : op.status,\n });\n }\n }\n\n this.schedulePersist();\n\n logger.debug('[OfflineOperationQueue] Imported operations', {\n count: this.queue.size,\n });\n }\n\n /**\n * Persist current queue snapshot.\n */\n async saveToPersistence(): Promise<void> {\n if (!this.persistence) {\n return;\n }\n\n const envelope: PersistedEnvelope<OfflineOperation[]> = {\n version: 1,\n updatedAt: Date.now(),\n data: this.export(),\n };\n\n const serialize =\n this.persistence.serializer ??\n ((value: PersistedEnvelope<OfflineOperation[]>) => JSON.stringify(value));\n const raw = serialize(envelope);\n\n await this.persistence.adapter.setItem(this.persistence.key, raw);\n }\n\n /**\n * Load queue snapshot from persistence.\n */\n async loadFromPersistence(): Promise<number> {\n if (!this.persistence) {\n return 0;\n }\n\n const raw = await this.persistence.adapter.getItem(this.persistence.key);\n if (!raw) {\n return 0;\n }\n\n const deserialize =\n this.persistence.deserializer ??\n ((value: string) =>\n JSON.parse(value) as PersistedEnvelope<OfflineOperation[]>);\n\n const envelope = deserialize(raw);\n if (envelope.version !== 1 || !Array.isArray(envelope.data)) {\n throw new Error('Invalid offline queue persistence payload');\n }\n\n this.queue.clear();\n this.syncingIds.clear();\n\n let imported = 0;\n for (const operation of envelope.data) {\n if (this.isValidOfflineOperation(operation)) {\n this.queue.set(operation.id, {\n ...operation,\n status: operation.status === 'syncing' ? 'pending' : operation.status,\n });\n imported++;\n }\n }\n\n logger.debug('[OfflineOperationQueue] Loaded from persistence', {\n key: this.persistence.key,\n imported,\n });\n\n return imported;\n }\n\n /**\n * Remove persisted queue snapshot.\n */\n async clearPersistence(): Promise<void> {\n if (!this.persistence) {\n return;\n }\n await this.persistence.adapter.removeItem(this.persistence.key);\n }\n\n private schedulePersist(): void {\n if (!this.persistence || this.persistence.autoPersist === false) {\n return;\n }\n\n if (this.persistTimer) {\n clearTimeout(this.persistTimer);\n }\n\n this.persistTimer = setTimeout(() => {\n void this.persistSafely();\n }, this.persistence.persistDebounceMs ?? 25);\n }\n\n private async persistSafely(): Promise<void> {\n if (!this.persistence) {\n return;\n }\n\n if (this.persistInFlight) {\n this.persistPending = true;\n return;\n }\n\n this.persistInFlight = true;\n\n try {\n await this.saveToPersistence();\n } catch (error) {\n logger.error('[OfflineOperationQueue] Persistence write failed', {\n key: this.persistence.key,\n error: error instanceof Error ? error.message : String(error),\n });\n } finally {\n this.persistInFlight = false;\n const shouldRunAgain = this.persistPending;\n this.persistPending = false;\n if (shouldRunAgain) {\n void this.persistSafely();\n }\n }\n }\n\n private isValidOfflineOperation(value: unknown): value is OfflineOperation {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const candidate = value as Partial<OfflineOperation>;\n const validType =\n candidate.type === 'create' ||\n candidate.type === 'update' ||\n candidate.type === 'delete' ||\n candidate.type === 'sync' ||\n candidate.type === 'batch';\n const validPriority =\n candidate.priority === 'high' ||\n candidate.priority === 'normal' ||\n candidate.priority === 'low';\n const validStatus =\n candidate.status === 'pending' ||\n candidate.status === 'syncing' ||\n candidate.status === 'failed' ||\n candidate.status === 'synced';\n\n return (\n typeof candidate.id === 'string' &&\n validType &&\n typeof candidate.data === 'object' &&\n candidate.data !== null &&\n !Array.isArray(candidate.data) &&\n typeof candidate.sessionId === 'string' &&\n validPriority &&\n typeof candidate.createdAt === 'number' &&\n typeof candidate.retryCount === 'number' &&\n typeof candidate.maxRetries === 'number' &&\n validStatus\n );\n }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet offlineQueueInstance: OfflineOperationQueue | null = null;\n\nexport function getOfflineOperationQueue(): OfflineOperationQueue {\n if (!offlineQueueInstance) {\n offlineQueueInstance = new OfflineOperationQueue();\n }\n return offlineQueueInstance;\n}\n\nexport function resetOfflineOperationQueue(): void {\n offlineQueueInstance = null;\n}\n"]}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { EventEmitter } from 'eventemitter3';
|
|
2
|
+
import { Operation, OperationPriority } from '../core/index.cjs';
|
|
3
|
+
import { S as StorageAdapter, b as PersistenceSerializer, a as PersistenceDeserializer } from '../types-CMxO7QF0.cjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Offline Operation Queue (Phase 11)
|
|
7
|
+
*
|
|
8
|
+
* Manages pending operations for offline-first clients.
|
|
9
|
+
* Provides priority-based queuing, persistence, and retry logic.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
interface OfflineOperation {
|
|
13
|
+
id: string;
|
|
14
|
+
type: Operation['type'];
|
|
15
|
+
data: Record<string, unknown>;
|
|
16
|
+
sessionId: string;
|
|
17
|
+
priority: OperationPriority;
|
|
18
|
+
createdAt: number;
|
|
19
|
+
retryCount: number;
|
|
20
|
+
maxRetries: number;
|
|
21
|
+
lastError?: string;
|
|
22
|
+
status: 'pending' | 'syncing' | 'failed' | 'synced';
|
|
23
|
+
}
|
|
24
|
+
interface OfflineQueueStats {
|
|
25
|
+
pending: number;
|
|
26
|
+
syncing: number;
|
|
27
|
+
failed: number;
|
|
28
|
+
synced: number;
|
|
29
|
+
totalOperations: number;
|
|
30
|
+
oldestPendingMs: number;
|
|
31
|
+
averageRetries: number;
|
|
32
|
+
}
|
|
33
|
+
interface OfflineQueueEvents {
|
|
34
|
+
'operation-added': (operation: OfflineOperation) => void;
|
|
35
|
+
'operation-synced': (operation: OfflineOperation) => void;
|
|
36
|
+
'operation-failed': (operation: OfflineOperation, error: Error) => void;
|
|
37
|
+
'queue-empty': () => void;
|
|
38
|
+
'sync-started': () => void;
|
|
39
|
+
'sync-completed': (stats: {
|
|
40
|
+
synced: number;
|
|
41
|
+
failed: number;
|
|
42
|
+
}) => void;
|
|
43
|
+
}
|
|
44
|
+
interface OfflineQueuePersistenceConfig {
|
|
45
|
+
adapter: StorageAdapter;
|
|
46
|
+
key?: string;
|
|
47
|
+
autoPersist?: boolean;
|
|
48
|
+
autoLoad?: boolean;
|
|
49
|
+
persistDebounceMs?: number;
|
|
50
|
+
serializer?: PersistenceSerializer<OfflineOperation[]>;
|
|
51
|
+
deserializer?: PersistenceDeserializer<OfflineOperation[]>;
|
|
52
|
+
}
|
|
53
|
+
interface OfflineOperationQueueOptions {
|
|
54
|
+
maxQueueSize?: number;
|
|
55
|
+
defaultMaxRetries?: number;
|
|
56
|
+
persistence?: OfflineQueuePersistenceConfig;
|
|
57
|
+
}
|
|
58
|
+
declare class OfflineOperationQueue extends EventEmitter<OfflineQueueEvents> {
|
|
59
|
+
private static readonly DEFAULT_PERSIST_KEY;
|
|
60
|
+
private queue;
|
|
61
|
+
private syncingIds;
|
|
62
|
+
private maxQueueSize;
|
|
63
|
+
private defaultMaxRetries;
|
|
64
|
+
private persistence;
|
|
65
|
+
private persistTimer;
|
|
66
|
+
private persistInFlight;
|
|
67
|
+
private persistPending;
|
|
68
|
+
constructor(maxQueueSizeOrOptions?: number | OfflineOperationQueueOptions, defaultMaxRetries?: number);
|
|
69
|
+
/**
|
|
70
|
+
* Add operation to the queue
|
|
71
|
+
*/
|
|
72
|
+
enqueue(type: Operation['type'], data: Record<string, unknown>, sessionId: string, priority?: OperationPriority, maxRetries?: number): OfflineOperation;
|
|
73
|
+
/**
|
|
74
|
+
* Get next operations to sync (by priority)
|
|
75
|
+
*/
|
|
76
|
+
getNextBatch(batchSize?: number): OfflineOperation[];
|
|
77
|
+
/**
|
|
78
|
+
* Mark operations as syncing
|
|
79
|
+
*/
|
|
80
|
+
markSyncing(operationIds: string[]): void;
|
|
81
|
+
/**
|
|
82
|
+
* Mark operation as synced
|
|
83
|
+
*/
|
|
84
|
+
markSynced(operationId: string): void;
|
|
85
|
+
/**
|
|
86
|
+
* Mark operation as failed
|
|
87
|
+
*/
|
|
88
|
+
markFailed(operationId: string, error: Error): void;
|
|
89
|
+
/**
|
|
90
|
+
* Get operation by ID
|
|
91
|
+
*/
|
|
92
|
+
getOperation(operationId: string): OfflineOperation | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* Get all pending operations
|
|
95
|
+
*/
|
|
96
|
+
getPendingOperations(): OfflineOperation[];
|
|
97
|
+
/**
|
|
98
|
+
* Get pending count
|
|
99
|
+
*/
|
|
100
|
+
getPendingCount(): number;
|
|
101
|
+
/**
|
|
102
|
+
* Get queue statistics
|
|
103
|
+
*/
|
|
104
|
+
getStats(): OfflineQueueStats;
|
|
105
|
+
/**
|
|
106
|
+
* Clear all operations
|
|
107
|
+
*/
|
|
108
|
+
clear(): void;
|
|
109
|
+
/**
|
|
110
|
+
* Clear failed operations
|
|
111
|
+
*/
|
|
112
|
+
clearFailed(): void;
|
|
113
|
+
/**
|
|
114
|
+
* Retry failed operations
|
|
115
|
+
*/
|
|
116
|
+
retryFailed(): void;
|
|
117
|
+
/**
|
|
118
|
+
* Find oldest low-priority operation
|
|
119
|
+
*/
|
|
120
|
+
private findOldestLowPriority;
|
|
121
|
+
/**
|
|
122
|
+
* Export queue for persistence
|
|
123
|
+
*/
|
|
124
|
+
export(): OfflineOperation[];
|
|
125
|
+
/**
|
|
126
|
+
* Import queue from persistence
|
|
127
|
+
*/
|
|
128
|
+
import(operations: OfflineOperation[]): void;
|
|
129
|
+
/**
|
|
130
|
+
* Persist current queue snapshot.
|
|
131
|
+
*/
|
|
132
|
+
saveToPersistence(): Promise<void>;
|
|
133
|
+
/**
|
|
134
|
+
* Load queue snapshot from persistence.
|
|
135
|
+
*/
|
|
136
|
+
loadFromPersistence(): Promise<number>;
|
|
137
|
+
/**
|
|
138
|
+
* Remove persisted queue snapshot.
|
|
139
|
+
*/
|
|
140
|
+
clearPersistence(): Promise<void>;
|
|
141
|
+
private schedulePersist;
|
|
142
|
+
private persistSafely;
|
|
143
|
+
private isValidOfflineOperation;
|
|
144
|
+
}
|
|
145
|
+
declare function getOfflineOperationQueue(): OfflineOperationQueue;
|
|
146
|
+
declare function resetOfflineOperationQueue(): void;
|
|
147
|
+
|
|
148
|
+
export { type OfflineOperation, OfflineOperationQueue, type OfflineOperationQueueOptions, type OfflineQueueEvents, type OfflineQueuePersistenceConfig, type OfflineQueueStats, OperationPriority, getOfflineOperationQueue, resetOfflineOperationQueue };
|