@juzi/wechaty-puppet-service 1.0.129 → 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 +27 -2
- package/dist/cjs/src/client/puppet-service.d.ts.map +1 -1
- package/dist/cjs/src/client/puppet-service.js +431 -124
- package/dist/cjs/src/client/puppet-service.js.map +1 -1
- package/dist/cjs/src/client/puppet-service.spec.js +107 -0
- package/dist/cjs/src/client/puppet-service.spec.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 +30 -0
- package/dist/cjs/src/server/event-stream-manager.js.map +1 -1
- package/dist/cjs/src/server/event-stream-manager.spec.d.ts +3 -0
- package/dist/cjs/src/server/event-stream-manager.spec.d.ts.map +1 -0
- package/dist/cjs/src/server/event-stream-manager.spec.js +22 -0
- package/dist/cjs/src/server/event-stream-manager.spec.js.map +1 -0
- package/dist/cjs/src/server/puppet-implementation.d.ts.map +1 -1
- package/dist/cjs/src/server/puppet-implementation.js +135 -28
- package/dist/cjs/src/server/puppet-implementation.js.map +1 -1
- package/dist/cjs/src/server/puppet-implementation.spec.js +98 -0
- package/dist/cjs/src/server/puppet-implementation.spec.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 +27 -2
- package/dist/esm/src/client/puppet-service.d.ts.map +1 -1
- package/dist/esm/src/client/puppet-service.js +432 -125
- package/dist/esm/src/client/puppet-service.js.map +1 -1
- package/dist/esm/src/client/puppet-service.spec.js +107 -0
- package/dist/esm/src/client/puppet-service.spec.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 +30 -0
- package/dist/esm/src/server/event-stream-manager.js.map +1 -1
- package/dist/esm/src/server/event-stream-manager.spec.d.ts +3 -0
- package/dist/esm/src/server/event-stream-manager.spec.d.ts.map +1 -0
- package/dist/esm/src/server/event-stream-manager.spec.js +20 -0
- package/dist/esm/src/server/event-stream-manager.spec.js.map +1 -0
- package/dist/esm/src/server/puppet-implementation.d.ts.map +1 -1
- package/dist/esm/src/server/puppet-implementation.js +136 -29
- package/dist/esm/src/server/puppet-implementation.js.map +1 -1
- package/dist/esm/src/server/puppet-implementation.spec.js +98 -0
- package/dist/esm/src/server/puppet-implementation.spec.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.spec.ts +147 -0
- package/src/client/puppet-service.ts +378 -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.spec.ts +30 -0
- package/src/server/event-stream-manager.ts +29 -0
- package/src/server/puppet-implementation.spec.ts +127 -0
- package/src/server/puppet-implementation.ts +144 -29
- package/src/utils/pb-payload-helper.ts +150 -0
- package/src/utils/room-member-load.spec.ts +67 -0
|
@@ -89,6 +89,113 @@ test('callInviteWithMedia rejects when the server returns an empty call_id', asy
|
|
|
89
89
|
const { puppet } = createCallInviteWithMediaPuppet('');
|
|
90
90
|
await t.rejects(puppet.callInviteWithMedia(['contact-1'], undefined, { hangupOnFinish: true }), /empty call_id/, 'does not hand back an unusable empty call_id');
|
|
91
91
|
});
|
|
92
|
+
let orgBroadcastTestId = 0;
|
|
93
|
+
function createOrgBroadcastPuppet(payloadResponse) {
|
|
94
|
+
const puppet = new PuppetService({
|
|
95
|
+
token: `org-broadcast-test-${orgBroadcastTestId++}`,
|
|
96
|
+
});
|
|
97
|
+
const executeRequestList = [];
|
|
98
|
+
puppet._grpcManager = {
|
|
99
|
+
client: {
|
|
100
|
+
orgBroadcastExecute: (request, callback) => {
|
|
101
|
+
executeRequestList.push(request);
|
|
102
|
+
callback(null, new grpcPuppet.OrgBroadcastExecuteResponse());
|
|
103
|
+
},
|
|
104
|
+
orgBroadcastPayload: (request, callback) => {
|
|
105
|
+
void request;
|
|
106
|
+
callback(null, payloadResponse);
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
return { puppet, executeRequestList };
|
|
111
|
+
}
|
|
112
|
+
test('orgBroadcastPayload maps every response field onto OrgBroadcastPayload', async (t) => {
|
|
113
|
+
const roomTarget = new grpcPuppet.OrgBroadcastTarget();
|
|
114
|
+
roomTarget.setRoomId('R:room-1');
|
|
115
|
+
roomTarget.setStatus(grpcPuppet.OrgBroadcastTargetStatus.ORG_BROADCAST_TARGET_STATUS_UNCONFIRMED);
|
|
116
|
+
const sentRoomTarget = new grpcPuppet.OrgBroadcastTarget();
|
|
117
|
+
sentRoomTarget.setRoomId('R:room-2');
|
|
118
|
+
sentRoomTarget.setStatus(grpcPuppet.OrgBroadcastTargetStatus.ORG_BROADCAST_TARGET_STATUS_SENT);
|
|
119
|
+
const response = new grpcPuppet.OrgBroadcastPayloadResponse();
|
|
120
|
+
response.setId('4728994241730369413');
|
|
121
|
+
response.setSendType(2);
|
|
122
|
+
response.setConversationType(1);
|
|
123
|
+
response.setCreatorId('creator-1');
|
|
124
|
+
response.setExecTime(1758600000000);
|
|
125
|
+
response.setStatus(3);
|
|
126
|
+
response.setCanCancel(true);
|
|
127
|
+
response.setAllowSelect(true);
|
|
128
|
+
response.setSent(false);
|
|
129
|
+
response.setTotalCount(7);
|
|
130
|
+
response.setSentCount(5);
|
|
131
|
+
response.setContentListJson('[{"contentType":2}]');
|
|
132
|
+
response.setTargetsList([roomTarget, sentRoomTarget]);
|
|
133
|
+
const { puppet } = createOrgBroadcastPuppet(response);
|
|
134
|
+
const payload = await puppet.orgBroadcastPayload('4728994241730369413');
|
|
135
|
+
t.same(payload, {
|
|
136
|
+
id: '4728994241730369413',
|
|
137
|
+
sendType: 2,
|
|
138
|
+
conversationType: 1,
|
|
139
|
+
creatorId: 'creator-1',
|
|
140
|
+
execTime: 1758600000000,
|
|
141
|
+
status: 3,
|
|
142
|
+
canCancel: true,
|
|
143
|
+
allowSelect: true,
|
|
144
|
+
sent: false,
|
|
145
|
+
totalCount: 7,
|
|
146
|
+
sentCount: 5,
|
|
147
|
+
contentListJson: '[{"contentType":2}]',
|
|
148
|
+
targets: [
|
|
149
|
+
{ contactId: undefined, roomId: 'R:room-1', status: 4 },
|
|
150
|
+
{ contactId: undefined, roomId: 'R:room-2', status: 1 },
|
|
151
|
+
],
|
|
152
|
+
}, 'maps every field and drops the empty contact_id of room targets');
|
|
153
|
+
});
|
|
154
|
+
test('orgBroadcastPayload maps empty creator_id and contact targets', async (t) => {
|
|
155
|
+
const contactTarget = new grpcPuppet.OrgBroadcastTarget();
|
|
156
|
+
contactTarget.setContactId('contact-1');
|
|
157
|
+
const response = new grpcPuppet.OrgBroadcastPayloadResponse();
|
|
158
|
+
response.setId('org-broadcast-2');
|
|
159
|
+
response.setTargetsList([contactTarget]);
|
|
160
|
+
const { puppet } = createOrgBroadcastPuppet(response);
|
|
161
|
+
const payload = await puppet.orgBroadcastPayload('org-broadcast-2');
|
|
162
|
+
t.equal(payload.creatorId, undefined, 'maps an empty creator_id to undefined');
|
|
163
|
+
t.same(payload.targets, [{ contactId: 'contact-1', roomId: undefined, status: 0 }], 'drops the empty room_id of contact targets');
|
|
164
|
+
});
|
|
165
|
+
test('orgBroadcastExecute sends all targets as an empty target_ids when targetIds is omitted', async (t) => {
|
|
166
|
+
const { puppet, executeRequestList } = createOrgBroadcastPuppet();
|
|
167
|
+
await puppet.orgBroadcastExecute('org-broadcast-1');
|
|
168
|
+
t.equal(executeRequestList.length, 1, 'sends exactly one request');
|
|
169
|
+
t.equal(executeRequestList[0].getId(), 'org-broadcast-1', 'maps orgBroadcastId onto id');
|
|
170
|
+
t.same(executeRequestList[0].getTargetIdsList(), [], 'leaves target_ids empty');
|
|
171
|
+
});
|
|
172
|
+
test('orgBroadcastExecute forwards the selected targets', async (t) => {
|
|
173
|
+
const { puppet, executeRequestList } = createOrgBroadcastPuppet();
|
|
174
|
+
await puppet.orgBroadcastExecute('org-broadcast-1', ['contact-1', 'contact-2']);
|
|
175
|
+
t.same(executeRequestList[0].getTargetIdsList(), ['contact-1', 'contact-2'], 'maps targetIds onto target_ids');
|
|
176
|
+
});
|
|
177
|
+
test('orgBroadcastExecute rejects an explicit empty targetIds instead of sending to all targets', async (t) => {
|
|
178
|
+
const { puppet, executeRequestList } = createOrgBroadcastPuppet();
|
|
179
|
+
await t.rejects(puppet.orgBroadcastExecute('org-broadcast-1', []), /targetIds is empty/, 'does not turn an empty selection into sending to all targets');
|
|
180
|
+
t.equal(executeRequestList.length, 0, 'never reaches the server');
|
|
181
|
+
});
|
|
182
|
+
test('org broadcast grpc events are emitted as puppet events', async (t) => {
|
|
183
|
+
const { puppet } = createOrgBroadcastPuppet();
|
|
184
|
+
const createdSpy = sinon.spy();
|
|
185
|
+
const sentSpy = sinon.spy();
|
|
186
|
+
puppet.on('org-broadcast-created', createdSpy);
|
|
187
|
+
puppet.on('org-broadcast-sent', sentSpy);
|
|
188
|
+
const createdEvent = new grpcPuppet.EventResponse();
|
|
189
|
+
createdEvent.setType(grpcPuppet.EventType.EVENT_TYPE_ORG_BROADCAST_CREATED);
|
|
190
|
+
createdEvent.setPayload(JSON.stringify({ orgBroadcastId: 'org-broadcast-1', messageId: 'message-1' }));
|
|
191
|
+
const sentEvent = new grpcPuppet.EventResponse();
|
|
192
|
+
sentEvent.setType(grpcPuppet.EventType.EVENT_TYPE_ORG_BROADCAST_SENT);
|
|
193
|
+
sentEvent.setPayload(JSON.stringify({ orgBroadcastId: 'org-broadcast-1' }));
|
|
194
|
+
await puppet.onGrpcStreamEvent(createdEvent);
|
|
195
|
+
await puppet.onGrpcStreamEvent(sentEvent);
|
|
196
|
+
t.same(createdSpy.args[0], [{ orgBroadcastId: 'org-broadcast-1', messageId: 'message-1' }], 'emits org-broadcast-created');
|
|
197
|
+
t.same(sentSpy.args[0], [{ orgBroadcastId: 'org-broadcast-1' }], 'emits org-broadcast-sent');
|
|
198
|
+
});
|
|
92
199
|
test('version()', async (t) => {
|
|
93
200
|
const puppet = new PuppetService({
|
|
94
201
|
token: 'test',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"puppet-service.spec.js","sourceRoot":"","sources":["../../../../src/client/puppet-service.spec.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"puppet-service.spec.js","sourceRoot":"","sources":["../../../../src/client/puppet-service.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare class RoomCacheOperationError extends Error {
|
|
2
|
+
readonly original: unknown;
|
|
3
|
+
constructor(roomId: string, original: unknown);
|
|
4
|
+
}
|
|
5
|
+
declare class RoomCacheCoordinator {
|
|
6
|
+
private readonly generations;
|
|
7
|
+
private readonly pending;
|
|
8
|
+
generation(roomId: string): number;
|
|
9
|
+
invalidate(roomId: string): void;
|
|
10
|
+
run<Result>(roomId: string, operation: () => Promise<Result>): Promise<Result>;
|
|
11
|
+
commit(roomId: string, generation: number, operation: () => Promise<unknown>): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export { RoomCacheCoordinator, RoomCacheOperationError };
|
|
14
|
+
//# sourceMappingURL=room-cache-coordinator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room-cache-coordinator.d.ts","sourceRoot":"","sources":["../../../../src/client/room-cache-coordinator.ts"],"names":[],"mappings":"AAAA,cAAM,uBAAwB,SAAQ,KAAK;IAEZ,QAAQ,CAAC,QAAQ,EAAE,OAAO;gBAA1C,MAAM,EAAE,MAAM,EAAW,QAAQ,EAAE,OAAO;CAKxD;AAED,cAAM,oBAAoB;IAExB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4B;IACxD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAE3D,UAAU,CAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAInC,UAAU,CAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAI3B,GAAG,CAAC,MAAM,EAAG,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAkB/E,MAAM,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAOpG;AAED,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
class RoomCacheOperationError extends Error {
|
|
2
|
+
original;
|
|
3
|
+
constructor(roomId, original) {
|
|
4
|
+
super(`Room cache ${roomId} failed: ${original instanceof Error ? original.message : String(original)}`);
|
|
5
|
+
this.original = original;
|
|
6
|
+
this.name = 'RoomCacheOperationError';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
class RoomCacheCoordinator {
|
|
10
|
+
generations = new Map();
|
|
11
|
+
pending = new Map();
|
|
12
|
+
generation(roomId) {
|
|
13
|
+
return this.generations.get(roomId) ?? 0;
|
|
14
|
+
}
|
|
15
|
+
invalidate(roomId) {
|
|
16
|
+
this.generations.set(roomId, this.generation(roomId) + 1);
|
|
17
|
+
}
|
|
18
|
+
async run(roomId, operation) {
|
|
19
|
+
const preceding = this.pending.get(roomId) ?? Promise.resolve();
|
|
20
|
+
const result = (async () => {
|
|
21
|
+
await preceding;
|
|
22
|
+
return operation();
|
|
23
|
+
})();
|
|
24
|
+
// Only the queue barrier settles errors; the caller still receives the rejected result.
|
|
25
|
+
const barrier = result.then(() => undefined, () => undefined);
|
|
26
|
+
this.pending.set(roomId, barrier);
|
|
27
|
+
try {
|
|
28
|
+
return await result;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
throw error instanceof RoomCacheOperationError ? error : new RoomCacheOperationError(roomId, error);
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
if (this.pending.get(roomId) === barrier) {
|
|
35
|
+
this.pending.delete(roomId);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async commit(roomId, generation, operation) {
|
|
40
|
+
await this.run(roomId, async () => {
|
|
41
|
+
if (this.generation(roomId) !== generation) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
await operation();
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export { RoomCacheCoordinator, RoomCacheOperationError };
|
|
49
|
+
//# sourceMappingURL=room-cache-coordinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room-cache-coordinator.js","sourceRoot":"","sources":["../../../../src/client/room-cache-coordinator.ts"],"names":[],"mappings":"AAAA,MAAM,uBAAwB,SAAQ,KAAK;IAEH;IAAtC,YAAa,MAAc,EAAW,QAAiB;QACrD,KAAK,CAAC,cAAc,MAAM,YAAY,QAAQ,YAAY,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;QADpE,aAAQ,GAAR,QAAQ,CAAS;QAErD,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAA;IACvC,CAAC;CAEF;AAED,MAAM,oBAAoB;IAEP,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAA;IACvC,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAA;IAE3D,UAAU,CAAE,MAAc;QACxB,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC1C,CAAC;IAED,UAAU,CAAE,MAAc;QACxB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;IAC3D,CAAC;IAED,KAAK,CAAC,GAAG,CAAU,MAAc,EAAE,SAAgC;QACjE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAA;QAC/D,MAAM,MAAM,GAAG,CAAC,KAAK,IAAqB,EAAE;YAC1C,MAAM,SAAS,CAAA;YACf,OAAO,SAAS,EAAE,CAAA;QACpB,CAAC,CAAC,EAAE,CAAA;QACJ,wFAAwF;QACxF,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAc,EAAE,CAAC,SAAS,EAAE,GAAc,EAAE,CAAC,SAAS,CAAC,CAAA;QACnF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACjC,IAAI;YACF,OAAO,MAAM,MAAM,CAAA;SACpB;QAAC,OAAO,KAAK,EAAE;YACd,MAAM,KAAK,YAAY,uBAAuB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,uBAAuB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;SACpG;gBAAS;YACR,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,OAAO,EAAE;gBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;aAAE;SAC1E;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAE,MAAc,EAAE,UAAkB,EAAE,SAAiC;QACjF,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,IAAmB,EAAE;YAC/C,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,UAAU,EAAE;gBAAE,OAAM;aAAE;YACtD,MAAM,SAAS,EAAE,CAAA;QACnB,CAAC,CAAC,CAAA;IACJ,CAAC;CAEF;AAED,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room-member-cache.spec.d.ts","sourceRoot":"","sources":["../../../../src/client/room-member-cache.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { test, sinon } from 'tstest';
|
|
2
|
+
import { puppet as grpcPuppet } from '@juzi/wechaty-grpc';
|
|
3
|
+
import { PuppetService } from './puppet-service.js';
|
|
4
|
+
import { GrpcManager } from './grpc-manager.js';
|
|
5
|
+
import { roomPayloadToPb, roomMemberPayloadToPb } from '../utils/pb-payload-helper.js';
|
|
6
|
+
function deferred() {
|
|
7
|
+
let finish = () => { throw new Error('Uninitialized resolver'); };
|
|
8
|
+
let fail = () => { throw new Error('Uninitialized rejection'); };
|
|
9
|
+
const promise = new Promise((resolve, reject) => { finish = resolve; fail = reject; });
|
|
10
|
+
return { promise, resolve: finish, reject: fail };
|
|
11
|
+
}
|
|
12
|
+
class BridgedService extends PuppetService {
|
|
13
|
+
connect(manager) { this._grpcManager = manager; this.bridgeGrpcEventStream(manager); }
|
|
14
|
+
}
|
|
15
|
+
let fixtureId = 0;
|
|
16
|
+
function serviceFixture() {
|
|
17
|
+
return new BridgedService({ token: `insecure_cache-${process.pid}-${fixtureId++}` });
|
|
18
|
+
}
|
|
19
|
+
function event(payload, seq = 2) {
|
|
20
|
+
const response = new grpcPuppet.EventResponse();
|
|
21
|
+
response.setType(grpcPuppet.EventType.EVENT_TYPE_ROOM_MEMBER_LOAD);
|
|
22
|
+
response.setSeq(seq);
|
|
23
|
+
response.setPayload(JSON.stringify(payload));
|
|
24
|
+
return response;
|
|
25
|
+
}
|
|
26
|
+
const state = { roomId: 'room', taskId: 'task', status: 3, revision: '1' };
|
|
27
|
+
async function drain() {
|
|
28
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
29
|
+
}
|
|
30
|
+
function resetFixture(remove = async () => { }) {
|
|
31
|
+
const service = serviceFixture();
|
|
32
|
+
const manager = new GrpcManager({ token: 'insecure_token' });
|
|
33
|
+
const metadata = new Map([['lastEventSeq', '1'], ['lastEventTimestamp', String(Date.now())], ['accountId', 'account']]);
|
|
34
|
+
Object.defineProperty(service, '_payloadStore', {
|
|
35
|
+
value: {
|
|
36
|
+
room: { delete: remove },
|
|
37
|
+
roomMember: { delete: async () => { } },
|
|
38
|
+
miscellaneous: {
|
|
39
|
+
get: async (key) => metadata.get(key),
|
|
40
|
+
set: async (key, value) => { metadata.set(key, value); },
|
|
41
|
+
delete: async (key) => { metadata.delete(key); },
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
Object.defineProperty(service, 'isLoggedIn', { get: () => true });
|
|
46
|
+
sinon.stub(service, 'login').resolves();
|
|
47
|
+
const stop = sinon.stub(manager, 'stopStream');
|
|
48
|
+
const started = deferred();
|
|
49
|
+
const release = deferred();
|
|
50
|
+
const start = sinon.stub(manager, 'startStream').callsFake(async () => {
|
|
51
|
+
started.resolve();
|
|
52
|
+
await release.promise;
|
|
53
|
+
});
|
|
54
|
+
service.connect(manager);
|
|
55
|
+
return { service, manager, metadata, stop, start, started, release };
|
|
56
|
+
}
|
|
57
|
+
async function finishResetHandshake(fixture) {
|
|
58
|
+
fixture.release.resolve();
|
|
59
|
+
await drain();
|
|
60
|
+
const login = new grpcPuppet.EventResponse();
|
|
61
|
+
login.setType(grpcPuppet.EventType.EVENT_TYPE_LOGIN);
|
|
62
|
+
login.setPayload(JSON.stringify({ contactId: 'account' }));
|
|
63
|
+
fixture.manager.emit('data', login);
|
|
64
|
+
const ready = new grpcPuppet.EventResponse();
|
|
65
|
+
ready.setType(grpcPuppet.EventType.EVENT_TYPE_READY);
|
|
66
|
+
ready.setPayload(JSON.stringify({ data: 'ready' }));
|
|
67
|
+
fixture.manager.emit('data', ready);
|
|
68
|
+
await drain();
|
|
69
|
+
}
|
|
70
|
+
test('bridge cache failure stops the stream and fences later seq until explicit reset', async (t) => {
|
|
71
|
+
const service = serviceFixture();
|
|
72
|
+
const manager = new GrpcManager({ token: 'insecure_token' });
|
|
73
|
+
const metadata = new Map([['lastEventSeq', '1'], ['lastEventTimestamp', String(Date.now())]]);
|
|
74
|
+
const deleteRoom = sinon.stub().rejects(new Error('persistent cache unavailable'));
|
|
75
|
+
Object.defineProperty(service, '_payloadStore', {
|
|
76
|
+
value: {
|
|
77
|
+
room: { delete: deleteRoom },
|
|
78
|
+
roomMember: { delete: sinon.stub().resolves() },
|
|
79
|
+
miscellaneous: {
|
|
80
|
+
get: async (key) => metadata.get(key),
|
|
81
|
+
set: async (key, value) => { metadata.set(key, value); },
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
const stop = sinon.stub(manager, 'stopStream');
|
|
86
|
+
const start = sinon.stub(manager, 'startStream').resolves();
|
|
87
|
+
const errors = sinon.spy();
|
|
88
|
+
const completed = sinon.spy();
|
|
89
|
+
const unhandled = sinon.spy();
|
|
90
|
+
process.on('unhandledRejection', unhandled);
|
|
91
|
+
t.teardown(() => { process.off('unhandledRejection', unhandled); });
|
|
92
|
+
service.on('error', errors);
|
|
93
|
+
service.on('room-member-load', completed);
|
|
94
|
+
service.connect(manager);
|
|
95
|
+
manager.emit('data', event(state));
|
|
96
|
+
manager.emit('data', event({ ...state, revision: '2' }, 3));
|
|
97
|
+
await drain();
|
|
98
|
+
t.equal(unhandled.callCount, 0);
|
|
99
|
+
t.equal(errors.callCount, 1);
|
|
100
|
+
t.equal(completed.callCount, 0);
|
|
101
|
+
t.equal(metadata.get('lastEventSeq'), '1');
|
|
102
|
+
t.equal(stop.callCount, 1);
|
|
103
|
+
t.equal(start.callCount, 0);
|
|
104
|
+
deleteRoom.resolves();
|
|
105
|
+
manager.emit('data', event(state));
|
|
106
|
+
await drain();
|
|
107
|
+
t.equal(completed.callCount, 0);
|
|
108
|
+
t.equal(metadata.get('lastEventSeq'), '1');
|
|
109
|
+
});
|
|
110
|
+
test('invalid event payloads never reach persistent cache or emit completion', async (t) => {
|
|
111
|
+
for (const payload of [
|
|
112
|
+
{ ...state, revision: 1 }, { ...state, revision: '01' }, { ...state, status: 99 },
|
|
113
|
+
{ ...state, roomId: '' }, { ...state, roomId: undefined }, { ...state, taskId: 1 },
|
|
114
|
+
]) {
|
|
115
|
+
const service = serviceFixture();
|
|
116
|
+
const manager = new GrpcManager({ token: 'insecure_token' });
|
|
117
|
+
const remove = sinon.stub().resolves();
|
|
118
|
+
Object.defineProperty(service, '_payloadStore', { value: { room: { delete: remove }, roomMember: { delete: remove } } });
|
|
119
|
+
sinon.stub(manager, 'stopStream');
|
|
120
|
+
sinon.stub(manager, 'startStream').resolves();
|
|
121
|
+
const errors = sinon.spy();
|
|
122
|
+
const completed = sinon.spy();
|
|
123
|
+
service.on('error', errors);
|
|
124
|
+
service.on('room-member-load', completed);
|
|
125
|
+
service.connect(manager);
|
|
126
|
+
manager.emit('data', event(payload));
|
|
127
|
+
await drain();
|
|
128
|
+
t.equal(remove.callCount, 0);
|
|
129
|
+
t.equal(completed.callCount, 0);
|
|
130
|
+
t.equal(errors.callCount, 1);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
test('all four raw RPC reads begun before invalidation cannot refill persistent caches', async (t) => {
|
|
134
|
+
const room = { id: 'room', topic: 'old', adminIdList: [], memberIdList: [] };
|
|
135
|
+
const member = { id: 'member', name: 'old', avatar: '' };
|
|
136
|
+
for (const method of ['room', 'batchRoom', 'member', 'batchMember']) {
|
|
137
|
+
const responseReady = deferred();
|
|
138
|
+
const requested = deferred();
|
|
139
|
+
const service = serviceFixture();
|
|
140
|
+
const manager = new GrpcManager({ token: 'insecure_token' });
|
|
141
|
+
const rooms = new Map();
|
|
142
|
+
const members = new Map();
|
|
143
|
+
Object.defineProperty(service, '_payloadStore', {
|
|
144
|
+
value: {
|
|
145
|
+
room: {
|
|
146
|
+
get: async (id) => rooms.get(id),
|
|
147
|
+
set: async (id, value) => { rooms.set(id, value); },
|
|
148
|
+
delete: async (id) => { rooms.delete(id); },
|
|
149
|
+
},
|
|
150
|
+
roomMember: {
|
|
151
|
+
get: async (id) => members.get(id),
|
|
152
|
+
set: async (id, value) => { members.set(id, value); },
|
|
153
|
+
delete: async (id) => { members.delete(id); },
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
const wait = async () => { requested.resolve(); await responseReady.promise; };
|
|
158
|
+
const respond = async (response, callback) => {
|
|
159
|
+
await wait();
|
|
160
|
+
callback(null, response);
|
|
161
|
+
};
|
|
162
|
+
const client = {
|
|
163
|
+
roomPayload: (_request, callback) => {
|
|
164
|
+
void respond(roomPayloadToPb(room), callback);
|
|
165
|
+
},
|
|
166
|
+
batchRoomPayload: (_request, callback) => {
|
|
167
|
+
const response = new grpcPuppet.BatchRoomPayloadResponse();
|
|
168
|
+
response.setRoomPayloadsList([roomPayloadToPb(room)]);
|
|
169
|
+
void respond(response, callback);
|
|
170
|
+
},
|
|
171
|
+
roomMemberPayload: (_request, callback) => {
|
|
172
|
+
void respond(roomMemberPayloadToPb(member), callback);
|
|
173
|
+
},
|
|
174
|
+
batchRoomMemberPayload: (_request, callback) => {
|
|
175
|
+
const response = new grpcPuppet.BatchRoomMemberPayloadResponse();
|
|
176
|
+
response.setMemberPayloadsList([roomMemberPayloadToPb(member)]);
|
|
177
|
+
void respond(response, callback);
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
Object.defineProperty(service, 'grpcManager', { value: { client } });
|
|
181
|
+
service.on('error', (error) => { t.fail(String(error)); });
|
|
182
|
+
service.connect(manager);
|
|
183
|
+
const pending = method === 'room' ? service.roomRawPayload('room')
|
|
184
|
+
: method === 'batchRoom' ? service.batchRoomRawPayload(['room'])
|
|
185
|
+
: method === 'member' ? service.roomMemberRawPayload('room', 'member')
|
|
186
|
+
: service.batchRoomMemberRawPayload('room', ['member']);
|
|
187
|
+
await requested.promise;
|
|
188
|
+
manager.emit('data', event(state, 0));
|
|
189
|
+
await drain();
|
|
190
|
+
responseReady.resolve();
|
|
191
|
+
await pending;
|
|
192
|
+
t.equal(rooms.size, 0, method);
|
|
193
|
+
t.equal(members.size, 0, method);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
test('invalidation waits for an already-started asynchronous cache write', async (t) => {
|
|
197
|
+
const service = serviceFixture();
|
|
198
|
+
const manager = new GrpcManager({ token: 'insecure_token' });
|
|
199
|
+
const writing = deferred();
|
|
200
|
+
const finishWrite = deferred();
|
|
201
|
+
let stored;
|
|
202
|
+
const room = { id: 'room', topic: 'old', adminIdList: [], memberIdList: [] };
|
|
203
|
+
const remove = sinon.stub().callsFake(async () => { stored = undefined; });
|
|
204
|
+
Object.defineProperty(service, '_payloadStore', {
|
|
205
|
+
value: {
|
|
206
|
+
room: {
|
|
207
|
+
get: async () => stored,
|
|
208
|
+
set: async (_id, value) => {
|
|
209
|
+
writing.resolve();
|
|
210
|
+
await finishWrite.promise;
|
|
211
|
+
stored = value;
|
|
212
|
+
},
|
|
213
|
+
delete: remove,
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
Object.defineProperty(service, 'grpcManager', {
|
|
218
|
+
value: {
|
|
219
|
+
client: {
|
|
220
|
+
roomPayload: (_request, callback) => callback(null, roomPayloadToPb(room)),
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
service.connect(manager);
|
|
225
|
+
const loaded = sinon.spy();
|
|
226
|
+
service.on('room-member-load', loaded);
|
|
227
|
+
const pending = service.roomRawPayload('room');
|
|
228
|
+
await writing.promise;
|
|
229
|
+
manager.emit('data', event(state, 0));
|
|
230
|
+
await drain();
|
|
231
|
+
t.equal(remove.callCount, 0);
|
|
232
|
+
t.equal(loaded.callCount, 0);
|
|
233
|
+
finishWrite.resolve();
|
|
234
|
+
await pending;
|
|
235
|
+
await drain();
|
|
236
|
+
t.equal(stored, undefined);
|
|
237
|
+
t.equal(loaded.callCount, 1);
|
|
238
|
+
});
|
|
239
|
+
test('later events cannot bypass a halted failure and never cause automatic restart', async (t) => {
|
|
240
|
+
for (const skipped of [false, true]) {
|
|
241
|
+
const service = serviceFixture();
|
|
242
|
+
const manager = new GrpcManager({ token: 'insecure_token' });
|
|
243
|
+
const metadata = new Map([['lastEventSeq', '1']]);
|
|
244
|
+
Object.defineProperty(service, '_payloadStore', {
|
|
245
|
+
value: {
|
|
246
|
+
room: { delete: sinon.stub().rejects(new Error('persistent cache unavailable')) },
|
|
247
|
+
miscellaneous: {
|
|
248
|
+
get: async (key) => metadata.get(key),
|
|
249
|
+
set: async (key, value) => { metadata.set(key, value); },
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
sinon.stub(manager, 'stopStream');
|
|
254
|
+
const start = sinon.stub(manager, 'startStream').resolves();
|
|
255
|
+
const errors = sinon.spy();
|
|
256
|
+
const completed = sinon.spy();
|
|
257
|
+
service.on('error', errors);
|
|
258
|
+
service.on('room-member-load', completed);
|
|
259
|
+
service.connect(manager);
|
|
260
|
+
manager.emit('data', event(state));
|
|
261
|
+
await drain();
|
|
262
|
+
manager.emit('data', event(state, skipped ? 3 : 2));
|
|
263
|
+
manager.emit('data', event(state, 4));
|
|
264
|
+
await drain();
|
|
265
|
+
t.equal(start.callCount, 0);
|
|
266
|
+
t.equal(errors.callCount, 1);
|
|
267
|
+
t.equal(completed.callCount, 0);
|
|
268
|
+
t.equal(metadata.get('lastEventSeq'), '1');
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
test('duplicate reset does not invalidate events queued by the owner reset', async (t) => {
|
|
272
|
+
const fixture = resetFixture();
|
|
273
|
+
const completed = sinon.spy();
|
|
274
|
+
fixture.service.on('room-member-load', completed);
|
|
275
|
+
const resetting = fixture.service.reset();
|
|
276
|
+
await fixture.started.promise;
|
|
277
|
+
fixture.release.resolve();
|
|
278
|
+
await drain();
|
|
279
|
+
const login = new grpcPuppet.EventResponse();
|
|
280
|
+
login.setType(grpcPuppet.EventType.EVENT_TYPE_LOGIN);
|
|
281
|
+
login.setPayload(JSON.stringify({ contactId: 'account' }));
|
|
282
|
+
fixture.manager.emit('data', login);
|
|
283
|
+
await drain();
|
|
284
|
+
fixture.manager.emit('data', event(state));
|
|
285
|
+
await fixture.service.reset();
|
|
286
|
+
await drain();
|
|
287
|
+
t.equal(completed.callCount, 1);
|
|
288
|
+
t.equal(fixture.metadata.get('lastEventSeq'), '2');
|
|
289
|
+
t.equal(fixture.start.callCount, 1);
|
|
290
|
+
await finishResetHandshake(fixture);
|
|
291
|
+
await resetting;
|
|
292
|
+
});
|
|
293
|
+
test('superseded delete rejection cannot stop the stream established by reset', async (t) => {
|
|
294
|
+
const removing = deferred();
|
|
295
|
+
const began = deferred();
|
|
296
|
+
const remove = sinon.stub().onFirstCall().callsFake(async () => { began.resolve(); await removing.promise; });
|
|
297
|
+
remove.onSecondCall().resolves();
|
|
298
|
+
const fixture = resetFixture(remove);
|
|
299
|
+
const errors = sinon.spy();
|
|
300
|
+
const completed = sinon.spy();
|
|
301
|
+
fixture.service.on('error', errors);
|
|
302
|
+
fixture.service.on('room-member-load', completed);
|
|
303
|
+
fixture.manager.emit('data', event(state));
|
|
304
|
+
await began.promise;
|
|
305
|
+
const resetting = fixture.service.reset();
|
|
306
|
+
await fixture.started.promise;
|
|
307
|
+
await finishResetHandshake(fixture);
|
|
308
|
+
await resetting;
|
|
309
|
+
removing.reject(new Error('old delete rejected after reset'));
|
|
310
|
+
await drain();
|
|
311
|
+
t.equal(fixture.stop.callCount, 1);
|
|
312
|
+
t.equal(fixture.start.callCount, 1);
|
|
313
|
+
t.equal(errors.callCount, 0);
|
|
314
|
+
t.equal(completed.callCount, 0);
|
|
315
|
+
t.equal(fixture.metadata.get('lastEventSeq'), '1');
|
|
316
|
+
fixture.manager.emit('data', event(state));
|
|
317
|
+
await drain();
|
|
318
|
+
t.equal(completed.callCount, 1);
|
|
319
|
+
t.equal(fixture.metadata.get('lastEventSeq'), '2');
|
|
320
|
+
});
|
|
321
|
+
test('failure stops before notifying an error listener that immediately performs actual reset', async (t) => {
|
|
322
|
+
const remove = sinon.stub().onFirstCall().rejects(new Error('persistent cache unavailable'));
|
|
323
|
+
remove.onSecondCall().resolves();
|
|
324
|
+
const fixture = resetFixture(remove);
|
|
325
|
+
const resetting = deferred();
|
|
326
|
+
const stopsAtError = [];
|
|
327
|
+
fixture.service.on('error', () => {
|
|
328
|
+
stopsAtError.push(fixture.stop.callCount);
|
|
329
|
+
resetting.resolve(fixture.service.reset());
|
|
330
|
+
});
|
|
331
|
+
fixture.manager.emit('data', event(state));
|
|
332
|
+
await fixture.started.promise;
|
|
333
|
+
t.same(stopsAtError, [1]);
|
|
334
|
+
t.equal(fixture.start.callCount, 1);
|
|
335
|
+
t.same(fixture.start.args[0], ['1', 'account']);
|
|
336
|
+
await finishResetHandshake(fixture);
|
|
337
|
+
await resetting.promise;
|
|
338
|
+
await drain();
|
|
339
|
+
t.equal(fixture.stop.callCount, 2);
|
|
340
|
+
t.equal(fixture.start.callCount, 1);
|
|
341
|
+
fixture.manager.emit('data', event(state));
|
|
342
|
+
await drain();
|
|
343
|
+
t.equal(fixture.metadata.get('lastEventSeq'), '2');
|
|
344
|
+
});
|
|
345
|
+
test('reset waits for and rolls back a superseded asynchronous cursor commit before resuming', async (t) => {
|
|
346
|
+
const fixture = resetFixture();
|
|
347
|
+
const writing = deferred();
|
|
348
|
+
const finishWrite = deferred();
|
|
349
|
+
Object.defineProperty(fixture.service, '_payloadStore', {
|
|
350
|
+
value: {
|
|
351
|
+
room: { delete: async () => { } },
|
|
352
|
+
roomMember: { delete: async () => { } },
|
|
353
|
+
miscellaneous: {
|
|
354
|
+
get: async (key) => fixture.metadata.get(key),
|
|
355
|
+
set: async (key, value) => {
|
|
356
|
+
if (key === 'lastEventSeq' && value === '2') {
|
|
357
|
+
writing.resolve();
|
|
358
|
+
await finishWrite.promise;
|
|
359
|
+
}
|
|
360
|
+
fixture.metadata.set(key, value);
|
|
361
|
+
},
|
|
362
|
+
delete: async (key) => { fixture.metadata.delete(key); },
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
fixture.manager.emit('data', event(state));
|
|
367
|
+
await writing.promise;
|
|
368
|
+
const resetting = fixture.service.reset();
|
|
369
|
+
await drain();
|
|
370
|
+
t.equal(fixture.start.callCount, 0);
|
|
371
|
+
finishWrite.resolve();
|
|
372
|
+
await fixture.started.promise;
|
|
373
|
+
t.same(fixture.start.args[0], ['1', 'account']);
|
|
374
|
+
t.equal(fixture.metadata.get('lastEventSeq'), '1');
|
|
375
|
+
await finishResetHandshake(fixture);
|
|
376
|
+
await resetting;
|
|
377
|
+
});
|
|
378
|
+
test('explicit reset preserves the failed seq barrier if the new stream skips that event', async (t) => {
|
|
379
|
+
const remove = sinon.stub().onFirstCall().rejects(new Error('persistent cache unavailable'));
|
|
380
|
+
remove.onSecondCall().resolves();
|
|
381
|
+
const fixture = resetFixture(remove);
|
|
382
|
+
const errors = sinon.spy();
|
|
383
|
+
const completed = sinon.spy();
|
|
384
|
+
fixture.service.on('error', errors);
|
|
385
|
+
fixture.service.on('room-member-load', completed);
|
|
386
|
+
fixture.manager.emit('data', event(state));
|
|
387
|
+
await drain();
|
|
388
|
+
t.equal(fixture.start.callCount, 0);
|
|
389
|
+
const resetting = fixture.service.reset();
|
|
390
|
+
await fixture.started.promise;
|
|
391
|
+
await finishResetHandshake(fixture);
|
|
392
|
+
await resetting;
|
|
393
|
+
fixture.manager.emit('data', event(state, 3));
|
|
394
|
+
await drain();
|
|
395
|
+
t.equal(errors.callCount, 2);
|
|
396
|
+
t.equal(completed.callCount, 0);
|
|
397
|
+
t.equal(fixture.metadata.get('lastEventSeq'), '1');
|
|
398
|
+
t.equal(fixture.start.callCount, 1);
|
|
399
|
+
});
|
|
400
|
+
test('explicit reset uses the actual durable cursor without age fallback or invented zero', async (t) => {
|
|
401
|
+
for (const absent of [false, true]) {
|
|
402
|
+
const fixture = resetFixture();
|
|
403
|
+
fixture.metadata.set('lastEventTimestamp', '0');
|
|
404
|
+
if (absent) {
|
|
405
|
+
fixture.metadata.delete('lastEventSeq');
|
|
406
|
+
}
|
|
407
|
+
const resetting = fixture.service.reset();
|
|
408
|
+
await fixture.started.promise;
|
|
409
|
+
t.same(fixture.start.args[0], [absent ? undefined : '1', 'account']);
|
|
410
|
+
await finishResetHandshake(fixture);
|
|
411
|
+
await resetting;
|
|
412
|
+
t.equal(fixture.metadata.get('lastEventSeq'), absent ? undefined : '1');
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
//# sourceMappingURL=room-member-cache.spec.js.map
|