@juzi/wechaty-puppet-service 1.0.130 → 1.0.131
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/cjs/src/auth/call-cred.d.ts +2 -2
- package/dist/cjs/src/auth/call-cred.d.ts.map +1 -1
- package/dist/cjs/src/auth/call-cred.js.map +1 -1
- package/dist/cjs/src/client/puppet-service.d.ts +25 -2
- package/dist/cjs/src/client/puppet-service.d.ts.map +1 -1
- package/dist/cjs/src/client/puppet-service.js +389 -124
- package/dist/cjs/src/client/puppet-service.js.map +1 -1
- package/dist/cjs/src/client/room-cache-coordinator.d.ts +14 -0
- package/dist/cjs/src/client/room-cache-coordinator.d.ts.map +1 -0
- package/dist/cjs/src/client/room-cache-coordinator.js +53 -0
- package/dist/cjs/src/client/room-cache-coordinator.js.map +1 -0
- package/dist/cjs/src/client/room-member-cache.spec.d.ts +2 -0
- package/dist/cjs/src/client/room-member-cache.spec.d.ts.map +1 -0
- package/dist/cjs/src/client/room-member-cache.spec.js +417 -0
- package/dist/cjs/src/client/room-member-cache.spec.js.map +1 -0
- package/dist/cjs/src/client/room-member-load.spec.d.ts +2 -0
- package/dist/cjs/src/client/room-member-load.spec.d.ts.map +1 -0
- package/dist/cjs/src/client/room-member-load.spec.js +324 -0
- package/dist/cjs/src/client/room-member-load.spec.js.map +1 -0
- package/dist/cjs/src/package-json.js +4 -4
- package/dist/cjs/src/server/event-stream-manager.d.ts.map +1 -1
- package/dist/cjs/src/server/event-stream-manager.js +16 -0
- package/dist/cjs/src/server/event-stream-manager.js.map +1 -1
- package/dist/cjs/src/server/puppet-implementation.d.ts.map +1 -1
- package/dist/cjs/src/server/puppet-implementation.js +91 -28
- package/dist/cjs/src/server/puppet-implementation.js.map +1 -1
- package/dist/cjs/src/utils/pb-payload-helper.d.ts +10 -0
- package/dist/cjs/src/utils/pb-payload-helper.d.ts.map +1 -1
- package/dist/cjs/src/utils/pb-payload-helper.js +180 -1
- package/dist/cjs/src/utils/pb-payload-helper.js.map +1 -1
- package/dist/cjs/src/utils/room-member-load.spec.d.ts +2 -0
- package/dist/cjs/src/utils/room-member-load.spec.d.ts.map +1 -0
- package/dist/cjs/src/utils/room-member-load.spec.js +83 -0
- package/dist/cjs/src/utils/room-member-load.spec.js.map +1 -0
- package/dist/esm/src/auth/call-cred.d.ts +2 -2
- package/dist/esm/src/auth/call-cred.d.ts.map +1 -1
- package/dist/esm/src/auth/call-cred.js.map +1 -1
- package/dist/esm/src/client/puppet-service.d.ts +25 -2
- package/dist/esm/src/client/puppet-service.d.ts.map +1 -1
- package/dist/esm/src/client/puppet-service.js +390 -125
- package/dist/esm/src/client/puppet-service.js.map +1 -1
- package/dist/esm/src/client/room-cache-coordinator.d.ts +14 -0
- package/dist/esm/src/client/room-cache-coordinator.d.ts.map +1 -0
- package/dist/esm/src/client/room-cache-coordinator.js +49 -0
- package/dist/esm/src/client/room-cache-coordinator.js.map +1 -0
- package/dist/esm/src/client/room-member-cache.spec.d.ts +2 -0
- package/dist/esm/src/client/room-member-cache.spec.d.ts.map +1 -0
- package/dist/esm/src/client/room-member-cache.spec.js +415 -0
- package/dist/esm/src/client/room-member-cache.spec.js.map +1 -0
- package/dist/esm/src/client/room-member-load.spec.d.ts +2 -0
- package/dist/esm/src/client/room-member-load.spec.d.ts.map +1 -0
- package/dist/esm/src/client/room-member-load.spec.js +296 -0
- package/dist/esm/src/client/room-member-load.spec.js.map +1 -0
- package/dist/esm/src/package-json.js +4 -4
- package/dist/esm/src/server/event-stream-manager.d.ts.map +1 -1
- package/dist/esm/src/server/event-stream-manager.js +16 -0
- package/dist/esm/src/server/event-stream-manager.js.map +1 -1
- package/dist/esm/src/server/puppet-implementation.d.ts.map +1 -1
- package/dist/esm/src/server/puppet-implementation.js +92 -29
- package/dist/esm/src/server/puppet-implementation.js.map +1 -1
- package/dist/esm/src/utils/pb-payload-helper.d.ts +10 -0
- package/dist/esm/src/utils/pb-payload-helper.d.ts.map +1 -1
- package/dist/esm/src/utils/pb-payload-helper.js +169 -0
- package/dist/esm/src/utils/pb-payload-helper.js.map +1 -1
- package/dist/esm/src/utils/room-member-load.spec.d.ts +2 -0
- package/dist/esm/src/utils/room-member-load.spec.d.ts.map +1 -0
- package/dist/esm/src/utils/room-member-load.spec.js +58 -0
- package/dist/esm/src/utils/room-member-load.spec.js.map +1 -0
- package/package.json +4 -4
- package/src/auth/call-cred.ts +1 -1
- package/src/client/puppet-service.ts +324 -138
- package/src/client/room-cache-coordinator.ts +50 -0
- package/src/client/room-member-cache.spec.ts +448 -0
- package/src/client/room-member-load.spec.ts +319 -0
- package/src/package-json.ts +4 -4
- package/src/server/event-stream-manager.ts +15 -0
- package/src/server/puppet-implementation.ts +94 -29
- package/src/utils/pb-payload-helper.ts +150 -0
- package/src/utils/room-member-load.spec.ts +67 -0
|
@@ -28,7 +28,8 @@ import { EventTypeRev, } from '../event-type-rev.js';
|
|
|
28
28
|
import { packageJson } from '../package-json.js';
|
|
29
29
|
import { GrpcManager } from './grpc-manager.js';
|
|
30
30
|
import { PayloadStore } from './payload-store.js';
|
|
31
|
-
import {
|
|
31
|
+
import { RoomCacheCoordinator, RoomCacheOperationError } from './room-cache-coordinator.js';
|
|
32
|
+
import { OptionalBooleanUnwrapper, OptionalBooleanWrapper, callRecordPbToPayload, channelPayloadToPb, channelPbToPayload, chatHistoryPbToPayload, contactPbToPayload, postPayloadToPb, roomMemberPbToPayload, urlLinkPbToPayload, channelCardPayloadToPb, channelCardPbToPayload, miniProgramPayloadToPb, urlLinkPayloadToPb, locationPayloadToPb, roomPbToPayload, roomMemberLoadStatePbToPayload, roomMemberSnapshotPbToPayload, validateRoomMemberRevision, validateRoomMemberLoadState } from '../utils/pb-payload-helper.js';
|
|
32
33
|
import { puppetCallMediaTypeToGrpc, grpcCallTypeToPuppetMedia } from '../utils/call-media-mapping.js';
|
|
33
34
|
import { timeoutPromise } from 'gerror';
|
|
34
35
|
import { BooleanIndicator } from 'state-switch';
|
|
@@ -47,6 +48,15 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
47
48
|
options;
|
|
48
49
|
static VERSION = VERSION;
|
|
49
50
|
_payloadStore;
|
|
51
|
+
roomCache = new RoomCacheCoordinator();
|
|
52
|
+
eventQueue = Promise.resolve();
|
|
53
|
+
eventEpoch = 0;
|
|
54
|
+
eventsBlocked = false;
|
|
55
|
+
failedEventSeq;
|
|
56
|
+
activeEventSeq;
|
|
57
|
+
pendingEventSeq;
|
|
58
|
+
checkpointQueue = Promise.resolve();
|
|
59
|
+
pendingCheckpointRollback;
|
|
50
60
|
timeoutMilliseconds;
|
|
51
61
|
_grpcManager;
|
|
52
62
|
get grpcManager() {
|
|
@@ -100,6 +110,8 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
100
110
|
this.log.verbose('PuppetService', 'onStart()');
|
|
101
111
|
this.waitingForLogin = false;
|
|
102
112
|
this.waitingForReady = false;
|
|
113
|
+
this.suspendEventProcessing();
|
|
114
|
+
this.eventsBlocked = false;
|
|
103
115
|
if (this._grpcManager) {
|
|
104
116
|
this.log.warn('PuppetService', 'onStart() found this.grpc is already existed. dropped.');
|
|
105
117
|
this._grpcManager = undefined;
|
|
@@ -116,7 +128,7 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
116
128
|
this.bridgeGrpcEventStream(grpcManager);
|
|
117
129
|
this.log.info('PuppetService', 'start() setting up bridge grpc event stream ... done');
|
|
118
130
|
this.log.info('PuppetService', 'start() starting grpc manager...');
|
|
119
|
-
const { lastEventSeq, accountId } = await this.
|
|
131
|
+
const { lastEventSeq, accountId } = await this.eventResumePosition();
|
|
120
132
|
await grpcManager.start(lastEventSeq, accountId);
|
|
121
133
|
this.log.info('PuppetService', 'start() starting grpc manager... done');
|
|
122
134
|
this.log.info('PuppetService', 'start healthCheck');
|
|
@@ -125,6 +137,8 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
125
137
|
}
|
|
126
138
|
async onStop() {
|
|
127
139
|
this.log.info('PuppetService', 'onStop()');
|
|
140
|
+
this.suspendEventProcessing();
|
|
141
|
+
await this.checkpointQueue;
|
|
128
142
|
if (this._grpcManager) {
|
|
129
143
|
this.log.info('PuppetService', 'onStop() stopping grpc manager ...');
|
|
130
144
|
const grpcManager = this._grpcManager;
|
|
@@ -160,7 +174,41 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
160
174
|
bridgeGrpcEventStream(client) {
|
|
161
175
|
this.log.verbose('PuppetService', 'bridgeGrpcEventStream(client)');
|
|
162
176
|
client
|
|
163
|
-
.on('data',
|
|
177
|
+
.on('data', (event) => {
|
|
178
|
+
if (client !== this._grpcManager || this.eventsBlocked) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const epoch = this.eventEpoch;
|
|
182
|
+
this.eventQueue = this.eventQueue.then(async () => {
|
|
183
|
+
if (!this.ownsEventWorker(client, epoch)) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
this.activeEventSeq = event.getSeq();
|
|
187
|
+
try {
|
|
188
|
+
if (this.failedEventSeq !== undefined && event.getSeq() > this.failedEventSeq) {
|
|
189
|
+
throw new Error(`Replay skipped failed event ${this.failedEventSeq}; stream halted until reset`);
|
|
190
|
+
}
|
|
191
|
+
await this.onGrpcStreamEvent(event, epoch);
|
|
192
|
+
if (!this.ownsEventWorker(client, epoch)) {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
if (event.getSeq() === this.failedEventSeq) {
|
|
196
|
+
this.failedEventSeq = undefined;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
if (!this.ownsEventWorker(client, epoch)) {
|
|
201
|
+
this.log.error('PuppetService', 'superseded event worker failed: %s', error);
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
this.haltEventStream(client, event, error);
|
|
205
|
+
}
|
|
206
|
+
if (epoch === this.eventEpoch) {
|
|
207
|
+
this.activeEventSeq = undefined;
|
|
208
|
+
}
|
|
209
|
+
return undefined;
|
|
210
|
+
}).catch((error) => { this.reportStreamError(error); });
|
|
211
|
+
})
|
|
164
212
|
.on('end', () => {
|
|
165
213
|
this.log.verbose('PuppetService', 'bridgeGrpcEventStream() eventStream.on(end)');
|
|
166
214
|
})
|
|
@@ -185,7 +233,128 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
185
233
|
this.log.verbose('PuppetService', 'bridgeGrpcEventStream() eventStream.on(cancel), %s', JSON.stringify(args));
|
|
186
234
|
});
|
|
187
235
|
}
|
|
188
|
-
|
|
236
|
+
suspendEventProcessing() {
|
|
237
|
+
if (this.activeEventSeq) {
|
|
238
|
+
this.pendingEventSeq ??= this.activeEventSeq;
|
|
239
|
+
}
|
|
240
|
+
this.eventEpoch++;
|
|
241
|
+
this.eventsBlocked = true;
|
|
242
|
+
this.activeEventSeq = undefined;
|
|
243
|
+
this.eventQueue = Promise.resolve();
|
|
244
|
+
}
|
|
245
|
+
ownsEventWorker(manager, epoch) {
|
|
246
|
+
return manager === this._grpcManager && this.isEventEpochCurrent(epoch);
|
|
247
|
+
}
|
|
248
|
+
isEventEpochCurrent(epoch) {
|
|
249
|
+
return epoch === this.eventEpoch && !this.eventsBlocked;
|
|
250
|
+
}
|
|
251
|
+
async eventResumePosition(epoch = this.eventEpoch) {
|
|
252
|
+
return this.withEventCheckpoint(async () => {
|
|
253
|
+
if (this.pendingCheckpointRollback) {
|
|
254
|
+
await this.restoreEventMetadata(this.pendingCheckpointRollback);
|
|
255
|
+
this.pendingCheckpointRollback = undefined;
|
|
256
|
+
}
|
|
257
|
+
const lastEventSeq = await this._payloadStore.miscellaneous?.get('lastEventSeq');
|
|
258
|
+
if (epoch !== this.eventEpoch) {
|
|
259
|
+
return { lastEventSeq };
|
|
260
|
+
}
|
|
261
|
+
if (this.pendingEventSeq !== undefined && this.pendingEventSeq > Number(lastEventSeq ?? 0)) {
|
|
262
|
+
this.failedEventSeq ??= this.pendingEventSeq;
|
|
263
|
+
}
|
|
264
|
+
this.pendingEventSeq = undefined;
|
|
265
|
+
return { lastEventSeq, accountId: await this._payloadStore.miscellaneous?.get('accountId') };
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
async withEventCheckpoint(operation) {
|
|
269
|
+
const result = this.checkpointQueue.then(operation);
|
|
270
|
+
this.checkpointQueue = result.then(() => undefined, () => undefined);
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
273
|
+
async restoreEventMetadata(previous) {
|
|
274
|
+
for (const [key, value] of previous) {
|
|
275
|
+
if (value === undefined) {
|
|
276
|
+
await this._payloadStore.miscellaneous?.delete(key);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
await this._payloadStore.miscellaneous?.set(key, value);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
async writeEventMetadata(changes, epoch) {
|
|
284
|
+
const isCurrent = () => epoch === undefined || this.isEventEpochCurrent(epoch);
|
|
285
|
+
if (!isCurrent()) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const previous = new Map();
|
|
289
|
+
for (const key of changes.keys()) {
|
|
290
|
+
previous.set(key, await this._payloadStore.miscellaneous?.get(key));
|
|
291
|
+
}
|
|
292
|
+
if (!isCurrent()) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
for (const [key, value] of changes) {
|
|
297
|
+
if (value === undefined) {
|
|
298
|
+
await this._payloadStore.miscellaneous?.delete(key);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
await this._payloadStore.miscellaneous?.set(key, value);
|
|
302
|
+
}
|
|
303
|
+
if (!isCurrent()) {
|
|
304
|
+
await this.restoreEventMetadata(previous);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
try {
|
|
311
|
+
await this.restoreEventMetadata(previous);
|
|
312
|
+
}
|
|
313
|
+
catch (rollbackError) {
|
|
314
|
+
this.pendingCheckpointRollback = previous;
|
|
315
|
+
this.log.error('PuppetService', 'checkpoint rollback failed: %s', rollbackError);
|
|
316
|
+
}
|
|
317
|
+
throw error;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
async commitEventCheckpoint(seq, timestamp, epoch) {
|
|
321
|
+
await this.withEventCheckpoint(async () => {
|
|
322
|
+
if (!this.isEventEpochCurrent(epoch)) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const lastEventSeq = await this._payloadStore.miscellaneous?.get('lastEventSeq');
|
|
326
|
+
if (lastEventSeq && seq <= Number(lastEventSeq) && seq !== 1) {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
await this.writeEventMetadata(new Map([
|
|
330
|
+
['lastEventTimestamp', timestamp], ['lastEventSeq', String(seq)],
|
|
331
|
+
]), epoch);
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
reportStreamError(error) {
|
|
335
|
+
this.log.error('PuppetService', 'event processing failed: %s', error);
|
|
336
|
+
try {
|
|
337
|
+
this.emit('error', error);
|
|
338
|
+
}
|
|
339
|
+
catch (listenerError) {
|
|
340
|
+
this.log.error('PuppetService', 'error listener failed: %s', listenerError);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
haltEventStream(manager, event, error) {
|
|
344
|
+
this.failedEventSeq ??= event.getSeq();
|
|
345
|
+
this.suspendEventProcessing();
|
|
346
|
+
try {
|
|
347
|
+
manager.stopStream();
|
|
348
|
+
}
|
|
349
|
+
catch (stopError) {
|
|
350
|
+
this.log.error('PuppetService', 'stopping failed event stream failed: %s', stopError);
|
|
351
|
+
}
|
|
352
|
+
this.reportStreamError(error);
|
|
353
|
+
}
|
|
354
|
+
async onGrpcStreamEvent(event, epoch = this.eventEpoch) {
|
|
355
|
+
if (!this.isEventEpochCurrent(epoch)) {
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
189
358
|
const type = event.getType();
|
|
190
359
|
const payload = event.getPayload();
|
|
191
360
|
const seq = event.getSeq();
|
|
@@ -199,15 +368,6 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
199
368
|
data: `onGrpcStreamEvent(${EventTypeRev[type]})`,
|
|
200
369
|
});
|
|
201
370
|
}
|
|
202
|
-
if (seq && !envVars.WECHATY_PUPPET_SERVICE_DISABLE_EVENT_CACHE()) {
|
|
203
|
-
const { lastEventSeq } = await this.getMiscellaneousStoreData();
|
|
204
|
-
if (!lastEventSeq || (seq > Number(lastEventSeq) || seq === 1)) {
|
|
205
|
-
await this.setMiscellaneousStoreData({
|
|
206
|
-
lastEventSeq: seq.toString(),
|
|
207
|
-
lastEventTimestamp: timestamp,
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
371
|
switch (type) {
|
|
212
372
|
case grpcPuppet.EventType.EVENT_TYPE_DONG:
|
|
213
373
|
this.emit('dong', JSON.parse(payload));
|
|
@@ -230,11 +390,14 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
230
390
|
const loginPayload = JSON.parse(payload);
|
|
231
391
|
if (!envVars.WECHATY_PUPPET_SERVICE_DISABLE_EVENT_CACHE()) {
|
|
232
392
|
const { accountId } = await this.getMiscellaneousStoreData();
|
|
393
|
+
if (!this.isEventEpochCurrent(epoch)) {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
233
396
|
if (accountId !== loginPayload.contactId) {
|
|
234
|
-
await this.resetMiscellaneousStoreData();
|
|
397
|
+
await this.resetMiscellaneousStoreData(epoch);
|
|
235
398
|
await this.setMiscellaneousStoreData({
|
|
236
399
|
accountId: loginPayload.contactId,
|
|
237
|
-
});
|
|
400
|
+
}, epoch);
|
|
238
401
|
}
|
|
239
402
|
}
|
|
240
403
|
(async () => this.login(loginPayload.contactId))().catch(e => this.log.error('PuppetService', 'onGrpcStreamEvent() this.login() rejection %s', e.message));
|
|
@@ -244,7 +407,7 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
244
407
|
{
|
|
245
408
|
const logoutPayload = JSON.parse(payload);
|
|
246
409
|
if (!envVars.WECHATY_PUPPET_SERVICE_DISABLE_EVENT_CACHE()) {
|
|
247
|
-
await this.resetMiscellaneousStoreData();
|
|
410
|
+
await this.resetMiscellaneousStoreData(epoch);
|
|
248
411
|
}
|
|
249
412
|
;
|
|
250
413
|
(async () => this.logout(logoutPayload.data))().catch(e => this.log.error('PuppetService', 'onGrpcStreamEvent() this.logout() rejection %s', e.message));
|
|
@@ -252,8 +415,25 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
252
415
|
break;
|
|
253
416
|
case grpcPuppet.EventType.EVENT_TYPE_DIRTY:
|
|
254
417
|
await this.fastDirty(JSON.parse(payload));
|
|
418
|
+
if (!this.isEventEpochCurrent(epoch)) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
255
421
|
this.emit('dirty', JSON.parse(payload));
|
|
256
422
|
break;
|
|
423
|
+
case grpcPuppet.EventType.EVENT_TYPE_ROOM_MEMBER_LOAD: {
|
|
424
|
+
const loadPayload = JSON.parse(payload);
|
|
425
|
+
validateRoomMemberLoadState(loadPayload);
|
|
426
|
+
this.roomCache.invalidate(loadPayload.roomId);
|
|
427
|
+
await this.roomCache.run(loadPayload.roomId, async () => {
|
|
428
|
+
await this._payloadStore.room?.delete(loadPayload.roomId);
|
|
429
|
+
await this._payloadStore.roomMember?.delete(loadPayload.roomId);
|
|
430
|
+
});
|
|
431
|
+
if (!this.isEventEpochCurrent(epoch)) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
this.emit('room-member-load', loadPayload);
|
|
435
|
+
break;
|
|
436
|
+
}
|
|
257
437
|
case grpcPuppet.EventType.EVENT_TYPE_MESSAGE:
|
|
258
438
|
this.emit('message', JSON.parse(payload));
|
|
259
439
|
break;
|
|
@@ -326,6 +506,9 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
326
506
|
// Huan(202003): in default, the `type` type should be `never`, please check.
|
|
327
507
|
this.log.error(`eventType ${type} unsupported! data: ${payload}`);
|
|
328
508
|
}
|
|
509
|
+
if (seq && this.isEventEpochCurrent(epoch) && !envVars.WECHATY_PUPPET_SERVICE_DISABLE_EVENT_CACHE()) {
|
|
510
|
+
await this.commitEventCheckpoint(seq, timestamp, epoch);
|
|
511
|
+
}
|
|
329
512
|
}
|
|
330
513
|
async logout(reason) {
|
|
331
514
|
this.log.verbose('PuppetService', 'logout(%s)', reason ? `"${reason}"` : '');
|
|
@@ -381,8 +564,14 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
381
564
|
[PUPPET.types.Dirty.Friendship]: async (_) => { },
|
|
382
565
|
[PUPPET.types.Dirty.Message]: async (_) => { },
|
|
383
566
|
[PUPPET.types.Dirty.Post]: async (_) => { },
|
|
384
|
-
[PUPPET.types.Dirty.Room]: async (id) =>
|
|
385
|
-
|
|
567
|
+
[PUPPET.types.Dirty.Room]: async (id) => {
|
|
568
|
+
this.roomCache.invalidate(id);
|
|
569
|
+
return this.roomCache.run(id, async () => this._payloadStore.room?.delete(id));
|
|
570
|
+
},
|
|
571
|
+
[PUPPET.types.Dirty.RoomMember]: async (id) => {
|
|
572
|
+
this.roomCache.invalidate(id);
|
|
573
|
+
return this.roomCache.run(id, async () => this._payloadStore.roomMember?.delete(id));
|
|
574
|
+
},
|
|
386
575
|
[PUPPET.types.Dirty.Tag]: async (id) => this._payloadStore.tag?.delete(id),
|
|
387
576
|
[PUPPET.types.Dirty.TagGroup]: async (id) => this._payloadStore.tagGroup?.delete(id),
|
|
388
577
|
[PUPPET.types.Dirty.Unspecified]: async (id) => { throw new Error('Unspecified type with id: ' + id); },
|
|
@@ -1551,8 +1740,9 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
1551
1740
|
*/
|
|
1552
1741
|
async roomRawPayload(id) {
|
|
1553
1742
|
this.log.verbose('PuppetService', 'roomRawPayload(%s)', id);
|
|
1554
|
-
const
|
|
1555
|
-
|
|
1743
|
+
const generation = this.roomCache.generation(id);
|
|
1744
|
+
const cachedPayload = await this.roomCache.run(id, async () => this._payloadStore.room?.get(id));
|
|
1745
|
+
if (cachedPayload && generation === this.roomCache.generation(id)) {
|
|
1556
1746
|
this.log.silly('PuppetService', 'roomRawPayload(%s) cache HIT', id);
|
|
1557
1747
|
return cachedPayload;
|
|
1558
1748
|
}
|
|
@@ -1560,26 +1750,52 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
1560
1750
|
request.setId(id);
|
|
1561
1751
|
const response = await util.promisify(this.grpcManager.client.roomPayload
|
|
1562
1752
|
.bind(this.grpcManager.client))(request);
|
|
1563
|
-
const payload =
|
|
1564
|
-
|
|
1565
|
-
avatar: response.getAvatar(),
|
|
1566
|
-
handle: response.getHandle(),
|
|
1567
|
-
id: response.getId(),
|
|
1568
|
-
memberIdList: response.getMemberIdsList(),
|
|
1569
|
-
ownerId: response.getOwnerId(),
|
|
1570
|
-
topic: response.getTopic(),
|
|
1571
|
-
additionalInfo: response.getAdditionalInfo(),
|
|
1572
|
-
remark: response.getRoomRemark(),
|
|
1573
|
-
external: response.getExternal(),
|
|
1574
|
-
};
|
|
1575
|
-
const createTime = response.getCreateTime();
|
|
1576
|
-
if (createTime) {
|
|
1577
|
-
payload.createTime = millisecondsFromTimestamp(createTime);
|
|
1578
|
-
}
|
|
1579
|
-
await this._payloadStore.room?.set(id, payload);
|
|
1753
|
+
const payload = roomPbToPayload(response);
|
|
1754
|
+
await this.roomCache.commit(id, generation, async () => this._payloadStore.room?.set(id, payload));
|
|
1580
1755
|
this.log.silly('PuppetService', 'roomRawPayload(%s) cache SET', id);
|
|
1581
1756
|
return payload;
|
|
1582
1757
|
}
|
|
1758
|
+
async roomMemberSync(roomId, options) {
|
|
1759
|
+
if (!roomId) {
|
|
1760
|
+
throw new Error('roomId is required');
|
|
1761
|
+
}
|
|
1762
|
+
const request = new grpcPuppet.RoomMemberSyncRequest();
|
|
1763
|
+
request.setId(roomId);
|
|
1764
|
+
if (options?.force !== undefined) {
|
|
1765
|
+
request.setForce(options.force);
|
|
1766
|
+
}
|
|
1767
|
+
const response = await util.promisify(this.grpcManager.client.roomMemberSync.bind(this.grpcManager.client))(request);
|
|
1768
|
+
return roomMemberLoadStatePbToPayload(response, roomId);
|
|
1769
|
+
}
|
|
1770
|
+
async roomMemberLoadState(roomId) {
|
|
1771
|
+
if (!roomId) {
|
|
1772
|
+
throw new Error('roomId is required');
|
|
1773
|
+
}
|
|
1774
|
+
const request = new grpcPuppet.RoomMemberLoadStateRequest();
|
|
1775
|
+
request.setId(roomId);
|
|
1776
|
+
const response = await util.promisify(this.grpcManager.client.roomMemberLoadState.bind(this.grpcManager.client))(request);
|
|
1777
|
+
return roomMemberLoadStatePbToPayload(response, roomId);
|
|
1778
|
+
}
|
|
1779
|
+
async roomMemberSnapshot(roomId, revision, options) {
|
|
1780
|
+
if (!roomId) {
|
|
1781
|
+
throw new Error('roomId is required');
|
|
1782
|
+
}
|
|
1783
|
+
validateRoomMemberRevision(revision);
|
|
1784
|
+
const request = new grpcPuppet.RoomMemberSnapshotRequest();
|
|
1785
|
+
request.setId(roomId);
|
|
1786
|
+
request.setRevision(revision);
|
|
1787
|
+
if (options?.pageToken !== undefined) {
|
|
1788
|
+
request.setPageToken(options.pageToken);
|
|
1789
|
+
}
|
|
1790
|
+
if (options?.pageSize !== undefined) {
|
|
1791
|
+
if (!Number.isInteger(options.pageSize) || options.pageSize < 0 || options.pageSize > 500) {
|
|
1792
|
+
throw new Error('pageSize must be an integer between 0 and 500');
|
|
1793
|
+
}
|
|
1794
|
+
request.setPageSize(options.pageSize);
|
|
1795
|
+
}
|
|
1796
|
+
const response = await util.promisify(this.grpcManager.client.roomMemberSnapshot.bind(this.grpcManager.client))(request);
|
|
1797
|
+
return roomMemberSnapshotPbToPayload(response, roomId, revision);
|
|
1798
|
+
}
|
|
1583
1799
|
async roomRawPayloadParser(payload) {
|
|
1584
1800
|
// this.log.silly('PuppetService', 'roomRawPayloadParser({id:%s})', payload.id)
|
|
1585
1801
|
// passthrough
|
|
@@ -1589,10 +1805,11 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
1589
1805
|
this.log.verbose('PuppetService', 'batchRoomRawPayload(%s)', roomIdList);
|
|
1590
1806
|
const result = new Map();
|
|
1591
1807
|
const roomIdSet = new Set(roomIdList);
|
|
1808
|
+
const generations = new Map(Array.from(roomIdSet, id => [id, this.roomCache.generation(id)]));
|
|
1592
1809
|
const needGetSet = new Set();
|
|
1593
1810
|
for (const roomId of roomIdSet) {
|
|
1594
|
-
const cachedRoomPayload = await this._payloadStore.room?.get(roomId);
|
|
1595
|
-
if (cachedRoomPayload) {
|
|
1811
|
+
const cachedRoomPayload = await this.roomCache.run(roomId, async () => this._payloadStore.room?.get(roomId));
|
|
1812
|
+
if (cachedRoomPayload && generations.get(roomId) === this.roomCache.generation(roomId)) {
|
|
1596
1813
|
result.set(roomId, cachedRoomPayload);
|
|
1597
1814
|
}
|
|
1598
1815
|
else {
|
|
@@ -1608,27 +1825,18 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
1608
1825
|
const payloads = response.getRoomPayloadsList();
|
|
1609
1826
|
for (const payload of payloads) {
|
|
1610
1827
|
const roomId = payload.getId();
|
|
1611
|
-
const puppetPayload =
|
|
1612
|
-
adminIdList: payload.getAdminIdsList(),
|
|
1613
|
-
avatar: payload.getAvatar(),
|
|
1614
|
-
handle: payload.getHandle(),
|
|
1615
|
-
id: payload.getId(),
|
|
1616
|
-
memberIdList: payload.getMemberIdsList(),
|
|
1617
|
-
ownerId: payload.getOwnerId(),
|
|
1618
|
-
topic: payload.getTopic(),
|
|
1619
|
-
additionalInfo: payload.getAdditionalInfo(),
|
|
1620
|
-
remark: payload.getRoomRemark(),
|
|
1621
|
-
external: payload.getExternal(),
|
|
1622
|
-
};
|
|
1623
|
-
const createTime = payload.getCreateTime();
|
|
1624
|
-
if (createTime) {
|
|
1625
|
-
puppetPayload.createTime = millisecondsFromTimestamp(createTime);
|
|
1626
|
-
}
|
|
1828
|
+
const puppetPayload = roomPbToPayload(payload);
|
|
1627
1829
|
result.set(roomId, puppetPayload);
|
|
1628
|
-
|
|
1830
|
+
const generation = generations.get(roomId);
|
|
1831
|
+
if (generation !== undefined) {
|
|
1832
|
+
await this.roomCache.commit(roomId, generation, async () => this._payloadStore.room?.set(roomId, puppetPayload));
|
|
1833
|
+
}
|
|
1629
1834
|
}
|
|
1630
1835
|
}
|
|
1631
1836
|
catch (e) {
|
|
1837
|
+
if (e instanceof RoomCacheOperationError) {
|
|
1838
|
+
throw e;
|
|
1839
|
+
}
|
|
1632
1840
|
this.log.error('PuppetService', 'batchRoomRawPayload(%s, %s) error: %s, use one by one method', roomIdList, needGetSet, e);
|
|
1633
1841
|
let fallbackSuccessCount = 0;
|
|
1634
1842
|
for (const roomId of needGetSet) {
|
|
@@ -1814,9 +2022,10 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
1814
2022
|
}
|
|
1815
2023
|
async roomMemberRawPayload(roomId, contactId) {
|
|
1816
2024
|
this.log.verbose('PuppetService', 'roomMemberRawPayload(%s, %s)', roomId, contactId);
|
|
1817
|
-
const
|
|
2025
|
+
const generation = this.roomCache.generation(roomId);
|
|
2026
|
+
const cachedPayload = await this.roomCache.run(roomId, async () => this._payloadStore.roomMember?.get(roomId));
|
|
1818
2027
|
const cachedRoomMemberPayload = cachedPayload && cachedPayload[contactId];
|
|
1819
|
-
if (cachedRoomMemberPayload) {
|
|
2028
|
+
if (cachedRoomMemberPayload && generation === this.roomCache.generation(roomId)) {
|
|
1820
2029
|
this.log.silly('PuppetService', 'roomMemberRawPayload(%s, %s) cache HIT', roomId, contactId);
|
|
1821
2030
|
return cachedRoomMemberPayload;
|
|
1822
2031
|
}
|
|
@@ -1835,9 +2044,9 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
1835
2044
|
joinScene: response.getJoinScene(),
|
|
1836
2045
|
joinTime: response.getJoinTime(),
|
|
1837
2046
|
};
|
|
1838
|
-
await this.
|
|
1839
|
-
|
|
1840
|
-
[contactId]: payload
|
|
2047
|
+
await this.roomCache.commit(roomId, generation, async () => {
|
|
2048
|
+
const current = await this._payloadStore.roomMember?.get(roomId);
|
|
2049
|
+
await this._payloadStore.roomMember?.set(roomId, { ...current, [contactId]: payload });
|
|
1841
2050
|
});
|
|
1842
2051
|
this.log.silly('PuppetService', 'roomMemberRawPayload(%s, %s) cache SET', roomId, contactId);
|
|
1843
2052
|
return payload;
|
|
@@ -1849,10 +2058,12 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
1849
2058
|
}
|
|
1850
2059
|
async batchRoomMemberRawPayload(roomId, contactIdList) {
|
|
1851
2060
|
this.log.verbose('PuppetService', 'batchRoomMemberRawPayload(%s, %s)', roomId, contactIdList);
|
|
2061
|
+
const generation = this.roomCache.generation(roomId);
|
|
1852
2062
|
const result = new Map();
|
|
1853
2063
|
const contactIdSet = new Set(contactIdList);
|
|
1854
2064
|
let needGetSet = new Set();
|
|
1855
|
-
const
|
|
2065
|
+
const cached = await this.roomCache.run(roomId, async () => this._payloadStore.roomMember?.get(roomId));
|
|
2066
|
+
const cachedPayload = generation === this.roomCache.generation(roomId) ? cached || {} : {};
|
|
1856
2067
|
if (Object.keys(cachedPayload).length > 0) {
|
|
1857
2068
|
for (const contactId of contactIdSet) {
|
|
1858
2069
|
const cachedRoomMemberPayload = cachedPayload[contactId];
|
|
@@ -1875,15 +2086,22 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
1875
2086
|
const response = await util.promisify(this.grpcManager.client.batchRoomMemberPayload
|
|
1876
2087
|
.bind(this.grpcManager.client))(request);
|
|
1877
2088
|
const payloads = response.getMemberPayloadsList();
|
|
2089
|
+
const fetched = {};
|
|
1878
2090
|
for (const payload of payloads) {
|
|
1879
2091
|
const contactId = payload.getId();
|
|
1880
2092
|
const puppetPayload = roomMemberPbToPayload(payload);
|
|
1881
2093
|
result.set(contactId, puppetPayload);
|
|
1882
|
-
|
|
2094
|
+
fetched[contactId] = puppetPayload;
|
|
1883
2095
|
}
|
|
1884
|
-
await this.
|
|
2096
|
+
await this.roomCache.commit(roomId, generation, async () => {
|
|
2097
|
+
const current = await this._payloadStore.roomMember?.get(roomId);
|
|
2098
|
+
await this._payloadStore.roomMember?.set(roomId, { ...current, ...fetched });
|
|
2099
|
+
});
|
|
1885
2100
|
}
|
|
1886
2101
|
catch (e) {
|
|
2102
|
+
if (e instanceof RoomCacheOperationError) {
|
|
2103
|
+
throw e;
|
|
2104
|
+
}
|
|
1887
2105
|
this.log.error('PuppetService', 'batchRoomMemberRawPayload(%s, %s) error: %s, use one by one method', roomId, needGetSet, e);
|
|
1888
2106
|
for (const contactId of needGetSet) {
|
|
1889
2107
|
const payload = await this.roomMemberRawPayload(roomId, contactId);
|
|
@@ -2625,23 +2843,40 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
2625
2843
|
waitingForReady = false;
|
|
2626
2844
|
reconnectIndicator;
|
|
2627
2845
|
async reset() {
|
|
2628
|
-
if (!this._grpcManager) {
|
|
2629
|
-
this.log.warn('PuppetService', 'grpc manager not constructed, perform regular reset');
|
|
2630
|
-
return super.reset();
|
|
2631
|
-
}
|
|
2632
|
-
if (!this.isLoggedIn) {
|
|
2633
|
-
this.log.warn('PuppetService', 'puppet not logged in, perform regular reset');
|
|
2634
|
-
return super.reset();
|
|
2635
|
-
}
|
|
2636
2846
|
if (this.reconnectIndicator.value()) {
|
|
2637
2847
|
this.log.warn('PuppetService', 'already trying to reconnect, pass this one');
|
|
2638
2848
|
return;
|
|
2639
2849
|
}
|
|
2640
2850
|
this.reconnectIndicator.value(true);
|
|
2641
|
-
this.
|
|
2642
|
-
const
|
|
2851
|
+
this.suspendEventProcessing();
|
|
2852
|
+
const epoch = this.eventEpoch;
|
|
2853
|
+
const manager = this._grpcManager;
|
|
2854
|
+
try {
|
|
2855
|
+
await this.checkpointQueue;
|
|
2856
|
+
if (epoch !== this.eventEpoch) {
|
|
2857
|
+
return;
|
|
2858
|
+
}
|
|
2859
|
+
if (!manager || !this.isLoggedIn) {
|
|
2860
|
+
this.log.warn('PuppetService', 'grpc manager unavailable or puppet logged out, perform regular reset');
|
|
2861
|
+
return await super.reset();
|
|
2862
|
+
}
|
|
2863
|
+
await this.resetEventStream(manager, epoch);
|
|
2864
|
+
}
|
|
2865
|
+
finally {
|
|
2866
|
+
this.reconnectIndicator.value(false);
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
async resetEventStream(manager, epoch) {
|
|
2870
|
+
manager.stopStream();
|
|
2871
|
+
const { lastEventSeq, accountId } = await this.eventResumePosition(epoch);
|
|
2872
|
+
if (epoch !== this.eventEpoch || manager !== this._grpcManager) {
|
|
2873
|
+
return;
|
|
2874
|
+
}
|
|
2643
2875
|
const onLoginResolve = (resolve) => {
|
|
2644
2876
|
const onLogin = (event) => {
|
|
2877
|
+
if (!this.ownsEventWorker(manager, epoch)) {
|
|
2878
|
+
return;
|
|
2879
|
+
}
|
|
2645
2880
|
const type = event.getType();
|
|
2646
2881
|
const payload = event.getPayload();
|
|
2647
2882
|
if (this.waitingForLogin && type === grpcPuppet.EventType.EVENT_TYPE_LOGIN) {
|
|
@@ -2657,6 +2892,9 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
2657
2892
|
};
|
|
2658
2893
|
const onReadyResolve = (resolve) => {
|
|
2659
2894
|
const onReady = (event) => {
|
|
2895
|
+
if (!this.ownsEventWorker(manager, epoch)) {
|
|
2896
|
+
return;
|
|
2897
|
+
}
|
|
2660
2898
|
const type = event.getType();
|
|
2661
2899
|
if (this.waitingForReady && type === grpcPuppet.EventType.EVENT_TYPE_READY) {
|
|
2662
2900
|
this.waitingForReady = false;
|
|
@@ -2665,60 +2903,85 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
2665
2903
|
};
|
|
2666
2904
|
return onReady;
|
|
2667
2905
|
};
|
|
2668
|
-
|
|
2669
|
-
let onReady;
|
|
2906
|
+
const removeListeners = [];
|
|
2670
2907
|
const loginFuture = new Promise(resolve => {
|
|
2671
|
-
onLogin = onLoginResolve(resolve);
|
|
2672
|
-
|
|
2908
|
+
const onLogin = onLoginResolve(resolve);
|
|
2909
|
+
manager.on('data', onLogin);
|
|
2910
|
+
removeListeners.push(() => { manager.off('data', onLogin); });
|
|
2673
2911
|
});
|
|
2674
2912
|
const readyFuture = new Promise(resolve => {
|
|
2675
|
-
onReady = onReadyResolve(resolve);
|
|
2676
|
-
|
|
2913
|
+
const onReady = onReadyResolve(resolve);
|
|
2914
|
+
manager.on('data', onReady);
|
|
2915
|
+
removeListeners.push(() => { manager.off('data', onReady); });
|
|
2677
2916
|
});
|
|
2678
2917
|
const startTime = Date.now();
|
|
2679
2918
|
const timeoutMilliseconds = this.timeoutMilliseconds / 10; // 2 min default, 4 min xiaoju-bot
|
|
2680
|
-
|
|
2919
|
+
this.waitingForLogin = true;
|
|
2920
|
+
this.waitingForReady = true;
|
|
2921
|
+
this.eventsBlocked = false;
|
|
2922
|
+
try {
|
|
2923
|
+
while (true) {
|
|
2924
|
+
try {
|
|
2925
|
+
if (!this.ownsEventWorker(manager, epoch)) {
|
|
2926
|
+
return;
|
|
2927
|
+
}
|
|
2928
|
+
await timeoutPromise(manager.startStream(lastEventSeq, accountId), 30 * 1000);
|
|
2929
|
+
if (!this.ownsEventWorker(manager, epoch)) {
|
|
2930
|
+
return;
|
|
2931
|
+
}
|
|
2932
|
+
break;
|
|
2933
|
+
}
|
|
2934
|
+
catch (e) {
|
|
2935
|
+
if (!this.ownsEventWorker(manager, epoch)) {
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2938
|
+
if (Date.now() - startTime < timeoutMilliseconds) {
|
|
2939
|
+
this.log.warn('failed to start stream, will try again in 15 seconds');
|
|
2940
|
+
await new Promise(resolve => {
|
|
2941
|
+
setTimeout(resolve, 5000);
|
|
2942
|
+
});
|
|
2943
|
+
}
|
|
2944
|
+
else {
|
|
2945
|
+
this.log.warn('failed to start stream and reaches timeout, will perform regular reset');
|
|
2946
|
+
return super.reset();
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2949
|
+
}
|
|
2681
2950
|
try {
|
|
2682
|
-
await timeoutPromise(
|
|
2683
|
-
|
|
2951
|
+
await timeoutPromise(loginFuture, ResetLoginTimeout)
|
|
2952
|
+
.finally(() => {
|
|
2953
|
+
if (epoch === this.eventEpoch) {
|
|
2954
|
+
this.waitingForLogin = false;
|
|
2955
|
+
}
|
|
2956
|
+
});
|
|
2684
2957
|
}
|
|
2685
2958
|
catch (e) {
|
|
2686
|
-
if (
|
|
2687
|
-
|
|
2688
|
-
await new Promise(resolve => {
|
|
2689
|
-
setTimeout(resolve, 5000);
|
|
2690
|
-
});
|
|
2691
|
-
}
|
|
2692
|
-
else {
|
|
2693
|
-
this.log.warn('failed to start stream and reaches timeout, will perform regular reset');
|
|
2694
|
-
this.reconnectIndicator.value(false);
|
|
2695
|
-
return super.reset();
|
|
2959
|
+
if (!this.ownsEventWorker(manager, epoch)) {
|
|
2960
|
+
return;
|
|
2696
2961
|
}
|
|
2962
|
+
this.log.warn('PuppetService', 'waiting for event reset login error, will perform regular reset');
|
|
2963
|
+
return super.reset();
|
|
2964
|
+
}
|
|
2965
|
+
try {
|
|
2966
|
+
await timeoutPromise(readyFuture, ResetReadyTimeout)
|
|
2967
|
+
.finally(() => {
|
|
2968
|
+
if (epoch === this.eventEpoch) {
|
|
2969
|
+
this.waitingForReady = false;
|
|
2970
|
+
}
|
|
2971
|
+
});
|
|
2972
|
+
}
|
|
2973
|
+
catch (e) {
|
|
2974
|
+
this.log.warn('PuppetService', 'waiting for event reset ready error, will do nothing');
|
|
2697
2975
|
}
|
|
2698
2976
|
}
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2977
|
+
finally {
|
|
2978
|
+
for (const removeListener of removeListeners) {
|
|
2979
|
+
removeListener();
|
|
2980
|
+
}
|
|
2981
|
+
if (epoch === this.eventEpoch) {
|
|
2704
2982
|
this.waitingForLogin = false;
|
|
2705
|
-
this.reconnectIndicator.value(false);
|
|
2706
|
-
this.grpcManager.off('data', onLogin);
|
|
2707
|
-
});
|
|
2708
|
-
}
|
|
2709
|
-
catch (e) {
|
|
2710
|
-
this.log.warn('PuppetService', 'waiting for event reset login error, will perform regular reset');
|
|
2711
|
-
return super.reset();
|
|
2712
|
-
}
|
|
2713
|
-
try {
|
|
2714
|
-
await timeoutPromise(readyFuture, ResetReadyTimeout)
|
|
2715
|
-
.finally(() => {
|
|
2716
2983
|
this.waitingForReady = false;
|
|
2717
|
-
|
|
2718
|
-
});
|
|
2719
|
-
}
|
|
2720
|
-
catch (e) {
|
|
2721
|
-
this.log.warn('PuppetService', 'waiting for event reset ready error, will do nothing');
|
|
2984
|
+
}
|
|
2722
2985
|
}
|
|
2723
2986
|
}
|
|
2724
2987
|
async getMiscellaneousStoreData() {
|
|
@@ -2742,27 +3005,29 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
2742
3005
|
accountId,
|
|
2743
3006
|
};
|
|
2744
3007
|
}
|
|
2745
|
-
async setMiscellaneousStoreData(data) {
|
|
3008
|
+
async setMiscellaneousStoreData(data, epoch) {
|
|
2746
3009
|
if (envVars.WECHATY_PUPPET_SERVICE_DISABLE_EVENT_CACHE()) {
|
|
2747
3010
|
return;
|
|
2748
3011
|
}
|
|
2749
|
-
|
|
2750
|
-
|
|
3012
|
+
const changes = new Map();
|
|
3013
|
+
if (data.lastEventTimestamp !== undefined) {
|
|
3014
|
+
changes.set('lastEventTimestamp', data.lastEventTimestamp);
|
|
2751
3015
|
}
|
|
2752
|
-
if (
|
|
2753
|
-
|
|
3016
|
+
if (data.accountId !== undefined) {
|
|
3017
|
+
changes.set('accountId', data.accountId);
|
|
2754
3018
|
}
|
|
2755
|
-
if (
|
|
2756
|
-
|
|
3019
|
+
if (data.lastEventSeq !== undefined) {
|
|
3020
|
+
changes.set('lastEventSeq', data.lastEventSeq);
|
|
2757
3021
|
}
|
|
3022
|
+
await this.withEventCheckpoint(async () => this.writeEventMetadata(changes, epoch));
|
|
2758
3023
|
}
|
|
2759
|
-
async resetMiscellaneousStoreData() {
|
|
3024
|
+
async resetMiscellaneousStoreData(epoch) {
|
|
2760
3025
|
if (envVars.WECHATY_PUPPET_SERVICE_DISABLE_EVENT_CACHE()) {
|
|
2761
3026
|
return;
|
|
2762
3027
|
}
|
|
2763
|
-
await this.
|
|
2764
|
-
|
|
2765
|
-
|
|
3028
|
+
await this.withEventCheckpoint(async () => this.writeEventMetadata(new Map([
|
|
3029
|
+
['lastEventSeq', undefined], ['lastEventTimestamp', undefined], ['accountId', undefined],
|
|
3030
|
+
]), epoch));
|
|
2766
3031
|
}
|
|
2767
3032
|
}
|
|
2768
3033
|
export { PuppetService, };
|