@ours.network/notifications 0.3.1-nightly.6 → 0.3.1-nightly.7
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/resource-views.d.ts +1 -0
- package/dist/resource-views.js +24 -11
- package/package.json +1 -1
package/dist/resource-views.d.ts
CHANGED
package/dist/resource-views.js
CHANGED
|
@@ -33,7 +33,7 @@ class Output {
|
|
|
33
33
|
this.response = response;
|
|
34
34
|
this.failed = failed;
|
|
35
35
|
}
|
|
36
|
-
send(envelope) {
|
|
36
|
+
send(envelope, admitted) {
|
|
37
37
|
if (this.closed)
|
|
38
38
|
return;
|
|
39
39
|
const bytes = Buffer.byteLength(JSON.stringify(envelope));
|
|
@@ -41,6 +41,7 @@ class Output {
|
|
|
41
41
|
this.failed();
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
|
+
admitted?.();
|
|
44
45
|
this.pending.push({ envelope, bytes });
|
|
45
46
|
this.bytes += bytes;
|
|
46
47
|
if (!this.active)
|
|
@@ -67,7 +68,9 @@ class Output {
|
|
|
67
68
|
const { envelope, bytes } = this.pending.shift();
|
|
68
69
|
this.bytes -= bytes;
|
|
69
70
|
const encoded = Buffer.from(JSON.stringify(envelope));
|
|
70
|
-
if (
|
|
71
|
+
if ('views' in envelope)
|
|
72
|
+
await this.write('resource-coverage', envelope);
|
|
73
|
+
else if (encoded.length + 32 <= FRAME)
|
|
71
74
|
await this.write('resource', envelope);
|
|
72
75
|
else {
|
|
73
76
|
const binding = { protocolVersion: 1, id: `${envelope.viewId}:${envelope.subscriptionEpoch}:${envelope.sequence}`,
|
|
@@ -119,9 +122,8 @@ export class NotificationViews {
|
|
|
119
122
|
};
|
|
120
123
|
const output = new Output(response, close);
|
|
121
124
|
const timer = setInterval(() => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}, 2000);
|
|
125
|
+
this.coverage(connection);
|
|
126
|
+
}, 15000);
|
|
125
127
|
timer.unref();
|
|
126
128
|
const connection = { id, principal, user, response, output, controller, views: new Map(), epochs: new Map(), timer, close };
|
|
127
129
|
this.connections.set(id, connection);
|
|
@@ -141,8 +143,7 @@ export class NotificationViews {
|
|
|
141
143
|
continue;
|
|
142
144
|
view.payload = payload;
|
|
143
145
|
view.revision = captured.revision;
|
|
144
|
-
this.emit(connection, view, 'snapshot', captured.payload);
|
|
145
|
-
this.emit(connection, view, 'coverage', { source: this.source(captured.revision) });
|
|
146
|
+
this.emit(connection, view, 'snapshot', captured.payload, this.source(captured.revision));
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
catch {
|
|
@@ -178,9 +179,21 @@ export class NotificationViews {
|
|
|
178
179
|
return { payload: structuredClone({ items, unread: summary.unread, revision: summary.revision, nextCursor,
|
|
179
180
|
summary, delivery: this.store.deliveryStatus(user) }), revision: summary.revision };
|
|
180
181
|
}
|
|
181
|
-
emit(connection, view, kind, payload) {
|
|
182
|
+
emit(connection, view, kind, payload, source) {
|
|
182
183
|
connection.output.send({ protocolVersion: 1, producerGeneration: this.producerGeneration, viewId: view.descriptor.viewId,
|
|
183
|
-
subscriptionEpoch: view.epoch, sequence:
|
|
184
|
+
subscriptionEpoch: view.epoch, sequence: view.sequence + 1, revision: view.revision, baselineId: view.baselineId, kind, payload, ...(source ? { source } : {}) }, () => { view.sequence++; if (source || kind === 'ready')
|
|
185
|
+
view.qualifiedAt = Date.now(); });
|
|
186
|
+
}
|
|
187
|
+
// A shared ordered batch retains each view's own captured revision.
|
|
188
|
+
coverage(connection) {
|
|
189
|
+
const now = Date.now(), eligible = [...connection.views.values()].filter(view => now - view.qualifiedAt >= 15000);
|
|
190
|
+
if (!eligible.length)
|
|
191
|
+
return;
|
|
192
|
+
const views = eligible.map(view => ({ protocolVersion: 1, producerGeneration: this.producerGeneration, viewId: view.descriptor.viewId, subscriptionEpoch: view.epoch, baselineId: view.baselineId, sequence: view.sequence + 1, revision: view.revision, source: this.source(view.revision) }));
|
|
193
|
+
connection.output.send({ protocolVersion: 1, producerGeneration: this.producerGeneration, views }, () => { for (const view of eligible) {
|
|
194
|
+
view.sequence++;
|
|
195
|
+
view.qualifiedAt = now;
|
|
196
|
+
} });
|
|
184
197
|
}
|
|
185
198
|
register(principal, input) {
|
|
186
199
|
const connection = this.get(String(input.connectionId), principal), value = descriptor(input.descriptor), epoch = input.subscriptionEpoch;
|
|
@@ -192,10 +205,10 @@ export class NotificationViews {
|
|
|
192
205
|
throw new HttpError(503, 'resource view capacity');
|
|
193
206
|
const baseline = this.project(connection.user, value);
|
|
194
207
|
const view = { descriptor: value, epoch: epoch, baselineId: randomUUID(), sequence: 0, revision: baseline.revision,
|
|
195
|
-
baseline, payload: contentKey(baseline.payload) };
|
|
208
|
+
baseline, qualifiedAt: Date.now(), payload: contentKey(baseline.payload) };
|
|
196
209
|
connection.views.set(value.viewId, view);
|
|
197
210
|
connection.epochs.set(value.viewId, view.epoch);
|
|
198
|
-
this.emit(connection, view, 'snapshot', baseline.payload);
|
|
211
|
+
this.emit(connection, view, 'snapshot', baseline.payload, this.source(baseline.revision));
|
|
199
212
|
this.emit(connection, view, 'ready', { baselineId: view.baselineId, source: this.source(baseline.revision) });
|
|
200
213
|
return { subscriptionEpoch: view.epoch, baselineId: view.baselineId };
|
|
201
214
|
}
|
package/package.json
CHANGED