@docstack/pouchdb-adapter-googledrive 0.1.2 → 0.1.4
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/lib/drive.js +67 -56
- package/package.json +1 -1
package/lib/drive.js
CHANGED
|
@@ -160,22 +160,31 @@ class DriveHandler {
|
|
|
160
160
|
return { id, changes: null };
|
|
161
161
|
}
|
|
162
162
|
}));
|
|
163
|
+
const foundNew = {};
|
|
163
164
|
for (const { id, changes } of logResults) {
|
|
164
165
|
if (!changes) {
|
|
165
166
|
this.log(`Skipping failed log ${id}`);
|
|
166
167
|
continue;
|
|
167
168
|
}
|
|
168
169
|
let changesArray = Array.isArray(changes) ? changes : [changes];
|
|
169
|
-
this.
|
|
170
|
+
this.log('Processing log file', id, 'changes', changesArray.length);
|
|
170
171
|
for (const change of changesArray) {
|
|
171
|
-
this.log('Processing change, sequence', change.seq);
|
|
172
172
|
this.updateIndex(change, id);
|
|
173
173
|
if (this.docCache.get(change.id)) {
|
|
174
174
|
this.docCache.remove(change.id);
|
|
175
175
|
}
|
|
176
|
+
foundNew[change.id] = {
|
|
177
|
+
_id: change.id,
|
|
178
|
+
_rev: change.rev,
|
|
179
|
+
_deleted: !!change.deleted,
|
|
180
|
+
seq: change.seq
|
|
181
|
+
};
|
|
176
182
|
}
|
|
177
183
|
this.processedLogIds.add(id);
|
|
178
|
-
|
|
184
|
+
}
|
|
185
|
+
if (Object.keys(foundNew).length > 0) {
|
|
186
|
+
this.log('Load complete, notifying of changes', Object.keys(foundNew).length);
|
|
187
|
+
this.notifyListeners(foundNew);
|
|
179
188
|
}
|
|
180
189
|
}
|
|
181
190
|
// 2. Replay NEW Change Logs (Metadata only updates)
|
|
@@ -278,6 +287,12 @@ class DriveHandler {
|
|
|
278
287
|
doc = content;
|
|
279
288
|
}
|
|
280
289
|
if (doc) {
|
|
290
|
+
// HEAL: Ensure PouchDB core validation doesn't fail due to history corruption
|
|
291
|
+
// This prevents the infinite replicator retry loop when start < ids.length
|
|
292
|
+
if (doc._revisions && doc._revisions.start < doc._revisions.ids.length) {
|
|
293
|
+
const start = doc._revisions.start || 1;
|
|
294
|
+
doc._revisions.ids = doc._revisions.ids.slice(0, start);
|
|
295
|
+
}
|
|
281
296
|
this.docCache.put(id, doc);
|
|
282
297
|
doc._rev = entry.rev;
|
|
283
298
|
}
|
|
@@ -508,13 +523,21 @@ class DriveHandler {
|
|
|
508
523
|
}
|
|
509
524
|
this.localDocsEtag = res.etag;
|
|
510
525
|
// Update Index
|
|
526
|
+
const changedDocs = {};
|
|
511
527
|
for (const change of changes) {
|
|
512
528
|
this.updateIndex(change, res.id);
|
|
513
529
|
if (change.doc)
|
|
514
530
|
this.docCache.put(change.id, change.doc);
|
|
515
531
|
else
|
|
516
532
|
this.docCache.remove(change.id);
|
|
533
|
+
changedDocs[change.id] = {
|
|
534
|
+
_id: change.id,
|
|
535
|
+
_rev: change.rev,
|
|
536
|
+
_deleted: !!change.deleted,
|
|
537
|
+
seq: change.seq
|
|
538
|
+
};
|
|
517
539
|
}
|
|
540
|
+
this.notifyListeners(changedDocs);
|
|
518
541
|
return;
|
|
519
542
|
}
|
|
520
543
|
catch (err) {
|
|
@@ -539,6 +562,7 @@ class DriveHandler {
|
|
|
539
562
|
await this.saveMeta(nextMeta, this.metaEtag);
|
|
540
563
|
// 4. Update Local State
|
|
541
564
|
this.meta = nextMeta;
|
|
565
|
+
const changedDocs = {};
|
|
542
566
|
for (const change of changes) {
|
|
543
567
|
this.updateIndex(change, fileId);
|
|
544
568
|
if (change.doc) {
|
|
@@ -547,9 +571,15 @@ class DriveHandler {
|
|
|
547
571
|
else if (change.deleted) {
|
|
548
572
|
this.docCache.remove(change.id);
|
|
549
573
|
}
|
|
574
|
+
changedDocs[change.id] = {
|
|
575
|
+
_id: change.id,
|
|
576
|
+
_rev: change.rev,
|
|
577
|
+
_deleted: !!change.deleted,
|
|
578
|
+
seq: change.seq
|
|
579
|
+
};
|
|
550
580
|
}
|
|
551
|
-
// Notify local changes feed listeners about
|
|
552
|
-
this.notifyListeners();
|
|
581
|
+
// Notify local changes feed listeners about only what we just wrote
|
|
582
|
+
this.notifyListeners(changedDocs);
|
|
553
583
|
// 5. Compaction Check
|
|
554
584
|
const totalChanges = await this.countTotalChanges();
|
|
555
585
|
if (totalChanges >= this.compactionThreshold ||
|
|
@@ -697,42 +727,27 @@ class DriveHandler {
|
|
|
697
727
|
return createRes.id;
|
|
698
728
|
}
|
|
699
729
|
async findFile(name) {
|
|
700
|
-
const
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
let file = files[0];
|
|
712
|
-
if (!file.etag) {
|
|
713
|
-
// Robustness: Fetch metadata for the file if etag is missing from list
|
|
714
|
-
try {
|
|
715
|
-
file = await this.client.getFileMetadata(file.id);
|
|
716
|
-
}
|
|
717
|
-
catch (e) {
|
|
718
|
-
this.log('Failed to fetch file metadata for etag', file.id, e);
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
return {
|
|
722
|
-
fileId: file.id,
|
|
723
|
-
etag: file.etag,
|
|
724
|
-
md5Checksum: file.md5Checksum,
|
|
725
|
-
modifiedTime: file.modifiedTime
|
|
726
|
-
};
|
|
730
|
+
const safeName = this.escapeQuery(name);
|
|
731
|
+
const q = `name = '${safeName}' and '${this.folderId}' in parents and trashed = false`;
|
|
732
|
+
const files = await this.client.listFiles(q);
|
|
733
|
+
if (files.length > 0) {
|
|
734
|
+
let file = files[0];
|
|
735
|
+
if (!file.etag) {
|
|
736
|
+
try {
|
|
737
|
+
file = await this.client.getFileMetadata(file.id);
|
|
738
|
+
}
|
|
739
|
+
catch (e) {
|
|
740
|
+
this.log('Failed to fetch file metadata for etag', file.id, e);
|
|
727
741
|
}
|
|
728
|
-
return null;
|
|
729
|
-
}
|
|
730
|
-
finally {
|
|
731
|
-
this.pendingFinds.delete(name);
|
|
732
742
|
}
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
743
|
+
return {
|
|
744
|
+
fileId: file.id,
|
|
745
|
+
etag: file.etag,
|
|
746
|
+
md5Checksum: file.md5Checksum,
|
|
747
|
+
modifiedTime: file.modifiedTime
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
return null;
|
|
736
751
|
}
|
|
737
752
|
async downloadJson(fileId, skipCache = false) {
|
|
738
753
|
return await this.fetchFile(fileId, skipCache);
|
|
@@ -855,24 +870,20 @@ class DriveHandler {
|
|
|
855
870
|
}
|
|
856
871
|
}, intervalMs);
|
|
857
872
|
}
|
|
858
|
-
notifyListeners() {
|
|
859
|
-
|
|
860
|
-
//
|
|
861
|
-
//
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
seq: entry.seq // IMPORTANT: Missing previously, preventing filtered changes from working
|
|
872
|
-
};
|
|
873
|
+
notifyListeners(changedDocs) {
|
|
874
|
+
const changes = changedDocs || {};
|
|
875
|
+
// If no specifically changed docs provided, we don't want to firehose the whole index anymore
|
|
876
|
+
// as it causes reprocessing loops in PouchDB sync.
|
|
877
|
+
if (Object.keys(changes).length === 0)
|
|
878
|
+
return;
|
|
879
|
+
for (const cb of this.listeners) {
|
|
880
|
+
try {
|
|
881
|
+
cb(changes);
|
|
882
|
+
}
|
|
883
|
+
catch (e) {
|
|
884
|
+
this.log('Error in change listener callback', e);
|
|
885
|
+
}
|
|
873
886
|
}
|
|
874
|
-
for (const cb of this.listeners)
|
|
875
|
-
cb(changes);
|
|
876
887
|
}
|
|
877
888
|
// For tests/debug
|
|
878
889
|
onChange(cb) {
|