@powerhousedao/connect 1.0.8 → 1.0.10-dev.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/LICENSE +661 -0
- package/dist/.env +0 -5
- package/dist/assets/{app-D3TxLTK-.css → app-BIIVKAZr.css} +241 -60
- package/dist/assets/{app-Bw1Ba-jV.js → app-CsiwsM42.js} +2262 -1224
- package/dist/assets/{app-loader-KTD3Q6e9.js → app-loader-C7A2YjX4.js} +876 -577
- package/dist/assets/{app-loader-CjrEwupY.css → app-loader-pcztQTL4.css} +189 -26
- package/dist/assets/{ccip-D3HujWHr.js → ccip-BG1d6viz.js} +3 -3
- package/dist/assets/{content-D3TuBhK9.js → content-0UFgs2d1.js} +37 -7
- package/dist/assets/{index-DpasqVlD.js → index-BMDqhr-9.js} +3 -3
- package/dist/assets/{index-DsNVpRhT.js → index-CTEGX1We.js} +670 -519
- package/dist/assets/{index-yFk8X8m1.js → index-yr0-SqYf.js} +4 -4
- package/dist/assets/{main.CzEw2R-H.js → main.BmcV9296.js} +1 -1
- package/dist/assets/{style-D4JhTt_m.css → style-Ce3V83BE.css} +31 -36
- package/dist/external-packages.js +5 -0
- package/dist/hmr.js +4 -1
- package/dist/index.html +1 -4
- package/dist/modules/@powerhousedao/reactor-browser/{chunk-G6LMXRY5.js → chunk-2ONJ2PX4.js} +1 -1
- package/dist/modules/@powerhousedao/reactor-browser/{chunk-P46ZMPJ3.js → chunk-3C54663M.js} +1 -1
- package/dist/modules/@powerhousedao/reactor-browser/{chunk-6AXML2S3.js → chunk-5QJXNK35.js} +1 -1
- package/dist/modules/@powerhousedao/reactor-browser/{chunk-FW7N6EJH.js → chunk-C7QRY43M.js} +3 -3
- package/dist/modules/@powerhousedao/reactor-browser/{chunk-45DCPCA7.js → chunk-CO2RVWYY.js} +1 -1
- package/dist/modules/@powerhousedao/reactor-browser/{chunk-POMUCSTC.js → chunk-ISDEPHKP.js} +74 -20
- package/dist/modules/@powerhousedao/reactor-browser/{chunk-F3RCGUF6.js → chunk-NHD6VUCD.js} +2 -2
- package/dist/modules/@powerhousedao/reactor-browser/{chunk-YOX3ZAET.js → chunk-SQ5HIKYV.js} +581 -334
- package/dist/modules/@powerhousedao/reactor-browser/{chunk-M2UUQ5LH.js → chunk-U34SEKEB.js} +2 -2
- package/dist/modules/@powerhousedao/reactor-browser/{chunk-4LZZ55AN.js → chunk-XV42KZK3.js} +1 -1
- package/dist/modules/@powerhousedao/reactor-browser/context/index.js +2 -2
- package/dist/modules/@powerhousedao/reactor-browser/context/read-mode.js +2 -2
- package/dist/modules/@powerhousedao/reactor-browser/hooks/index.js +8 -8
- package/dist/modules/@powerhousedao/reactor-browser/hooks/useAddDebouncedOperations.js +3 -3
- package/dist/modules/@powerhousedao/reactor-browser/hooks/useConnectCrypto.js +2 -2
- package/dist/modules/@powerhousedao/reactor-browser/hooks/useDocumentDrives.js +2 -2
- package/dist/modules/@powerhousedao/reactor-browser/hooks/useDocumentEditor.js +5 -5
- package/dist/modules/@powerhousedao/reactor-browser/hooks/useDriveActions.js +2 -2
- package/dist/modules/@powerhousedao/reactor-browser/hooks/useDriveActionsWithUiNodes.js +3 -3
- package/dist/modules/@powerhousedao/reactor-browser/index.js +10 -10
- package/dist/modules/@powerhousedao/reactor-browser/reactor.js +2 -2
- package/dist/swEnv.js +0 -3
- package/dist/vite-envs.sh +1 -28
- package/package.json +9 -9
|
@@ -688,30 +688,79 @@ var require_lib = __commonJS({
|
|
|
688
688
|
}
|
|
689
689
|
});
|
|
690
690
|
|
|
691
|
+
// ../../packages/document-drive/dist/src/cache/util.js
|
|
692
|
+
var trimResultingState = (document) => {
|
|
693
|
+
const global2 = document.operations.global.map((e) => {
|
|
694
|
+
delete e.resultingState;
|
|
695
|
+
return e;
|
|
696
|
+
});
|
|
697
|
+
const local = document.operations.local.map((e) => {
|
|
698
|
+
delete e.resultingState;
|
|
699
|
+
return e;
|
|
700
|
+
});
|
|
701
|
+
return { ...document, operations: { global: global2, local } };
|
|
702
|
+
};
|
|
703
|
+
|
|
691
704
|
// ../../packages/document-drive/dist/src/cache/memory.js
|
|
692
705
|
var InMemoryCache = class {
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
+
idTodocument = /* @__PURE__ */ new Map();
|
|
707
|
+
idToDrive = /* @__PURE__ */ new Map();
|
|
708
|
+
slugToDriveId = /* @__PURE__ */ new Map();
|
|
709
|
+
clear() {
|
|
710
|
+
this.idTodocument.clear();
|
|
711
|
+
this.idToDrive.clear();
|
|
712
|
+
this.slugToDriveId.clear();
|
|
713
|
+
}
|
|
714
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
715
|
+
// ICache
|
|
716
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
717
|
+
async setDocument(documentId, document) {
|
|
718
|
+
const doc = trimResultingState(document);
|
|
719
|
+
this.idTodocument.set(documentId, doc);
|
|
720
|
+
}
|
|
721
|
+
async getDocument(documentId) {
|
|
722
|
+
return this.idTodocument.get(documentId);
|
|
723
|
+
}
|
|
724
|
+
async deleteDocument(documentId) {
|
|
725
|
+
return this.idTodocument.delete(documentId);
|
|
726
|
+
}
|
|
727
|
+
async setDrive(driveId, drive) {
|
|
728
|
+
const doc = trimResultingState(drive);
|
|
729
|
+
this.idToDrive.set(driveId, doc);
|
|
730
|
+
}
|
|
731
|
+
async getDrive(driveId) {
|
|
732
|
+
return this.idToDrive.get(driveId);
|
|
733
|
+
}
|
|
734
|
+
async deleteDrive(driveId) {
|
|
735
|
+
const drive = this.idToDrive.get(driveId);
|
|
736
|
+
if (!drive) {
|
|
737
|
+
return false;
|
|
706
738
|
}
|
|
707
|
-
|
|
708
|
-
|
|
739
|
+
const slug = drive.state.global.slug;
|
|
740
|
+
if (slug) {
|
|
741
|
+
this.slugToDriveId.delete(slug);
|
|
742
|
+
}
|
|
743
|
+
return this.idToDrive.delete(driveId);
|
|
709
744
|
}
|
|
710
|
-
async
|
|
711
|
-
|
|
745
|
+
async setDriveBySlug(slug, drive) {
|
|
746
|
+
const driveId = drive.state.global.id;
|
|
747
|
+
this.slugToDriveId.set(slug, driveId);
|
|
748
|
+
this.setDrive(driveId, drive);
|
|
712
749
|
}
|
|
713
|
-
async
|
|
714
|
-
|
|
750
|
+
async getDriveBySlug(slug) {
|
|
751
|
+
const driveId = this.slugToDriveId.get(slug);
|
|
752
|
+
if (!driveId) {
|
|
753
|
+
return void 0;
|
|
754
|
+
}
|
|
755
|
+
return this.getDrive(driveId);
|
|
756
|
+
}
|
|
757
|
+
async deleteDriveBySlug(slug) {
|
|
758
|
+
const driveId = this.slugToDriveId.get(slug);
|
|
759
|
+
if (!driveId) {
|
|
760
|
+
return false;
|
|
761
|
+
}
|
|
762
|
+
this.slugToDriveId.delete(slug);
|
|
763
|
+
return this.deleteDrive(driveId);
|
|
715
764
|
}
|
|
716
765
|
};
|
|
717
766
|
var memory_default = InMemoryCache;
|
|
@@ -1652,19 +1701,16 @@ var ReadDocumentNotFoundError = class extends ReadDriveError {
|
|
|
1652
1701
|
// ../../packages/document-drive/dist/src/storage/memory.js
|
|
1653
1702
|
var MemoryStorage = class {
|
|
1654
1703
|
documents;
|
|
1655
|
-
drives;
|
|
1656
1704
|
driveManifests;
|
|
1657
|
-
slugToDriveId = {};
|
|
1658
1705
|
constructor() {
|
|
1659
1706
|
this.documents = {};
|
|
1660
|
-
this.drives = {};
|
|
1661
1707
|
this.driveManifests = {};
|
|
1662
1708
|
}
|
|
1663
1709
|
////////////////////////////////
|
|
1664
1710
|
// IDocumentStorage
|
|
1665
1711
|
////////////////////////////////
|
|
1666
1712
|
exists(documentId) {
|
|
1667
|
-
return Promise.resolve(!!this.documents[documentId]);
|
|
1713
|
+
return Promise.resolve(!!this.documents[documentId] || !!this.documents[`drive/${documentId}`]);
|
|
1668
1714
|
}
|
|
1669
1715
|
create(documentId, document) {
|
|
1670
1716
|
this.documents[documentId] = document;
|
|
@@ -1673,10 +1719,52 @@ var MemoryStorage = class {
|
|
|
1673
1719
|
get(documentId) {
|
|
1674
1720
|
const document = this.documents[documentId];
|
|
1675
1721
|
if (!document) {
|
|
1722
|
+
const drive = this.documents[`drive/${documentId}`];
|
|
1723
|
+
if (drive) {
|
|
1724
|
+
return Promise.resolve(drive);
|
|
1725
|
+
}
|
|
1676
1726
|
throw new Error(`Document with id ${documentId} not found`);
|
|
1677
1727
|
}
|
|
1678
1728
|
return Promise.resolve(document);
|
|
1679
1729
|
}
|
|
1730
|
+
async delete(documentId) {
|
|
1731
|
+
const drives = await this.getDrives();
|
|
1732
|
+
for (const driveId of drives) {
|
|
1733
|
+
if (driveId === documentId)
|
|
1734
|
+
continue;
|
|
1735
|
+
await this.removeChild(driveId, documentId);
|
|
1736
|
+
}
|
|
1737
|
+
delete this.driveManifests[documentId];
|
|
1738
|
+
if (this.documents[documentId]) {
|
|
1739
|
+
delete this.documents[documentId];
|
|
1740
|
+
return Promise.resolve(true);
|
|
1741
|
+
}
|
|
1742
|
+
return Promise.resolve(false);
|
|
1743
|
+
}
|
|
1744
|
+
async addChild(parentId, childId) {
|
|
1745
|
+
if (parentId === childId) {
|
|
1746
|
+
throw new Error("Cannot associate a document with itself");
|
|
1747
|
+
}
|
|
1748
|
+
const children = await this.getChildren(childId);
|
|
1749
|
+
if (children.includes(parentId)) {
|
|
1750
|
+
throw new Error("Cannot associate a document with its child");
|
|
1751
|
+
}
|
|
1752
|
+
const manifest = this.getManifest(parentId);
|
|
1753
|
+
manifest.documentIds.add(childId);
|
|
1754
|
+
this.updateDriveManifest(parentId, manifest);
|
|
1755
|
+
}
|
|
1756
|
+
async removeChild(parentId, childId) {
|
|
1757
|
+
const manifest = this.getManifest(parentId);
|
|
1758
|
+
if (manifest.documentIds.delete(childId)) {
|
|
1759
|
+
this.updateDriveManifest(parentId, manifest);
|
|
1760
|
+
return true;
|
|
1761
|
+
}
|
|
1762
|
+
return false;
|
|
1763
|
+
}
|
|
1764
|
+
async getChildren(parentId) {
|
|
1765
|
+
const manifest = this.getManifest(parentId);
|
|
1766
|
+
return [...manifest.documentIds];
|
|
1767
|
+
}
|
|
1680
1768
|
////////////////////////////////
|
|
1681
1769
|
// IDriveStorage
|
|
1682
1770
|
////////////////////////////////
|
|
@@ -1684,27 +1772,19 @@ var MemoryStorage = class {
|
|
|
1684
1772
|
return this.exists(id);
|
|
1685
1773
|
}
|
|
1686
1774
|
getDocuments(drive) {
|
|
1687
|
-
const manifest = this.
|
|
1775
|
+
const manifest = this.getManifest(drive);
|
|
1688
1776
|
return Promise.resolve([...manifest.documentIds]);
|
|
1689
1777
|
}
|
|
1690
1778
|
getDocument(driveId, id) {
|
|
1691
1779
|
return this.get(id);
|
|
1692
1780
|
}
|
|
1693
|
-
async saveDocument(drive, id, document) {
|
|
1694
|
-
this.documents[id] = document;
|
|
1695
|
-
const manifest = this.getDriveManifest(drive);
|
|
1696
|
-
manifest.documentIds.add(id);
|
|
1697
|
-
this.updateDriveManifest(drive, manifest);
|
|
1698
|
-
}
|
|
1699
1781
|
async clearStorage() {
|
|
1700
1782
|
this.documents = {};
|
|
1701
|
-
this.drives = {};
|
|
1702
1783
|
this.driveManifests = {};
|
|
1703
|
-
this.slugToDriveId = {};
|
|
1704
1784
|
}
|
|
1705
1785
|
async createDocument(drive, id, document) {
|
|
1706
1786
|
await this.create(id, document);
|
|
1707
|
-
const manifest = this.
|
|
1787
|
+
const manifest = this.getManifest(drive);
|
|
1708
1788
|
manifest.documentIds.add(id);
|
|
1709
1789
|
this.updateDriveManifest(drive, manifest);
|
|
1710
1790
|
}
|
|
@@ -1721,59 +1801,60 @@ var MemoryStorage = class {
|
|
|
1721
1801
|
};
|
|
1722
1802
|
}
|
|
1723
1803
|
async deleteDocument(drive, id) {
|
|
1724
|
-
|
|
1725
|
-
for (const driveId of drives) {
|
|
1726
|
-
const manifest = this.getDriveManifest(driveId);
|
|
1727
|
-
if (manifest.documentIds.has(id)) {
|
|
1728
|
-
manifest.documentIds.delete(id);
|
|
1729
|
-
this.updateDriveManifest(driveId, manifest);
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
delete this.documents[id];
|
|
1804
|
+
this.delete(id);
|
|
1733
1805
|
}
|
|
1734
1806
|
async getDrives() {
|
|
1735
|
-
return Object.keys(this.
|
|
1807
|
+
return Object.keys(this.driveManifests);
|
|
1736
1808
|
}
|
|
1737
1809
|
async getDrive(id) {
|
|
1738
|
-
const drive = this.
|
|
1810
|
+
const drive = this.documents[`drive/${id}`];
|
|
1739
1811
|
if (!drive) {
|
|
1740
1812
|
throw new DriveNotFoundError(id);
|
|
1741
1813
|
}
|
|
1742
1814
|
return drive;
|
|
1743
1815
|
}
|
|
1744
1816
|
async getDriveBySlug(slug) {
|
|
1745
|
-
const driveId
|
|
1746
|
-
|
|
1747
|
-
|
|
1817
|
+
for (const driveId of Object.keys(this.driveManifests)) {
|
|
1818
|
+
const drive = this.documents[`drive/${driveId}`];
|
|
1819
|
+
if (drive.initialState.state.global.slug === slug) {
|
|
1820
|
+
return drive;
|
|
1821
|
+
}
|
|
1748
1822
|
}
|
|
1749
|
-
|
|
1823
|
+
throw new Error(`Drive with slug ${slug} not found`);
|
|
1750
1824
|
}
|
|
1751
1825
|
async createDrive(id, drive) {
|
|
1752
|
-
|
|
1753
|
-
this.updateDriveManifest(id, { documentIds: /* @__PURE__ */ new Set() });
|
|
1754
|
-
const { slug } = drive.initialState.state.global;
|
|
1826
|
+
const slug = drive.initialState.state.global.slug;
|
|
1755
1827
|
if (slug) {
|
|
1756
|
-
|
|
1828
|
+
let existingDrive;
|
|
1829
|
+
try {
|
|
1830
|
+
existingDrive = await this.getDriveBySlug(slug);
|
|
1831
|
+
} catch {
|
|
1832
|
+
}
|
|
1833
|
+
if (existingDrive) {
|
|
1834
|
+
throw new Error(`Drive with slug ${slug} already exists`);
|
|
1835
|
+
}
|
|
1757
1836
|
}
|
|
1837
|
+
await this.create(`drive/${id}`, drive);
|
|
1838
|
+
this.updateDriveManifest(id, { documentIds: /* @__PURE__ */ new Set() });
|
|
1758
1839
|
}
|
|
1759
1840
|
async addDriveOperations(id, operations, header) {
|
|
1760
1841
|
const drive = await this.getDrive(id);
|
|
1761
1842
|
const mergedOperations = mergeOperations(drive.operations, operations);
|
|
1762
|
-
this.
|
|
1843
|
+
this.documents[`drive/${id}`] = {
|
|
1763
1844
|
...drive,
|
|
1764
1845
|
...header,
|
|
1765
1846
|
operations: mergedOperations
|
|
1766
1847
|
};
|
|
1767
1848
|
}
|
|
1768
1849
|
async deleteDrive(id) {
|
|
1769
|
-
const manifest = this.
|
|
1850
|
+
const manifest = this.getManifest(id);
|
|
1770
1851
|
const drives = await this.getDrives();
|
|
1771
1852
|
await Promise.all([...manifest.documentIds].map((docId) => {
|
|
1772
1853
|
for (const driveId of drives) {
|
|
1773
1854
|
if (driveId === id) {
|
|
1774
1855
|
continue;
|
|
1775
1856
|
}
|
|
1776
|
-
const manifest2 = this.
|
|
1857
|
+
const manifest2 = this.getManifest(driveId);
|
|
1777
1858
|
if (manifest2.documentIds.has(docId)) {
|
|
1778
1859
|
return;
|
|
1779
1860
|
}
|
|
@@ -1781,24 +1862,18 @@ var MemoryStorage = class {
|
|
|
1781
1862
|
delete this.documents[docId];
|
|
1782
1863
|
}));
|
|
1783
1864
|
delete this.driveManifests[id];
|
|
1784
|
-
delete this.
|
|
1785
|
-
for (const [slug, driveId] of Object.entries(this.slugToDriveId)) {
|
|
1786
|
-
if (driveId === id) {
|
|
1787
|
-
delete this.slugToDriveId[slug];
|
|
1788
|
-
}
|
|
1789
|
-
}
|
|
1865
|
+
delete this.documents[id];
|
|
1790
1866
|
}
|
|
1791
1867
|
async getSynchronizationUnitsRevision(units) {
|
|
1792
1868
|
const results = await Promise.allSettled(units.map(async (unit) => {
|
|
1793
1869
|
try {
|
|
1794
|
-
const document = await
|
|
1870
|
+
const document = await this.get(unit.documentId);
|
|
1795
1871
|
if (!document) {
|
|
1796
1872
|
return void 0;
|
|
1797
1873
|
}
|
|
1798
1874
|
const operation = document.operations[unit.scope].at(-1);
|
|
1799
1875
|
if (operation) {
|
|
1800
1876
|
return {
|
|
1801
|
-
driveId: unit.driveId,
|
|
1802
1877
|
documentId: unit.documentId,
|
|
1803
1878
|
scope: unit.scope,
|
|
1804
1879
|
branch: unit.branch,
|
|
@@ -1820,7 +1895,7 @@ var MemoryStorage = class {
|
|
|
1820
1895
|
////////////////////////////////
|
|
1821
1896
|
// Private
|
|
1822
1897
|
////////////////////////////////
|
|
1823
|
-
|
|
1898
|
+
getManifest(driveId) {
|
|
1824
1899
|
if (!this.driveManifests[driveId]) {
|
|
1825
1900
|
this.driveManifests[driveId] = { documentIds: /* @__PURE__ */ new Set() };
|
|
1826
1901
|
}
|
|
@@ -11823,11 +11898,14 @@ var PULL_DRIVE_INTERVAL = 1500;
|
|
|
11823
11898
|
|
|
11824
11899
|
// ../../packages/document-drive/dist/src/server/listener/transmitter/pull-responder.js
|
|
11825
11900
|
var MAX_REVISIONS_PER_ACK = 100;
|
|
11901
|
+
var _staticLogger;
|
|
11902
|
+
var staticLogger = () => {
|
|
11903
|
+
if (!_staticLogger) {
|
|
11904
|
+
_staticLogger = childLogger(["PullResponderTransmitter", "static"]);
|
|
11905
|
+
}
|
|
11906
|
+
return _staticLogger;
|
|
11907
|
+
};
|
|
11826
11908
|
var PullResponderTransmitter = class _PullResponderTransmitter {
|
|
11827
|
-
static staticLogger = childLogger([
|
|
11828
|
-
"PullResponderTransmitter",
|
|
11829
|
-
"static"
|
|
11830
|
-
]);
|
|
11831
11909
|
logger = childLogger([
|
|
11832
11910
|
"PullResponderTransmitter",
|
|
11833
11911
|
Math.floor(Math.random() * 999).toString()
|
|
@@ -11840,8 +11918,18 @@ var PullResponderTransmitter = class _PullResponderTransmitter {
|
|
|
11840
11918
|
this.logger.verbose(`constructor(listener: ${listener.listenerId})`);
|
|
11841
11919
|
}
|
|
11842
11920
|
getStrands(options) {
|
|
11843
|
-
this.logger.verbose(`getStrands
|
|
11844
|
-
return this.manager.getStrands(this.listener.driveId, this.listener.listenerId, options)
|
|
11921
|
+
this.logger.verbose(`[SYNC DEBUG] PullResponderTransmitter.getStrands called for drive: ${this.listener.driveId}, listener: ${this.listener.listenerId}, options: ${JSON.stringify(options || {})}`);
|
|
11922
|
+
return this.manager.getStrands(this.listener.driveId, this.listener.listenerId, options).then((strands) => {
|
|
11923
|
+
this.logger.verbose(`[SYNC DEBUG] PullResponderTransmitter.getStrands returning ${strands.length} strands for drive: ${this.listener.driveId}, listener: ${this.listener.listenerId}`);
|
|
11924
|
+
if (strands.length === 0) {
|
|
11925
|
+
this.logger.verbose(`[SYNC DEBUG] No strands returned for drive: ${this.listener.driveId}, listener: ${this.listener.listenerId}`);
|
|
11926
|
+
} else {
|
|
11927
|
+
for (const strand of strands) {
|
|
11928
|
+
this.logger.verbose(`[SYNC DEBUG] Strand for drive: ${strand.driveId}, document: ${strand.documentId}, scope: ${strand.scope}, operations: ${strand.operations.length}`);
|
|
11929
|
+
}
|
|
11930
|
+
}
|
|
11931
|
+
return strands;
|
|
11932
|
+
});
|
|
11845
11933
|
}
|
|
11846
11934
|
disconnect() {
|
|
11847
11935
|
return Promise.resolve();
|
|
@@ -11851,7 +11939,7 @@ var PullResponderTransmitter = class _PullResponderTransmitter {
|
|
|
11851
11939
|
const syncUnits = await this.manager.getListenerSyncUnitIds(driveId, listenerId);
|
|
11852
11940
|
let success = true;
|
|
11853
11941
|
for (const revision of revisions) {
|
|
11854
|
-
const syncUnit = syncUnits.find((s) => s.scope === revision.scope && s.branch === revision.branch && s.
|
|
11942
|
+
const syncUnit = syncUnits.find((s) => s.scope === revision.scope && s.branch === revision.branch && s.documentId == revision.documentId);
|
|
11855
11943
|
if (!syncUnit) {
|
|
11856
11944
|
this.logger.warn("Unknown sync unit was acknowledged", revision);
|
|
11857
11945
|
success = false;
|
|
@@ -11861,15 +11949,21 @@ var PullResponderTransmitter = class _PullResponderTransmitter {
|
|
|
11861
11949
|
}
|
|
11862
11950
|
return success;
|
|
11863
11951
|
}
|
|
11864
|
-
static async registerPullResponder(driveId, url, filter) {
|
|
11865
|
-
|
|
11952
|
+
static async registerPullResponder(driveId, url, filter, listenerId) {
|
|
11953
|
+
staticLogger().verbose(`registerPullResponder(url: ${url})`, filter);
|
|
11866
11954
|
const result = await requestGraphql(url, gql`
|
|
11867
|
-
mutation registerPullResponderListener(
|
|
11868
|
-
|
|
11955
|
+
mutation registerPullResponderListener(
|
|
11956
|
+
$filter: InputListenerFilter!
|
|
11957
|
+
$listenerId: String
|
|
11958
|
+
) {
|
|
11959
|
+
registerPullResponderListener(
|
|
11960
|
+
filter: $filter
|
|
11961
|
+
listenerId: $listenerId
|
|
11962
|
+
) {
|
|
11869
11963
|
listenerId
|
|
11870
11964
|
}
|
|
11871
11965
|
}
|
|
11872
|
-
`, { filter });
|
|
11966
|
+
`, { filter, listenerId });
|
|
11873
11967
|
const error = result.errors?.at(0);
|
|
11874
11968
|
if (error) {
|
|
11875
11969
|
throw error;
|
|
@@ -11880,7 +11974,7 @@ var PullResponderTransmitter = class _PullResponderTransmitter {
|
|
|
11880
11974
|
return result.registerPullResponderListener.listenerId;
|
|
11881
11975
|
}
|
|
11882
11976
|
static async pullStrands(driveId, url, listenerId, options) {
|
|
11883
|
-
|
|
11977
|
+
staticLogger().verbose(`[SYNC DEBUG] PullResponderTransmitter.pullStrands called for drive: ${driveId}, url: ${url}, listener: ${listenerId}, options: ${JSON.stringify(options || {})}`);
|
|
11884
11978
|
const result = await requestGraphql(url, gql`
|
|
11885
11979
|
query strands($listenerId: ID!) {
|
|
11886
11980
|
system {
|
|
@@ -11920,27 +12014,34 @@ var PullResponderTransmitter = class _PullResponderTransmitter {
|
|
|
11920
12014
|
`, { listenerId });
|
|
11921
12015
|
const error = result.errors?.at(0);
|
|
11922
12016
|
if (error) {
|
|
12017
|
+
staticLogger().verbose(`[SYNC DEBUG] Error pulling strands for drive: ${driveId}, listener: ${listenerId}, error: ${JSON.stringify(error)}`);
|
|
11923
12018
|
throw error;
|
|
11924
12019
|
}
|
|
11925
12020
|
if (!result.system) {
|
|
12021
|
+
staticLogger().verbose(`[SYNC DEBUG] No system data returned when pulling strands for drive: ${driveId}, listener: ${listenerId}`);
|
|
11926
12022
|
return [];
|
|
11927
12023
|
}
|
|
11928
|
-
|
|
12024
|
+
const strands = result.system.sync.strands.map((s) => ({
|
|
11929
12025
|
...s,
|
|
11930
12026
|
operations: s.operations.map((o) => ({
|
|
11931
12027
|
...o,
|
|
11932
12028
|
input: JSON.parse(o.input)
|
|
11933
12029
|
}))
|
|
11934
12030
|
}));
|
|
12031
|
+
staticLogger().verbose(`[SYNC DEBUG] PullResponderTransmitter.pullStrands returning ${strands.length} strands for drive: ${driveId}, listener: ${listenerId}`);
|
|
12032
|
+
if (strands.length > 0) {
|
|
12033
|
+
staticLogger().verbose(`[SYNC DEBUG] Strands being returned: ${strands.map((s) => `${s.documentId}:${s.scope}`).join(", ")}`);
|
|
12034
|
+
}
|
|
12035
|
+
return strands;
|
|
11935
12036
|
}
|
|
11936
12037
|
static async acknowledgeStrands(url, listenerId, revisions) {
|
|
11937
|
-
|
|
12038
|
+
staticLogger().verbose(`acknowledgeStrands(url: ${url}, listener: ${listenerId})`, revisions);
|
|
11938
12039
|
const chunks = [];
|
|
11939
12040
|
for (let i = 0; i < revisions.length; i += MAX_REVISIONS_PER_ACK) {
|
|
11940
12041
|
chunks.push(revisions.slice(i, i + MAX_REVISIONS_PER_ACK));
|
|
11941
12042
|
}
|
|
11942
12043
|
if (chunks.length > 1) {
|
|
11943
|
-
|
|
12044
|
+
staticLogger().verbose(`Breaking strand acknowledgement into ${chunks.length} chunks...`);
|
|
11944
12045
|
}
|
|
11945
12046
|
const results = await Promise.allSettled(chunks.map(async (chunk) => {
|
|
11946
12047
|
const result = await requestGraphql(url, gql`
|
|
@@ -11964,74 +12065,124 @@ var PullResponderTransmitter = class _PullResponderTransmitter {
|
|
|
11964
12065
|
throw new Error("Error acknowledging strands");
|
|
11965
12066
|
}
|
|
11966
12067
|
}
|
|
12068
|
+
/**
|
|
12069
|
+
* This function will only throw if `onError` throws an error (or there is
|
|
12070
|
+
* an unintentionally unhandled error in the pull loop).
|
|
12071
|
+
*
|
|
12072
|
+
* All other errors are caught, logged, and passed to `onError`.
|
|
12073
|
+
*
|
|
12074
|
+
* Because of this, `onError` _may be called multiple times_.
|
|
12075
|
+
*/
|
|
11967
12076
|
static async executePull(driveId, trigger, onStrandUpdate, onError, onRevisions, onAcknowledge) {
|
|
11968
|
-
|
|
12077
|
+
staticLogger().verbose(`executePull(driveId: ${driveId}), trigger:`, trigger);
|
|
12078
|
+
staticLogger().info(`[SYNC DEBUG] PullResponderTransmitter.executePull starting for drive: ${driveId}, listenerId: ${trigger.data.listenerId}`);
|
|
12079
|
+
const { url } = trigger.data;
|
|
12080
|
+
let strands;
|
|
12081
|
+
let error;
|
|
12082
|
+
const listenerId = trigger.data.listenerId;
|
|
11969
12083
|
try {
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
|
|
11985
|
-
|
|
11986
|
-
let error = void 0;
|
|
11987
|
-
try {
|
|
11988
|
-
const result = await onStrandUpdate(strand, {
|
|
11989
|
-
type: "trigger",
|
|
11990
|
-
trigger
|
|
11991
|
-
});
|
|
11992
|
-
if (result.error) {
|
|
11993
|
-
throw result.error;
|
|
12084
|
+
strands = await _PullResponderTransmitter.pullStrands(driveId, url, listenerId);
|
|
12085
|
+
} catch (e) {
|
|
12086
|
+
error = e;
|
|
12087
|
+
const graphqlError = error;
|
|
12088
|
+
const errors = graphqlError.response?.errors ?? [];
|
|
12089
|
+
for (const err of errors) {
|
|
12090
|
+
if (err.message === "Listener not found") {
|
|
12091
|
+
staticLogger().verbose(`[SYNC DEBUG] Auto-registering pull responder for drive: ${driveId}`);
|
|
12092
|
+
await _PullResponderTransmitter.registerPullResponder(trigger.driveId, url, trigger.filter, listenerId);
|
|
12093
|
+
try {
|
|
12094
|
+
strands = await _PullResponderTransmitter.pullStrands(driveId, url, listenerId);
|
|
12095
|
+
staticLogger().verbose(`Successfully auto-registered and pulled strands for drive: ${driveId}, listenerId: ${listenerId}`);
|
|
12096
|
+
} catch (error2) {
|
|
12097
|
+
staticLogger().error(`Could not resolve 'Listener not found' error by registering a new pull responder for drive: ${driveId}, listenerId: ${listenerId}: ${error2}`);
|
|
12098
|
+
onError(error2);
|
|
12099
|
+
return;
|
|
11994
12100
|
}
|
|
11995
|
-
|
|
11996
|
-
|
|
11997
|
-
onError(error);
|
|
11998
|
-
}
|
|
11999
|
-
listenerRevisions.push({
|
|
12000
|
-
branch: strand.branch,
|
|
12001
|
-
documentId: strand.documentId || "",
|
|
12002
|
-
driveId: strand.driveId,
|
|
12003
|
-
revision: operations.pop()?.index ?? -1,
|
|
12004
|
-
scope: strand.scope,
|
|
12005
|
-
status: error ? error instanceof OperationError ? error.status : "ERROR" : "SUCCESS",
|
|
12006
|
-
error
|
|
12007
|
-
});
|
|
12101
|
+
break;
|
|
12102
|
+
}
|
|
12008
12103
|
}
|
|
12009
|
-
|
|
12010
|
-
|
|
12011
|
-
|
|
12012
|
-
|
|
12104
|
+
}
|
|
12105
|
+
if (!strands) {
|
|
12106
|
+
staticLogger().error(`Error pulling strands for drive, and could not auto-register: ${driveId}, listenerId: ${trigger.data.listenerId}: ${error}`);
|
|
12107
|
+
onError(error);
|
|
12108
|
+
return;
|
|
12109
|
+
}
|
|
12110
|
+
if (!strands.length) {
|
|
12111
|
+
staticLogger().verbose(`[SYNC DEBUG] No strands returned in pull cycle for drive: ${driveId}, listenerId: ${trigger.data.listenerId}`);
|
|
12013
12112
|
try {
|
|
12014
|
-
|
|
12015
|
-
|
|
12016
|
-
|
|
12017
|
-
|
|
12018
|
-
success = true;
|
|
12019
|
-
} catch (error) {
|
|
12020
|
-
this.staticLogger.error("ACK error", error);
|
|
12113
|
+
onRevisions?.([]);
|
|
12114
|
+
} catch (error2) {
|
|
12115
|
+
staticLogger().error(`Error calling onRevisions for drive: ${driveId}, listenerId: ${trigger.data.listenerId}: ${error2}`);
|
|
12116
|
+
onError(error2);
|
|
12021
12117
|
}
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
|
|
12025
|
-
|
|
12118
|
+
return;
|
|
12119
|
+
}
|
|
12120
|
+
staticLogger().verbose(`[SYNC DEBUG] Processing ${strands.length} strands in pull cycle for drive: ${driveId}, listenerId: ${trigger.data.listenerId}`);
|
|
12121
|
+
const listenerRevisions = [];
|
|
12122
|
+
for (const strand of strands) {
|
|
12123
|
+
const operations = strand.operations.map((op) => ({
|
|
12124
|
+
...op,
|
|
12125
|
+
scope: strand.scope,
|
|
12126
|
+
branch: strand.branch
|
|
12127
|
+
}));
|
|
12128
|
+
staticLogger().verbose(`[SYNC DEBUG] Processing strand for drive: ${strand.driveId}, document: ${strand.documentId}, scope: ${strand.scope}, with ${operations.length} operations`);
|
|
12129
|
+
let error2 = void 0;
|
|
12130
|
+
try {
|
|
12131
|
+
const result = await onStrandUpdate(strand, {
|
|
12132
|
+
type: "trigger",
|
|
12133
|
+
trigger
|
|
12134
|
+
});
|
|
12135
|
+
if (result.error) {
|
|
12136
|
+
throw result.error;
|
|
12137
|
+
}
|
|
12138
|
+
} catch (e) {
|
|
12139
|
+
staticLogger().error(`Error processing strand for drive: ${strand.driveId}, document: ${strand.documentId}, scope: ${strand.scope}, with ${operations.length} operations: ${e}`);
|
|
12140
|
+
error2 = e;
|
|
12141
|
+
onError(error2);
|
|
12026
12142
|
}
|
|
12143
|
+
listenerRevisions.push({
|
|
12144
|
+
branch: strand.branch,
|
|
12145
|
+
documentId: strand.documentId || "",
|
|
12146
|
+
driveId: strand.driveId,
|
|
12147
|
+
revision: operations.pop()?.index ?? -1,
|
|
12148
|
+
scope: strand.scope,
|
|
12149
|
+
status: error2 ? error2 instanceof OperationError ? error2.status : "ERROR" : "SUCCESS",
|
|
12150
|
+
error: error2
|
|
12151
|
+
});
|
|
12152
|
+
}
|
|
12153
|
+
staticLogger().verbose("Processed strands...");
|
|
12154
|
+
try {
|
|
12155
|
+
onRevisions?.(listenerRevisions);
|
|
12156
|
+
} catch (error2) {
|
|
12157
|
+
staticLogger().error(`Error calling onRevisions for drive: ${driveId}, listenerId: ${trigger.data.listenerId}: ${error2}`);
|
|
12158
|
+
onError(error2);
|
|
12159
|
+
}
|
|
12160
|
+
staticLogger().verbose(`[SYNC DEBUG] Acknowledging ${listenerRevisions.length} strands for drive: ${driveId}, listenerId: ${trigger.data.listenerId}`);
|
|
12161
|
+
let success = false;
|
|
12162
|
+
try {
|
|
12163
|
+
await _PullResponderTransmitter.acknowledgeStrands(url, trigger.data.listenerId, listenerRevisions.map((revision) => {
|
|
12164
|
+
const { error: error2, ...rest } = revision;
|
|
12165
|
+
return rest;
|
|
12166
|
+
}));
|
|
12167
|
+
success = true;
|
|
12168
|
+
} catch (error2) {
|
|
12169
|
+
staticLogger().error(`Error acknowledging strands for drive: ${driveId}, listenerId: ${trigger.data.listenerId}: ${error2}`);
|
|
12170
|
+
onError(error2);
|
|
12171
|
+
}
|
|
12172
|
+
if (success) {
|
|
12173
|
+
staticLogger().verbose(`[SYNC DEBUG] Successfully acknowledged strands for drive: ${driveId}, listenerId: ${trigger.data.listenerId}`);
|
|
12174
|
+
} else {
|
|
12175
|
+
staticLogger().error("Failed to acknowledge strands");
|
|
12176
|
+
}
|
|
12177
|
+
try {
|
|
12027
12178
|
onAcknowledge?.(success);
|
|
12028
|
-
} catch (
|
|
12029
|
-
|
|
12030
|
-
onError(
|
|
12179
|
+
} catch (error2) {
|
|
12180
|
+
staticLogger().error(`Error calling onAcknowledge for drive: ${driveId}, listenerId: ${trigger.data.listenerId}: ${error2}`);
|
|
12181
|
+
onError(error2);
|
|
12031
12182
|
}
|
|
12032
12183
|
}
|
|
12033
12184
|
static setupPull(driveId, trigger, onStrandUpdate, onError, onRevisions, onAcknowledge) {
|
|
12034
|
-
|
|
12185
|
+
staticLogger().verbose(`[SYNC DEBUG] PullResponderTransmitter.setupPull initiated for drive: ${driveId}, listenerId: ${trigger.data.listenerId}`);
|
|
12035
12186
|
const { interval } = trigger.data;
|
|
12036
12187
|
let loopInterval = PULL_DRIVE_INTERVAL;
|
|
12037
12188
|
if (interval) {
|
|
@@ -12043,20 +12194,25 @@ var PullResponderTransmitter = class _PullResponderTransmitter {
|
|
|
12043
12194
|
} catch {
|
|
12044
12195
|
}
|
|
12045
12196
|
}
|
|
12197
|
+
staticLogger().verbose(`[SYNC DEBUG] Pull interval set to ${loopInterval}ms for drive: ${driveId}, listenerId: ${trigger.data.listenerId}`);
|
|
12046
12198
|
let isCancelled = false;
|
|
12047
12199
|
let timeout;
|
|
12048
12200
|
const executeLoop = async () => {
|
|
12049
12201
|
while (!isCancelled) {
|
|
12050
|
-
|
|
12202
|
+
staticLogger().verbose(`[SYNC DEBUG] Starting pull cycle for drive: ${driveId}, listenerId: ${trigger.data.listenerId}`);
|
|
12051
12203
|
await this.executePull(driveId, trigger, onStrandUpdate, onError, onRevisions, onAcknowledge);
|
|
12204
|
+
staticLogger().verbose(`[SYNC DEBUG] Completed pull cycle for drive: ${driveId}, listenerId: ${trigger.data.listenerId}, waiting ${loopInterval}ms for next cycle`);
|
|
12052
12205
|
await new Promise((resolve) => {
|
|
12053
|
-
|
|
12206
|
+
staticLogger().verbose(`Scheduling next pull in ${loopInterval} ms`);
|
|
12054
12207
|
timeout = setTimeout(resolve, loopInterval);
|
|
12055
12208
|
});
|
|
12056
12209
|
}
|
|
12057
12210
|
};
|
|
12058
|
-
executeLoop().catch(
|
|
12211
|
+
executeLoop().catch((error) => {
|
|
12212
|
+
staticLogger().error(`Error in executeLoop for drive: ${driveId}, listenerId: ${trigger.data.listenerId}: ${error}`);
|
|
12213
|
+
});
|
|
12059
12214
|
return () => {
|
|
12215
|
+
staticLogger().verbose(`[SYNC DEBUG] Cancelling pull loop for drive: ${driveId}, listenerId: ${trigger.data.listenerId}`);
|
|
12060
12216
|
isCancelled = true;
|
|
12061
12217
|
if (timeout !== void 0) {
|
|
12062
12218
|
clearTimeout(timeout);
|
|
@@ -12064,17 +12220,20 @@ var PullResponderTransmitter = class _PullResponderTransmitter {
|
|
|
12064
12220
|
};
|
|
12065
12221
|
}
|
|
12066
12222
|
static async createPullResponderTrigger(driveId, url, options) {
|
|
12067
|
-
|
|
12223
|
+
staticLogger().verbose(`createPullResponderTrigger(drive: ${driveId}, url: ${url})`);
|
|
12068
12224
|
const { pullFilter, pullInterval } = options;
|
|
12069
|
-
const
|
|
12225
|
+
const filter = pullFilter ?? {
|
|
12070
12226
|
documentId: ["*"],
|
|
12071
12227
|
documentType: ["*"],
|
|
12072
12228
|
branch: ["*"],
|
|
12073
12229
|
scope: ["*"]
|
|
12074
|
-
}
|
|
12230
|
+
};
|
|
12231
|
+
const listenerId = await _PullResponderTransmitter.registerPullResponder(driveId, url, filter);
|
|
12075
12232
|
const pullTrigger = {
|
|
12076
12233
|
id: generateUUID(),
|
|
12077
12234
|
type: "PullResponder",
|
|
12235
|
+
driveId,
|
|
12236
|
+
filter,
|
|
12078
12237
|
data: {
|
|
12079
12238
|
url,
|
|
12080
12239
|
listenerId,
|
|
@@ -12088,6 +12247,80 @@ var PullResponderTransmitter = class _PullResponderTransmitter {
|
|
|
12088
12247
|
}
|
|
12089
12248
|
};
|
|
12090
12249
|
|
|
12250
|
+
// ../../packages/document-drive/dist/src/server/listener/transmitter/switchboard-push.js
|
|
12251
|
+
var import_json_stringify_deterministic = __toESM(require_lib(), 1);
|
|
12252
|
+
var SYNC_OPS_BATCH_LIMIT = 10;
|
|
12253
|
+
var SwitchboardPushTransmitter = class {
|
|
12254
|
+
targetURL;
|
|
12255
|
+
logger = childLogger([
|
|
12256
|
+
"SwitchboardPushTransmitter",
|
|
12257
|
+
Math.floor(Math.random() * 999).toString()
|
|
12258
|
+
]);
|
|
12259
|
+
constructor(targetURL) {
|
|
12260
|
+
this.targetURL = targetURL;
|
|
12261
|
+
}
|
|
12262
|
+
async transmit(strands, source) {
|
|
12263
|
+
if (source.type === "trigger" && source.trigger.data?.url === this.targetURL) {
|
|
12264
|
+
this.logger.verbose(`Cutting trigger loop from ${this.targetURL}.`);
|
|
12265
|
+
return strands.map((strand) => ({
|
|
12266
|
+
driveId: strand.driveId,
|
|
12267
|
+
documentId: strand.documentId,
|
|
12268
|
+
scope: strand.scope,
|
|
12269
|
+
branch: strand.branch,
|
|
12270
|
+
status: "SUCCESS",
|
|
12271
|
+
revision: strand.operations.at(-1)?.index ?? -1
|
|
12272
|
+
}));
|
|
12273
|
+
}
|
|
12274
|
+
const culledStrands = [];
|
|
12275
|
+
let opsCounter = 0;
|
|
12276
|
+
for (let s = 0; opsCounter <= SYNC_OPS_BATCH_LIMIT && s < strands.length; s++) {
|
|
12277
|
+
const currentStrand = strands.at(s);
|
|
12278
|
+
if (!currentStrand) {
|
|
12279
|
+
break;
|
|
12280
|
+
}
|
|
12281
|
+
const newOps = Math.min(SYNC_OPS_BATCH_LIMIT - opsCounter, currentStrand.operations.length);
|
|
12282
|
+
culledStrands.push({
|
|
12283
|
+
...currentStrand,
|
|
12284
|
+
operations: currentStrand.operations.slice(0, newOps)
|
|
12285
|
+
});
|
|
12286
|
+
opsCounter += newOps;
|
|
12287
|
+
}
|
|
12288
|
+
this.logger.verbose(` Total update: [${strands.map((s) => s.operations.length).join(", ")}] operations`);
|
|
12289
|
+
this.logger.verbose(`Culled update: [${culledStrands.map((s) => s.operations.length).join(", ")}] operations`);
|
|
12290
|
+
try {
|
|
12291
|
+
const { pushUpdates } = await requestGraphql(this.targetURL, gql`
|
|
12292
|
+
mutation pushUpdates($strands: [InputStrandUpdate!]) {
|
|
12293
|
+
pushUpdates(strands: $strands) {
|
|
12294
|
+
driveId
|
|
12295
|
+
documentId
|
|
12296
|
+
scope
|
|
12297
|
+
branch
|
|
12298
|
+
status
|
|
12299
|
+
revision
|
|
12300
|
+
error
|
|
12301
|
+
}
|
|
12302
|
+
}
|
|
12303
|
+
`, {
|
|
12304
|
+
strands: culledStrands.map((strand) => ({
|
|
12305
|
+
...strand,
|
|
12306
|
+
operations: strand.operations.map((op) => ({
|
|
12307
|
+
...op,
|
|
12308
|
+
input: (0, import_json_stringify_deterministic.default)(op.input)
|
|
12309
|
+
}))
|
|
12310
|
+
}))
|
|
12311
|
+
});
|
|
12312
|
+
if (!pushUpdates) {
|
|
12313
|
+
throw new Error("Couldn't update listener revision");
|
|
12314
|
+
}
|
|
12315
|
+
return pushUpdates;
|
|
12316
|
+
} catch (e) {
|
|
12317
|
+
this.logger.error(e);
|
|
12318
|
+
throw e;
|
|
12319
|
+
}
|
|
12320
|
+
return [];
|
|
12321
|
+
}
|
|
12322
|
+
};
|
|
12323
|
+
|
|
12091
12324
|
// ../../packages/document-drive/dist/src/server/types.js
|
|
12092
12325
|
var TransmitterType;
|
|
12093
12326
|
(function(TransmitterType2) {
|
|
@@ -12127,6 +12360,7 @@ function isAtRevision(document, revisions) {
|
|
|
12127
12360
|
|
|
12128
12361
|
// ../../packages/document-drive/dist/src/server/base-server.js
|
|
12129
12362
|
var BaseDocumentDriveServer = class {
|
|
12363
|
+
logger = childLogger(["BaseDocumentDriveServer"]);
|
|
12130
12364
|
// external dependencies
|
|
12131
12365
|
documentModelModules;
|
|
12132
12366
|
storage;
|
|
@@ -12185,17 +12419,6 @@ var BaseDocumentDriveServer = class {
|
|
|
12185
12419
|
taskQueueMethod: options?.taskQueueMethod === void 0 ? RunAsap.runAsap : options.taskQueueMethod
|
|
12186
12420
|
};
|
|
12187
12421
|
this.defaultDrivesManager = new DefaultDrivesManager(this, this.defaultDrivesManagerDelegate, options);
|
|
12188
|
-
this.storage.setStorageDelegate?.({
|
|
12189
|
-
getCachedOperations: async (drive, id) => {
|
|
12190
|
-
try {
|
|
12191
|
-
const document = await this.cache.getDocument(drive, id);
|
|
12192
|
-
return document?.operations;
|
|
12193
|
-
} catch (error) {
|
|
12194
|
-
logger.error(error);
|
|
12195
|
-
return void 0;
|
|
12196
|
-
}
|
|
12197
|
-
}
|
|
12198
|
-
});
|
|
12199
12422
|
this.initializePromise = this._initialize();
|
|
12200
12423
|
}
|
|
12201
12424
|
// workaround for testing the ephemeral listeners -- we don't have DI in place yet
|
|
@@ -12209,19 +12432,19 @@ var BaseDocumentDriveServer = class {
|
|
|
12209
12432
|
async _initialize() {
|
|
12210
12433
|
await this.listenerManager.initialize(this.handleListenerError);
|
|
12211
12434
|
await this.queueManager.init(this.queueDelegate, (error) => {
|
|
12212
|
-
logger.error(`Error initializing queue manager`, error);
|
|
12435
|
+
this.logger.error(`Error initializing queue manager`, error);
|
|
12213
12436
|
errors.push(error);
|
|
12214
12437
|
});
|
|
12215
12438
|
try {
|
|
12216
12439
|
await this.defaultDrivesManager.removeOldremoteDrives();
|
|
12217
12440
|
} catch (error) {
|
|
12218
|
-
logger.error(error);
|
|
12441
|
+
this.logger.error(error);
|
|
12219
12442
|
}
|
|
12220
12443
|
const errors = [];
|
|
12221
12444
|
const drives = await this.getDrives();
|
|
12222
12445
|
for (const drive of drives) {
|
|
12223
12446
|
await this._initializeDrive(drive).catch((error) => {
|
|
12224
|
-
logger.error(`Error initializing drive ${drive}`, error);
|
|
12447
|
+
this.logger.error(`Error initializing drive ${drive}`, error);
|
|
12225
12448
|
errors.push(error);
|
|
12226
12449
|
});
|
|
12227
12450
|
}
|
|
@@ -12251,7 +12474,7 @@ var BaseDocumentDriveServer = class {
|
|
|
12251
12474
|
return source.type === "local" ? "push" : "pull";
|
|
12252
12475
|
}
|
|
12253
12476
|
handleListenerError(error, driveId, listener) {
|
|
12254
|
-
logger.error(`Listener ${listener.listener.label ?? listener.listener.listenerId} error:`, error);
|
|
12477
|
+
this.logger.error(`Listener ${listener.listener.label ?? listener.listener.listenerId} error:`, error);
|
|
12255
12478
|
const status = error instanceof OperationError ? error.status : "ERROR";
|
|
12256
12479
|
this.synchronizationManager.updateSyncStatus(driveId, { push: status }, error);
|
|
12257
12480
|
}
|
|
@@ -12311,9 +12534,9 @@ var BaseDocumentDriveServer = class {
|
|
|
12311
12534
|
if (pushListener) {
|
|
12312
12535
|
this.getSynchronizationUnitsRevision(driveId, syncUnits).then((syncUnitRevisions) => {
|
|
12313
12536
|
for (const revision of syncUnitRevisions) {
|
|
12314
|
-
this.listenerManager.updateListenerRevision(pushListener.listenerId, driveId, revision.syncId, revision.revision).catch(logger.error);
|
|
12537
|
+
this.listenerManager.updateListenerRevision(pushListener.listenerId, driveId, revision.syncId, revision.revision).catch(this.logger.error);
|
|
12315
12538
|
}
|
|
12316
|
-
}).catch(logger.error);
|
|
12539
|
+
}).catch(this.logger.error);
|
|
12317
12540
|
}
|
|
12318
12541
|
}
|
|
12319
12542
|
});
|
|
@@ -12335,10 +12558,57 @@ var BaseDocumentDriveServer = class {
|
|
|
12335
12558
|
}
|
|
12336
12559
|
async _initializeDrive(driveId) {
|
|
12337
12560
|
const drive = await this.getDrive(driveId);
|
|
12561
|
+
this.logger.verbose(`[SYNC DEBUG] Initializing drive ${driveId} with slug "${drive.state.global.slug}"`);
|
|
12338
12562
|
await this.synchronizationManager.initializeDriveSyncStatus(driveId, drive);
|
|
12339
12563
|
if (this.shouldSyncRemoteDrive(drive)) {
|
|
12564
|
+
this.logger.verbose(`[SYNC DEBUG] Starting sync for remote drive ${driveId}`);
|
|
12340
12565
|
await this.startSyncRemoteDrive(driveId);
|
|
12341
12566
|
}
|
|
12567
|
+
this.logger.verbose(`[SYNC DEBUG] Processing ${drive.state.local.listeners.length} listeners for drive ${driveId}`);
|
|
12568
|
+
for (const zodListener of drive.state.local.listeners) {
|
|
12569
|
+
if (zodListener.callInfo?.transmitterType === "SwitchboardPush") {
|
|
12570
|
+
this.logger.verbose(`[SYNC DEBUG] Setting up SwitchboardPush listener ${zodListener.listenerId} for drive ${driveId}`);
|
|
12571
|
+
const transmitter = new SwitchboardPushTransmitter(zodListener.callInfo?.data ?? "");
|
|
12572
|
+
this.logger.verbose(`[SYNC DEBUG] Created SwitchboardPush transmitter with URL: ${zodListener.callInfo?.data || "none"}`);
|
|
12573
|
+
await this.listenerManager.setListener(driveId, {
|
|
12574
|
+
block: zodListener.block,
|
|
12575
|
+
driveId: drive.state.global.id,
|
|
12576
|
+
filter: {
|
|
12577
|
+
branch: zodListener.filter?.branch ?? [],
|
|
12578
|
+
documentId: zodListener.filter?.documentId ?? [],
|
|
12579
|
+
documentType: zodListener.filter?.documentType ?? [],
|
|
12580
|
+
scope: zodListener.filter?.scope ?? []
|
|
12581
|
+
},
|
|
12582
|
+
listenerId: zodListener.listenerId,
|
|
12583
|
+
callInfo: zodListener.callInfo,
|
|
12584
|
+
system: zodListener.system,
|
|
12585
|
+
label: zodListener.label ?? "",
|
|
12586
|
+
transmitter
|
|
12587
|
+
}).then(() => {
|
|
12588
|
+
this.logger.verbose(`[SYNC DEBUG] Successfully set up listener ${zodListener.listenerId} for drive ${driveId}`);
|
|
12589
|
+
});
|
|
12590
|
+
} else if (zodListener.callInfo?.transmitterType === "PullResponder") {
|
|
12591
|
+
this.logger.verbose(`[SYNC DEBUG] Setting up PullResponder listener ${zodListener.listenerId} for drive ${driveId}`);
|
|
12592
|
+
const pullResponderListener = {
|
|
12593
|
+
driveId,
|
|
12594
|
+
listenerId: zodListener.listenerId,
|
|
12595
|
+
block: false,
|
|
12596
|
+
filter: zodListener.filter,
|
|
12597
|
+
system: false,
|
|
12598
|
+
label: `PullResponder #${zodListener.listenerId}`,
|
|
12599
|
+
callInfo: {
|
|
12600
|
+
data: "",
|
|
12601
|
+
name: "PullResponder",
|
|
12602
|
+
transmitterType: "PullResponder"
|
|
12603
|
+
}
|
|
12604
|
+
};
|
|
12605
|
+
const pullResponder = new PullResponderTransmitter(pullResponderListener, this.listenerManager);
|
|
12606
|
+
pullResponderListener.transmitter = pullResponder;
|
|
12607
|
+
await this.listenerManager.setListener(driveId, pullResponderListener);
|
|
12608
|
+
} else {
|
|
12609
|
+
this.logger.error(`Skipping listener ${zodListener.listenerId} with unsupported type ${zodListener.callInfo?.transmitterType || "unknown"}`);
|
|
12610
|
+
}
|
|
12611
|
+
}
|
|
12342
12612
|
}
|
|
12343
12613
|
// Delegate synchronization methods to synchronizationManager
|
|
12344
12614
|
getSynchronizationUnits(driveId, documentId, scope, branch, documentType2) {
|
|
@@ -12380,7 +12650,7 @@ var BaseDocumentDriveServer = class {
|
|
|
12380
12650
|
};
|
|
12381
12651
|
await this.storage.createDrive(id, document);
|
|
12382
12652
|
if (input.global.slug) {
|
|
12383
|
-
await this.cache.
|
|
12653
|
+
await this.cache.deleteDriveBySlug(input.global.slug);
|
|
12384
12654
|
}
|
|
12385
12655
|
await this._initializeDrive(id);
|
|
12386
12656
|
this.eventEmitter.emit("driveAdded", document);
|
|
@@ -12412,7 +12682,7 @@ var BaseDocumentDriveServer = class {
|
|
|
12412
12682
|
const result = await Promise.allSettled([
|
|
12413
12683
|
this.stopSyncRemoteDrive(driveId),
|
|
12414
12684
|
this.listenerManager.removeDrive(driveId),
|
|
12415
|
-
this.cache.
|
|
12685
|
+
this.cache.deleteDrive(driveId),
|
|
12416
12686
|
this.storage.deleteDrive(driveId)
|
|
12417
12687
|
]);
|
|
12418
12688
|
result.forEach((r) => {
|
|
@@ -12427,7 +12697,7 @@ var BaseDocumentDriveServer = class {
|
|
|
12427
12697
|
async getDrive(driveId, options) {
|
|
12428
12698
|
let document;
|
|
12429
12699
|
try {
|
|
12430
|
-
const cachedDocument = await this.cache.
|
|
12700
|
+
const cachedDocument = await this.cache.getDrive(driveId);
|
|
12431
12701
|
if (cachedDocument && isDocumentDrive(cachedDocument)) {
|
|
12432
12702
|
document = cachedDocument;
|
|
12433
12703
|
if (isAtRevision(document, options?.revisions)) {
|
|
@@ -12435,7 +12705,7 @@ var BaseDocumentDriveServer = class {
|
|
|
12435
12705
|
}
|
|
12436
12706
|
}
|
|
12437
12707
|
} catch (e) {
|
|
12438
|
-
logger.error("Error getting drive from cache", e);
|
|
12708
|
+
this.logger.error("Error getting drive from cache", e);
|
|
12439
12709
|
}
|
|
12440
12710
|
const driveStorage = document ?? await this.storage.getDrive(driveId);
|
|
12441
12711
|
const result = this._buildDocument(driveStorage, options);
|
|
@@ -12443,43 +12713,43 @@ var BaseDocumentDriveServer = class {
|
|
|
12443
12713
|
throw new Error(`Document with id ${driveId} is not a Document Drive`);
|
|
12444
12714
|
} else {
|
|
12445
12715
|
if (!options?.revisions) {
|
|
12446
|
-
this.cache.
|
|
12716
|
+
this.cache.setDrive(driveId, result).catch(this.logger.error);
|
|
12447
12717
|
}
|
|
12448
12718
|
return result;
|
|
12449
12719
|
}
|
|
12450
12720
|
}
|
|
12451
12721
|
async getDriveBySlug(slug, options) {
|
|
12452
12722
|
try {
|
|
12453
|
-
const
|
|
12454
|
-
if (
|
|
12455
|
-
return
|
|
12723
|
+
const drive = await this.cache.getDriveBySlug(slug);
|
|
12724
|
+
if (drive) {
|
|
12725
|
+
return drive;
|
|
12456
12726
|
}
|
|
12457
12727
|
} catch (e) {
|
|
12458
|
-
logger.error("Error getting drive from cache", e);
|
|
12728
|
+
this.logger.error("Error getting drive from cache", e);
|
|
12459
12729
|
}
|
|
12460
12730
|
const driveStorage = await this.storage.getDriveBySlug(slug);
|
|
12461
12731
|
const document = this._buildDocument(driveStorage, options);
|
|
12462
12732
|
if (!isDocumentDrive(document)) {
|
|
12463
12733
|
throw new Error(`Document with slug ${slug} is not a Document Drive`);
|
|
12464
12734
|
} else {
|
|
12465
|
-
this.cache.
|
|
12735
|
+
this.cache.setDriveBySlug(slug, document).catch(this.logger.error);
|
|
12466
12736
|
return document;
|
|
12467
12737
|
}
|
|
12468
12738
|
}
|
|
12469
12739
|
async getDocument(driveId, documentId, options) {
|
|
12470
12740
|
let cachedDocument;
|
|
12471
12741
|
try {
|
|
12472
|
-
cachedDocument = await this.cache.getDocument(
|
|
12742
|
+
cachedDocument = await this.cache.getDocument(documentId);
|
|
12473
12743
|
if (cachedDocument && isAtRevision(cachedDocument, options?.revisions)) {
|
|
12474
12744
|
return cachedDocument;
|
|
12475
12745
|
}
|
|
12476
12746
|
} catch (e) {
|
|
12477
|
-
logger.error("Error getting document from cache", e);
|
|
12747
|
+
this.logger.error("Error getting document from cache", e);
|
|
12478
12748
|
}
|
|
12479
12749
|
const documentStorage = cachedDocument ?? await this.storage.getDocument(driveId, documentId);
|
|
12480
12750
|
const document = this._buildDocument(documentStorage, options);
|
|
12481
12751
|
if (!options?.revisions) {
|
|
12482
|
-
this.cache.setDocument(
|
|
12752
|
+
this.cache.setDocument(documentId, document).catch(this.logger.error);
|
|
12483
12753
|
}
|
|
12484
12754
|
return document;
|
|
12485
12755
|
}
|
|
@@ -12534,9 +12804,9 @@ var BaseDocumentDriveServer = class {
|
|
|
12534
12804
|
}
|
|
12535
12805
|
await this.listenerManager.removeSyncUnits(driveId, syncUnits);
|
|
12536
12806
|
} catch (error) {
|
|
12537
|
-
logger.warn("Error deleting document", error);
|
|
12807
|
+
this.logger.warn("Error deleting document", error);
|
|
12538
12808
|
}
|
|
12539
|
-
await this.cache.deleteDocument(
|
|
12809
|
+
await this.cache.deleteDocument(documentId);
|
|
12540
12810
|
return this.storage.deleteDocument(driveId, documentId);
|
|
12541
12811
|
}
|
|
12542
12812
|
async _processOperations(driveId, documentId, documentStorage, operations) {
|
|
@@ -12706,33 +12976,35 @@ var BaseDocumentDriveServer = class {
|
|
|
12706
12976
|
if (result) {
|
|
12707
12977
|
return result;
|
|
12708
12978
|
}
|
|
12979
|
+
let jobId;
|
|
12980
|
+
const promise = new Promise((resolve, reject) => {
|
|
12981
|
+
const unsubscribe = this.queueManager.on("jobCompleted", (job, result2) => {
|
|
12982
|
+
if (job.jobId === jobId) {
|
|
12983
|
+
unsubscribe();
|
|
12984
|
+
unsubscribeError();
|
|
12985
|
+
resolve(result2);
|
|
12986
|
+
}
|
|
12987
|
+
});
|
|
12988
|
+
const unsubscribeError = this.queueManager.on("jobFailed", (job, error) => {
|
|
12989
|
+
if (job.jobId === jobId) {
|
|
12990
|
+
unsubscribe();
|
|
12991
|
+
unsubscribeError();
|
|
12992
|
+
reject(error);
|
|
12993
|
+
}
|
|
12994
|
+
});
|
|
12995
|
+
});
|
|
12709
12996
|
try {
|
|
12710
|
-
|
|
12997
|
+
jobId = await this.queueManager.addJob({
|
|
12711
12998
|
driveId,
|
|
12712
12999
|
documentId,
|
|
12713
13000
|
operations,
|
|
12714
13001
|
options
|
|
12715
13002
|
});
|
|
12716
|
-
return new Promise((resolve, reject) => {
|
|
12717
|
-
const unsubscribe = this.queueManager.on("jobCompleted", (job, result2) => {
|
|
12718
|
-
if (job.jobId === jobId) {
|
|
12719
|
-
unsubscribe();
|
|
12720
|
-
unsubscribeError();
|
|
12721
|
-
resolve(result2);
|
|
12722
|
-
}
|
|
12723
|
-
});
|
|
12724
|
-
const unsubscribeError = this.queueManager.on("jobFailed", (job, error) => {
|
|
12725
|
-
if (job.jobId === jobId) {
|
|
12726
|
-
unsubscribe();
|
|
12727
|
-
unsubscribeError();
|
|
12728
|
-
reject(error);
|
|
12729
|
-
}
|
|
12730
|
-
});
|
|
12731
|
-
});
|
|
12732
13003
|
} catch (error) {
|
|
12733
|
-
logger.error("Error adding job", error);
|
|
13004
|
+
this.logger.error("Error adding job", error);
|
|
12734
13005
|
throw error;
|
|
12735
13006
|
}
|
|
13007
|
+
return promise;
|
|
12736
13008
|
}
|
|
12737
13009
|
async queueAction(driveId, documentId, action, options) {
|
|
12738
13010
|
return this.queueActions(driveId, documentId, [action], options);
|
|
@@ -12762,7 +13034,7 @@ var BaseDocumentDriveServer = class {
|
|
|
12762
13034
|
});
|
|
12763
13035
|
});
|
|
12764
13036
|
} catch (error) {
|
|
12765
|
-
logger.error("Error adding job", error);
|
|
13037
|
+
this.logger.error("Error adding job", error);
|
|
12766
13038
|
throw error;
|
|
12767
13039
|
}
|
|
12768
13040
|
}
|
|
@@ -12793,7 +13065,7 @@ var BaseDocumentDriveServer = class {
|
|
|
12793
13065
|
});
|
|
12794
13066
|
});
|
|
12795
13067
|
} catch (error) {
|
|
12796
|
-
logger.error("Error adding drive job", error);
|
|
13068
|
+
this.logger.error("Error adding drive job", error);
|
|
12797
13069
|
throw error;
|
|
12798
13070
|
}
|
|
12799
13071
|
}
|
|
@@ -12810,7 +13082,7 @@ var BaseDocumentDriveServer = class {
|
|
|
12810
13082
|
await this._addOperations(driveId, documentId, async (documentStorage) => {
|
|
12811
13083
|
const result2 = await this._processOperations(driveId, documentId, documentStorage, operations);
|
|
12812
13084
|
if (!result2.document) {
|
|
12813
|
-
logger.error("Invalid document");
|
|
13085
|
+
this.logger.error("Invalid document");
|
|
12814
13086
|
throw result2.error ?? new Error("Invalid document");
|
|
12815
13087
|
}
|
|
12816
13088
|
document = result2.document;
|
|
@@ -12824,7 +13096,7 @@ var BaseDocumentDriveServer = class {
|
|
|
12824
13096
|
};
|
|
12825
13097
|
});
|
|
12826
13098
|
if (document) {
|
|
12827
|
-
this.cache.setDocument(
|
|
13099
|
+
this.cache.setDocument(documentId, document).catch(this.logger.error);
|
|
12828
13100
|
}
|
|
12829
13101
|
const { scopes, branches } = operationsApplied.reduce((acc, operation) => {
|
|
12830
13102
|
if (!acc.scopes.includes(operation.scope)) {
|
|
@@ -12857,7 +13129,7 @@ var BaseDocumentDriveServer = class {
|
|
|
12857
13129
|
});
|
|
12858
13130
|
}
|
|
12859
13131
|
}).catch((error2) => {
|
|
12860
|
-
logger.error("Non handled error updating sync revision", error2);
|
|
13132
|
+
this.logger.error("Non handled error updating sync revision", error2);
|
|
12861
13133
|
this.synchronizationManager.updateSyncStatus(driveId, {
|
|
12862
13134
|
[operationSource]: "ERROR"
|
|
12863
13135
|
}, error2);
|
|
@@ -12958,7 +13230,7 @@ var BaseDocumentDriveServer = class {
|
|
|
12958
13230
|
});
|
|
12959
13231
|
});
|
|
12960
13232
|
} catch (error) {
|
|
12961
|
-
logger.error("Error adding drive job", error);
|
|
13233
|
+
this.logger.error("Error adding drive job", error);
|
|
12962
13234
|
throw error;
|
|
12963
13235
|
}
|
|
12964
13236
|
}
|
|
@@ -12986,7 +13258,7 @@ var BaseDocumentDriveServer = class {
|
|
|
12986
13258
|
if (!document || !isDocumentDrive(document)) {
|
|
12987
13259
|
throw error ?? new Error("Invalid Document Drive document");
|
|
12988
13260
|
}
|
|
12989
|
-
this.cache.
|
|
13261
|
+
this.cache.setDrive(driveId, document).catch(this.logger.error);
|
|
12990
13262
|
const lastOperation = operationsApplied.filter((op) => op.scope === "global").slice().pop();
|
|
12991
13263
|
if (lastOperation) {
|
|
12992
13264
|
const newOp = operationsApplied.find((appliedOp) => !operations.find((o) => o.id === appliedOp.id && o.index === appliedOp.index && o.skip === appliedOp.skip && o.hash === appliedOp.hash));
|
|
@@ -12995,7 +13267,6 @@ var BaseDocumentDriveServer = class {
|
|
|
12995
13267
|
this.listenerManager.updateSynchronizationRevisions(driveId, [
|
|
12996
13268
|
{
|
|
12997
13269
|
syncId: "0",
|
|
12998
|
-
driveId,
|
|
12999
13270
|
documentId: "",
|
|
13000
13271
|
scope: "global",
|
|
13001
13272
|
branch: "main",
|
|
@@ -13014,7 +13285,7 @@ var BaseDocumentDriveServer = class {
|
|
|
13014
13285
|
});
|
|
13015
13286
|
}
|
|
13016
13287
|
}).catch((error2) => {
|
|
13017
|
-
logger.error("Non handled error updating sync revision", error2);
|
|
13288
|
+
this.logger.error("Non handled error updating sync revision", error2);
|
|
13018
13289
|
this.synchronizationManager.updateSyncStatus(driveId, {
|
|
13019
13290
|
[operationSource]: "ERROR"
|
|
13020
13291
|
}, error2);
|
|
@@ -13116,9 +13387,26 @@ var BaseDocumentDriveServer = class {
|
|
|
13116
13387
|
scope: strand.scope,
|
|
13117
13388
|
branch: strand.branch
|
|
13118
13389
|
}));
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
|
|
13390
|
+
let result;
|
|
13391
|
+
if (strand.documentId) {
|
|
13392
|
+
try {
|
|
13393
|
+
result = await this.queueOperations(strand.driveId, strand.documentId, operations, {
|
|
13394
|
+
source
|
|
13395
|
+
});
|
|
13396
|
+
} catch (error) {
|
|
13397
|
+
this.logger.error("Error queueing operations", error);
|
|
13398
|
+
throw error;
|
|
13399
|
+
}
|
|
13400
|
+
} else {
|
|
13401
|
+
try {
|
|
13402
|
+
result = await this.queueDriveOperations(strand.driveId, operations, {
|
|
13403
|
+
source
|
|
13404
|
+
});
|
|
13405
|
+
} catch (error) {
|
|
13406
|
+
this.logger.error("Error queueing operations", error);
|
|
13407
|
+
throw error;
|
|
13408
|
+
}
|
|
13409
|
+
}
|
|
13122
13410
|
if (result.status === "ERROR") {
|
|
13123
13411
|
const syncUnits = strand.documentId !== "" ? (await this.getSynchronizationUnitsIds(strand.driveId, [strand.documentId], [strand.scope], [strand.branch])).map((s) => s.syncId) : [strand.driveId];
|
|
13124
13412
|
const operationSource = this.getOperationSource(source);
|
|
@@ -13290,11 +13578,10 @@ var ListenerManager = class _ListenerManager {
|
|
|
13290
13578
|
throw new Error("Maximum retries exhausted.");
|
|
13291
13579
|
}
|
|
13292
13580
|
const listenerUpdates = [];
|
|
13293
|
-
for (const [driveId,
|
|
13294
|
-
for (const [listenerId, listenerState] of
|
|
13581
|
+
for (const [driveId, listenerStateById] of this.listenerStateByDriveId) {
|
|
13582
|
+
for (const [listenerId, listenerState] of listenerStateById) {
|
|
13295
13583
|
const transmitter = listenerState.listener.transmitter;
|
|
13296
13584
|
if (!transmitter?.transmit) {
|
|
13297
|
-
this.logger.verbose(`Transmitter not set on listener: ${listenerId}`);
|
|
13298
13585
|
continue;
|
|
13299
13586
|
}
|
|
13300
13587
|
const syncUnits = await this.getListenerSyncUnits(driveId, listenerId);
|
|
@@ -13306,7 +13593,7 @@ var ListenerManager = class _ListenerManager {
|
|
|
13306
13593
|
this.logger.verbose(`Abandoning push for sync unit ${syncUnit.syncId}: already up-to-date (${unitState.listenerRev} >= ${syncUnit.revision})`);
|
|
13307
13594
|
return;
|
|
13308
13595
|
} else {
|
|
13309
|
-
this.logger.verbose(`Listener out-of-date for sync unit (${syncUnit.
|
|
13596
|
+
this.logger.verbose(`Listener out-of-date for sync unit (${syncUnit.scope}, ${syncUnit.documentId}): ${unitState?.listenerRev} < ${syncUnit.revision}`);
|
|
13310
13597
|
}
|
|
13311
13598
|
const opData = [];
|
|
13312
13599
|
try {
|
|
@@ -13445,57 +13732,78 @@ var ListenerManager = class _ListenerManager {
|
|
|
13445
13732
|
}
|
|
13446
13733
|
}
|
|
13447
13734
|
async getStrands(driveId, listenerId, options) {
|
|
13448
|
-
|
|
13735
|
+
this.logger.verbose(`[SYNC DEBUG] ListenerManager.getStrands called for drive: ${driveId}, listener: ${listenerId}, options: ${JSON.stringify(options || {})}`);
|
|
13736
|
+
let listenerState;
|
|
13737
|
+
try {
|
|
13738
|
+
listenerState = this.getListenerState(driveId, listenerId);
|
|
13739
|
+
this.logger.verbose(`[SYNC DEBUG] Found listener state for drive: ${driveId}, listener: ${listenerId}, status: ${listenerState.listenerStatus}`);
|
|
13740
|
+
} catch (error) {
|
|
13741
|
+
this.logger.error(`[SYNC DEBUG] Failed to find listener state for drive: ${driveId}, listener: ${listenerId}. Error: ${error}`);
|
|
13742
|
+
throw error;
|
|
13743
|
+
}
|
|
13449
13744
|
const strands = [];
|
|
13450
|
-
|
|
13451
|
-
|
|
13452
|
-
|
|
13453
|
-
|
|
13454
|
-
|
|
13455
|
-
|
|
13456
|
-
|
|
13457
|
-
|
|
13458
|
-
|
|
13459
|
-
|
|
13460
|
-
|
|
13461
|
-
|
|
13462
|
-
|
|
13463
|
-
|
|
13464
|
-
|
|
13465
|
-
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
{
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
|
|
13745
|
+
try {
|
|
13746
|
+
const syncUnits = await this.getListenerSyncUnits(driveId, listenerId);
|
|
13747
|
+
this.logger.verbose(`[SYNC DEBUG] Retrieved ${syncUnits.length} sync units for drive: ${driveId}, listener: ${listenerId}`);
|
|
13748
|
+
const limit = options?.limit;
|
|
13749
|
+
let operationsCount = 0;
|
|
13750
|
+
const tasks = syncUnits.map((syncUnit) => async () => {
|
|
13751
|
+
if (limit && operationsCount >= limit) {
|
|
13752
|
+
return;
|
|
13753
|
+
}
|
|
13754
|
+
if (syncUnit.revision < 0) {
|
|
13755
|
+
this.logger.verbose(`[SYNC DEBUG] Skipping sync unit with negative revision: ${syncUnit.syncId}, revision: ${syncUnit.revision}`);
|
|
13756
|
+
return;
|
|
13757
|
+
}
|
|
13758
|
+
const entry = listenerState.syncUnits.get(syncUnit.syncId);
|
|
13759
|
+
if (entry && entry.listenerRev >= syncUnit.revision) {
|
|
13760
|
+
this.logger.verbose(`[SYNC DEBUG] Skipping sync unit - listener already up to date: ${syncUnit.syncId}, listenerRev: ${entry.listenerRev}, revision: ${syncUnit.revision}`);
|
|
13761
|
+
return;
|
|
13762
|
+
}
|
|
13763
|
+
const { documentId, scope, branch } = syncUnit;
|
|
13764
|
+
try {
|
|
13765
|
+
this.logger.verbose(`[SYNC DEBUG] Getting operations for syncUnit: ${syncUnit.syncId}, documentId: ${documentId}, scope: ${scope}, branch: ${branch}`);
|
|
13766
|
+
const operations = await this.syncManager.getOperationData(
|
|
13767
|
+
// DEAL WITH INVALID SYNC ID ERROR
|
|
13768
|
+
driveId,
|
|
13769
|
+
syncUnit.syncId,
|
|
13770
|
+
{
|
|
13771
|
+
since: options?.since,
|
|
13772
|
+
fromRevision: options?.fromRevision ?? entry?.listenerRev,
|
|
13773
|
+
limit: limit ? limit - operationsCount : void 0
|
|
13774
|
+
}
|
|
13775
|
+
);
|
|
13776
|
+
this.logger.verbose(`[SYNC DEBUG] Retrieved ${operations.length} operations for syncUnit: ${syncUnit.syncId}`);
|
|
13777
|
+
if (!operations.length) {
|
|
13778
|
+
return;
|
|
13474
13779
|
}
|
|
13475
|
-
|
|
13476
|
-
|
|
13780
|
+
operationsCount += operations.length;
|
|
13781
|
+
strands.push({
|
|
13782
|
+
driveId,
|
|
13783
|
+
documentId,
|
|
13784
|
+
scope,
|
|
13785
|
+
branch,
|
|
13786
|
+
operations
|
|
13787
|
+
});
|
|
13788
|
+
this.logger.verbose(`[SYNC DEBUG] Added strand with ${operations.length} operations for syncUnit: ${syncUnit.syncId}`);
|
|
13789
|
+
} catch (error) {
|
|
13790
|
+
this.logger.error(`Error getting operations for syncUnit: ${syncUnit.syncId}, error: ${error}`);
|
|
13477
13791
|
return;
|
|
13478
13792
|
}
|
|
13479
|
-
|
|
13480
|
-
|
|
13481
|
-
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
|
|
13486
|
-
});
|
|
13487
|
-
|
|
13488
|
-
this.logger.error(error);
|
|
13489
|
-
return;
|
|
13490
|
-
}
|
|
13491
|
-
});
|
|
13492
|
-
if (this.options.sequentialUpdates) {
|
|
13493
|
-
for (const task of tasks) {
|
|
13494
|
-
await task();
|
|
13793
|
+
});
|
|
13794
|
+
if (this.options.sequentialUpdates) {
|
|
13795
|
+
this.logger.verbose(`[SYNC DEBUG] Processing ${tasks.length} sync units sequentially`);
|
|
13796
|
+
for (const task of tasks) {
|
|
13797
|
+
await task();
|
|
13798
|
+
}
|
|
13799
|
+
} else {
|
|
13800
|
+
this.logger.verbose(`[SYNC DEBUG] Processing ${tasks.length} sync units in parallel`);
|
|
13801
|
+
await Promise.all(tasks.map((task) => task()));
|
|
13495
13802
|
}
|
|
13496
|
-
}
|
|
13497
|
-
|
|
13803
|
+
} catch (error) {
|
|
13804
|
+
this.logger.error(`Error in getStrands: ${error}`);
|
|
13498
13805
|
}
|
|
13806
|
+
this.logger.verbose(`ListenerManager.getStrands returning ${strands.length} strands for drive: ${driveId}, listener: ${listenerId}`);
|
|
13499
13807
|
return strands;
|
|
13500
13808
|
}
|
|
13501
13809
|
getListenerState(driveId, listenerId) {
|
|
@@ -13520,80 +13828,6 @@ var ListenerManager = class _ListenerManager {
|
|
|
13520
13828
|
}
|
|
13521
13829
|
};
|
|
13522
13830
|
|
|
13523
|
-
// ../../packages/document-drive/dist/src/server/listener/transmitter/switchboard-push.js
|
|
13524
|
-
var import_json_stringify_deterministic = __toESM(require_lib(), 1);
|
|
13525
|
-
var SYNC_OPS_BATCH_LIMIT = 10;
|
|
13526
|
-
var SwitchboardPushTransmitter = class {
|
|
13527
|
-
targetURL;
|
|
13528
|
-
logger = childLogger([
|
|
13529
|
-
"SwitchboardPushTransmitter",
|
|
13530
|
-
Math.floor(Math.random() * 999).toString()
|
|
13531
|
-
]);
|
|
13532
|
-
constructor(targetURL) {
|
|
13533
|
-
this.targetURL = targetURL;
|
|
13534
|
-
}
|
|
13535
|
-
async transmit(strands, source) {
|
|
13536
|
-
if (source.type === "trigger" && source.trigger.data?.url === this.targetURL) {
|
|
13537
|
-
this.logger.verbose(`Cutting trigger loop from ${this.targetURL}.`);
|
|
13538
|
-
return strands.map((strand) => ({
|
|
13539
|
-
driveId: strand.driveId,
|
|
13540
|
-
documentId: strand.documentId,
|
|
13541
|
-
scope: strand.scope,
|
|
13542
|
-
branch: strand.branch,
|
|
13543
|
-
status: "SUCCESS",
|
|
13544
|
-
revision: strand.operations.at(-1)?.index ?? -1
|
|
13545
|
-
}));
|
|
13546
|
-
}
|
|
13547
|
-
const culledStrands = [];
|
|
13548
|
-
let opsCounter = 0;
|
|
13549
|
-
for (let s = 0; opsCounter <= SYNC_OPS_BATCH_LIMIT && s < strands.length; s++) {
|
|
13550
|
-
const currentStrand = strands.at(s);
|
|
13551
|
-
if (!currentStrand) {
|
|
13552
|
-
break;
|
|
13553
|
-
}
|
|
13554
|
-
const newOps = Math.min(SYNC_OPS_BATCH_LIMIT - opsCounter, currentStrand.operations.length);
|
|
13555
|
-
culledStrands.push({
|
|
13556
|
-
...currentStrand,
|
|
13557
|
-
operations: currentStrand.operations.slice(0, newOps)
|
|
13558
|
-
});
|
|
13559
|
-
opsCounter += newOps;
|
|
13560
|
-
}
|
|
13561
|
-
this.logger.verbose(` Total update: [${strands.map((s) => s.operations.length).join(", ")}] operations`);
|
|
13562
|
-
this.logger.verbose(`Culled update: [${culledStrands.map((s) => s.operations.length).join(", ")}] operations`);
|
|
13563
|
-
try {
|
|
13564
|
-
const { pushUpdates } = await requestGraphql(this.targetURL, gql`
|
|
13565
|
-
mutation pushUpdates($strands: [InputStrandUpdate!]) {
|
|
13566
|
-
pushUpdates(strands: $strands) {
|
|
13567
|
-
driveId
|
|
13568
|
-
documentId
|
|
13569
|
-
scope
|
|
13570
|
-
branch
|
|
13571
|
-
status
|
|
13572
|
-
revision
|
|
13573
|
-
error
|
|
13574
|
-
}
|
|
13575
|
-
}
|
|
13576
|
-
`, {
|
|
13577
|
-
strands: culledStrands.map((strand) => ({
|
|
13578
|
-
...strand,
|
|
13579
|
-
operations: strand.operations.map((op) => ({
|
|
13580
|
-
...op,
|
|
13581
|
-
input: (0, import_json_stringify_deterministic.default)(op.input)
|
|
13582
|
-
}))
|
|
13583
|
-
}))
|
|
13584
|
-
});
|
|
13585
|
-
if (!pushUpdates) {
|
|
13586
|
-
throw new Error("Couldn't update listener revision");
|
|
13587
|
-
}
|
|
13588
|
-
return pushUpdates;
|
|
13589
|
-
} catch (e) {
|
|
13590
|
-
this.logger.error(e);
|
|
13591
|
-
throw e;
|
|
13592
|
-
}
|
|
13593
|
-
return [];
|
|
13594
|
-
}
|
|
13595
|
-
};
|
|
13596
|
-
|
|
13597
13831
|
// ../../packages/document-drive/dist/src/server/listener/transmitter/factory.js
|
|
13598
13832
|
var TransmitterFactory = class {
|
|
13599
13833
|
listenerManager;
|
|
@@ -13634,18 +13868,20 @@ var SynchronizationManager = class {
|
|
|
13634
13868
|
}
|
|
13635
13869
|
async getSynchronizationUnits(driveId, documentId, scope, branch, documentType2) {
|
|
13636
13870
|
const synchronizationUnitsQuery = await this.getSynchronizationUnitsIds(driveId, documentId, scope, branch, documentType2);
|
|
13871
|
+
this.logger.verbose(`getSynchronizationUnits query: ${JSON.stringify(synchronizationUnitsQuery)}`);
|
|
13637
13872
|
return this.getSynchronizationUnitsRevision(driveId, synchronizationUnitsQuery);
|
|
13638
13873
|
}
|
|
13639
13874
|
async getSynchronizationUnitsRevision(driveId, syncUnitsQuery) {
|
|
13640
13875
|
const drive = await this.getDrive(driveId);
|
|
13641
13876
|
const revisions = await this.storage.getSynchronizationUnitsRevision(syncUnitsQuery);
|
|
13877
|
+
this.logger.verbose(`getSynchronizationUnitsRevision: ${JSON.stringify(revisions)}`);
|
|
13642
13878
|
const synchronizationUnits = syncUnitsQuery.map((s) => ({
|
|
13643
13879
|
...s,
|
|
13644
13880
|
lastUpdated: drive.created,
|
|
13645
13881
|
revision: -1
|
|
13646
13882
|
}));
|
|
13647
13883
|
for (const revision of revisions) {
|
|
13648
|
-
const syncUnit = synchronizationUnits.find((s) => revision.
|
|
13884
|
+
const syncUnit = synchronizationUnits.find((s) => revision.documentId === s.documentId && revision.scope === s.scope && revision.branch === s.branch);
|
|
13649
13885
|
if (syncUnit) {
|
|
13650
13886
|
syncUnit.revision = revision.revision;
|
|
13651
13887
|
syncUnit.lastUpdated = revision.lastUpdated;
|
|
@@ -13658,7 +13894,7 @@ var SynchronizationManager = class {
|
|
|
13658
13894
|
const nodes = drive.state.global.nodes.filter((node) => isFileNode(node) && (!documentId?.length || documentId.includes(node.id) || documentId.includes("*")) && (!documentType2?.length || documentType2.includes(node.documentType) || documentType2.includes("*")));
|
|
13659
13895
|
if ((!documentId || documentId.includes("*") || documentId.includes("")) && (!documentType2?.length || documentType2.includes("powerhouse/document-drive") || documentType2.includes("*"))) {
|
|
13660
13896
|
nodes.unshift({
|
|
13661
|
-
id:
|
|
13897
|
+
id: driveId,
|
|
13662
13898
|
documentType: "powerhouse/document-drive",
|
|
13663
13899
|
synchronizationUnits: [
|
|
13664
13900
|
{
|
|
@@ -13700,7 +13936,6 @@ var SynchronizationManager = class {
|
|
|
13700
13936
|
syncId,
|
|
13701
13937
|
scope: syncUnit.scope,
|
|
13702
13938
|
branch: syncUnit.branch,
|
|
13703
|
-
driveId,
|
|
13704
13939
|
documentId: node.id,
|
|
13705
13940
|
documentType: node.documentType
|
|
13706
13941
|
};
|
|
@@ -13718,7 +13953,6 @@ var SynchronizationManager = class {
|
|
|
13718
13953
|
syncId,
|
|
13719
13954
|
scope,
|
|
13720
13955
|
branch,
|
|
13721
|
-
driveId,
|
|
13722
13956
|
documentId,
|
|
13723
13957
|
documentType: documentType2,
|
|
13724
13958
|
lastUpdated: lastOperation.timestamp ?? document.lastModified,
|
|
@@ -13726,14 +13960,27 @@ var SynchronizationManager = class {
|
|
|
13726
13960
|
};
|
|
13727
13961
|
}
|
|
13728
13962
|
async getOperationData(driveId, syncId, filter) {
|
|
13963
|
+
this.logger.verbose(`[SYNC DEBUG] SynchronizationManager.getOperationData called for drive: ${driveId}, syncId: ${syncId}, filter: ${JSON.stringify(filter)}`);
|
|
13729
13964
|
const syncUnit = syncId === "0" ? { documentId: "", scope: "global" } : await this.getSynchronizationUnitIdInfo(driveId, syncId);
|
|
13730
13965
|
if (!syncUnit) {
|
|
13966
|
+
this.logger.error(`SYNC DEBUG] Invalid Sync Id ${syncId} in drive ${driveId}`);
|
|
13731
13967
|
throw new Error(`Invalid Sync Id ${syncId} in drive ${driveId}`);
|
|
13732
13968
|
}
|
|
13969
|
+
this.logger.verbose(`[SYNC DEBUG] Found sync unit: documentId: ${syncUnit.documentId}, scope: ${syncUnit.scope}`);
|
|
13733
13970
|
const document = syncId === "0" ? await this.getDrive(driveId) : await this.getDocument(driveId, syncUnit.documentId);
|
|
13971
|
+
this.logger.verbose(`[SYNC DEBUG] Retrieved document ${syncUnit.documentId} with type: ${document.documentType}`);
|
|
13734
13972
|
const operations = document.operations[syncUnit.scope] ?? [];
|
|
13973
|
+
this.logger.verbose(`[SYNC DEBUG] Found ${operations.length} total operations in scope ${syncUnit.scope}`);
|
|
13735
13974
|
const filteredOperations = operations.filter((operation) => Object.keys(filter).length === 0 || (filter.since === void 0 || isBefore(filter.since, operation.timestamp)) && (filter.fromRevision === void 0 || operation.index > filter.fromRevision));
|
|
13975
|
+
this.logger.verbose(`[SYNC DEBUG] Filtered to ${filteredOperations.length} operations based on filter criteria` + (filter.fromRevision !== void 0 ? ` (fromRevision: ${filter.fromRevision})` : ""));
|
|
13736
13976
|
const limitedOperations = filter.limit ? filteredOperations.slice(0, filter.limit) : filteredOperations;
|
|
13977
|
+
this.logger.verbose(`[SYNC DEBUG] Returning ${limitedOperations.length} operations after applying limit`);
|
|
13978
|
+
if (limitedOperations.length > 0) {
|
|
13979
|
+
const firstOp = limitedOperations[0];
|
|
13980
|
+
const lastOp = limitedOperations[limitedOperations.length - 1];
|
|
13981
|
+
this.logger.verbose(`[SYNC DEBUG] First operation: index=${firstOp.index}, type=${firstOp.type}`);
|
|
13982
|
+
this.logger.verbose(`[SYNC DEBUG] Last operation: index=${lastOp.index}, type=${lastOp.type}`);
|
|
13983
|
+
}
|
|
13737
13984
|
return limitedOperations.map((operation) => ({
|
|
13738
13985
|
hash: operation.hash,
|
|
13739
13986
|
index: operation.index,
|
|
@@ -13747,7 +13994,7 @@ var SynchronizationManager = class {
|
|
|
13747
13994
|
}
|
|
13748
13995
|
async getDrive(driveId) {
|
|
13749
13996
|
try {
|
|
13750
|
-
const cachedDocument = await this.cache.
|
|
13997
|
+
const cachedDocument = await this.cache.getDrive(driveId);
|
|
13751
13998
|
if (cachedDocument && isDocumentDrive(cachedDocument)) {
|
|
13752
13999
|
return cachedDocument;
|
|
13753
14000
|
}
|
|
@@ -13763,7 +14010,7 @@ var SynchronizationManager = class {
|
|
|
13763
14010
|
}
|
|
13764
14011
|
async getDocument(driveId, documentId) {
|
|
13765
14012
|
try {
|
|
13766
|
-
const cachedDocument = await this.cache.getDocument(
|
|
14013
|
+
const cachedDocument = await this.cache.getDocument(documentId);
|
|
13767
14014
|
if (cachedDocument) {
|
|
13768
14015
|
return cachedDocument;
|
|
13769
14016
|
}
|