@automerge/automerge-repo 2.5.0 → 2.5.2-alpha.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/dist/Presence.d.ts +245 -0
- package/dist/Presence.d.ts.map +1 -0
- package/dist/Presence.js +526 -0
- package/dist/Repo.d.ts +1 -0
- package/dist/Repo.d.ts.map +1 -1
- package/dist/Repo.js +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/synchronizer/CollectionSynchronizer.d.ts +8 -0
- package/dist/synchronizer/CollectionSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/CollectionSynchronizer.js +48 -1
- package/dist/synchronizer/DocSynchronizer.js +1 -1
- package/package.json +2 -2
- package/src/Presence.ts +722 -0
- package/src/Repo.ts +4 -0
- package/src/index.ts +8 -0
- package/src/synchronizer/CollectionSynchronizer.ts +61 -1
- package/src/synchronizer/DocSynchronizer.ts +1 -1
- package/test/Presence.test.ts +264 -0
- package/test/Repo.test.ts +47 -168
- package/test/SharePolicy.test.ts +244 -0
- package/test/helpers/awaitState.ts +24 -0
- package/test/helpers/connectRepos.ts +18 -0
- package/test/helpers/pause.ts +3 -0
- package/test/helpers/twoPeers.ts +30 -0
- package/test/helpers/wait.ts +5 -0
- package/test/helpers/waitFor.ts +14 -0
- package/test/helpers/withTimeout.ts +9 -0
|
@@ -14,6 +14,7 @@ export class CollectionSynchronizer extends Synchronizer {
|
|
|
14
14
|
/** Used to determine if the document is know to the Collection and a synchronizer exists or is being set up */
|
|
15
15
|
#docSetUp = {};
|
|
16
16
|
#denylist;
|
|
17
|
+
#hasRequested = new Map();
|
|
17
18
|
constructor(repo, denylist = []) {
|
|
18
19
|
super();
|
|
19
20
|
this.repo = repo;
|
|
@@ -83,6 +84,15 @@ export class CollectionSynchronizer extends Synchronizer {
|
|
|
83
84
|
});
|
|
84
85
|
return;
|
|
85
86
|
}
|
|
87
|
+
// Record the request so that even if access is denied now, we know that the
|
|
88
|
+
// peer requested the document so that if the share policy changes we know
|
|
89
|
+
// to begin syncing with this peer
|
|
90
|
+
if (message.type === "request") {
|
|
91
|
+
if (!this.#hasRequested.has(documentId)) {
|
|
92
|
+
this.#hasRequested.set(documentId, new Set());
|
|
93
|
+
}
|
|
94
|
+
this.#hasRequested.get(documentId)?.add(message.senderId);
|
|
95
|
+
}
|
|
86
96
|
const hasAccess = await this.repo.shareConfig.access(message.senderId, documentId);
|
|
87
97
|
if (!hasAccess) {
|
|
88
98
|
log("access denied");
|
|
@@ -111,6 +121,7 @@ export class CollectionSynchronizer extends Synchronizer {
|
|
|
111
121
|
if (this.#docSetUp[handle.documentId]) {
|
|
112
122
|
return;
|
|
113
123
|
}
|
|
124
|
+
this.#docSetUp[handle.documentId] = true;
|
|
114
125
|
const docSynchronizer = this.#fetchDocSynchronizer(handle);
|
|
115
126
|
void this.#documentGenerousPeers(handle.documentId).then(peers => {
|
|
116
127
|
void docSynchronizer.beginSync(peers);
|
|
@@ -145,6 +156,9 @@ export class CollectionSynchronizer extends Synchronizer {
|
|
|
145
156
|
removePeer(peerId) {
|
|
146
157
|
log(`removing peer ${peerId}`);
|
|
147
158
|
this.#peers.delete(peerId);
|
|
159
|
+
for (const requested of this.#hasRequested.values()) {
|
|
160
|
+
requested.delete(peerId);
|
|
161
|
+
}
|
|
148
162
|
for (const docSynchronizer of Object.values(this.docSynchronizers)) {
|
|
149
163
|
docSynchronizer.endSync(peerId);
|
|
150
164
|
}
|
|
@@ -153,6 +167,38 @@ export class CollectionSynchronizer extends Synchronizer {
|
|
|
153
167
|
get peers() {
|
|
154
168
|
return Array.from(this.#peers);
|
|
155
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Re-evaluates share policy for a document and updates sync accordingly
|
|
172
|
+
*
|
|
173
|
+
* @remarks
|
|
174
|
+
* This is called when the share policy for a document has changed. It re-evaluates
|
|
175
|
+
* which peers should have access and starts/stops synchronization as needed.
|
|
176
|
+
*/
|
|
177
|
+
async reevaluateDocumentShare() {
|
|
178
|
+
const peers = Array.from(this.#peers);
|
|
179
|
+
const docPromises = [];
|
|
180
|
+
for (const docSynchronizer of Object.values(this.docSynchronizers)) {
|
|
181
|
+
const documentId = docSynchronizer.documentId;
|
|
182
|
+
docPromises.push((async () => {
|
|
183
|
+
for (const peerId of peers) {
|
|
184
|
+
const shouldShare = await this.#shouldShare(peerId, documentId);
|
|
185
|
+
const isAlreadySyncing = docSynchronizer.hasPeer(peerId);
|
|
186
|
+
log(`reevaluateDocumentShare: ${peerId} for ${documentId}, shouldShare: ${shouldShare}, isAlreadySyncing: ${isAlreadySyncing}`);
|
|
187
|
+
if (shouldShare && !isAlreadySyncing) {
|
|
188
|
+
log(`reevaluateDocumentShare: starting sync with ${peerId} for ${documentId}`);
|
|
189
|
+
void docSynchronizer.beginSync([peerId]);
|
|
190
|
+
}
|
|
191
|
+
else if (!shouldShare && isAlreadySyncing) {
|
|
192
|
+
log(`reevaluateDocumentShare: stopping sync with ${peerId} for ${documentId}`);
|
|
193
|
+
docSynchronizer.endSync(peerId);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
})().catch(e => {
|
|
197
|
+
console.log(`error reevaluating document share for ${documentId}: ${e}`);
|
|
198
|
+
}));
|
|
199
|
+
}
|
|
200
|
+
await Promise.allSettled(docPromises);
|
|
201
|
+
}
|
|
156
202
|
metrics() {
|
|
157
203
|
return Object.fromEntries(Object.entries(this.docSynchronizers).map(([documentId, synchronizer]) => {
|
|
158
204
|
return [documentId, synchronizer.metrics()];
|
|
@@ -163,6 +209,7 @@ export class CollectionSynchronizer extends Synchronizer {
|
|
|
163
209
|
this.repo.shareConfig.announce(peerId, documentId),
|
|
164
210
|
this.repo.shareConfig.access(peerId, documentId),
|
|
165
211
|
]);
|
|
166
|
-
|
|
212
|
+
const hasRequested = this.#hasRequested.get(documentId)?.has(peerId) ?? false;
|
|
213
|
+
return announce || (access && hasRequested);
|
|
167
214
|
}
|
|
168
215
|
}
|
|
@@ -130,8 +130,8 @@ export class DocSynchronizer extends Synchronizer {
|
|
|
130
130
|
durationMillis: end - start,
|
|
131
131
|
forPeer: peerId,
|
|
132
132
|
});
|
|
133
|
+
this.#setSyncState(peerId, newSyncState);
|
|
133
134
|
if (message) {
|
|
134
|
-
this.#setSyncState(peerId, newSyncState);
|
|
135
135
|
const isNew = A.getHeads(doc).length === 0;
|
|
136
136
|
if (!this.#handle.isReady() &&
|
|
137
137
|
isNew &&
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automerge/automerge-repo",
|
|
3
|
-
"version": "2.5.0",
|
|
3
|
+
"version": "2.5.2-alpha.0",
|
|
4
4
|
"description": "A repository object to manage a collection of automerge documents",
|
|
5
5
|
"repository": "https://github.com/automerge/automerge-repo/tree/master/packages/automerge-repo",
|
|
6
6
|
"author": "Peter van Hardenberg <pvh@pvh.ca>",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"access": "public"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "ba4493efcd7819fe841d3647f28090837792d964"
|
|
63
63
|
}
|