Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix(channels): preserve DWS sender identity history
  • Loading branch information
qqqys committed Aug 17, 2026
commit 563d0d17b32568e42655a9b27bea367578904aac
127 changes: 127 additions & 0 deletions packages/channels/dws/src/dws-channel.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,133 @@ describe('DwsChannel', () => {
expect(client.streams).toEqual([]);
});

it('preserves self sender history across degraded group reconnects', async () => {
const config = makeConfig({
dmPolicy: 'disabled',
groups: { '*': { requireMention: false } },
});
const name = 'degraded-self-id-dws';
const firstClient = new FakeDwsClient();
firstClient.identity = {
profile: 'corp:bot',
selfSenderIds: ['open-self-old'],
};
const first = await readyChannel(firstClient, config, name);
first.disconnect();

const secondClient = new FakeDwsClient();
secondClient.identity = { profile: 'corp:bot' };
const second = await readyChannel(secondClient, config, name);
await secondClient.emit(
1,
message(
'user_im_message_receive_group_all',
'degraded-self-1',
'own echo',
{
senderId: 'open-self-old',
},
),
);
expect(second.inbound).toEqual([]);
second.disconnect();

const thirdClient = new FakeDwsClient();
thirdClient.identity = { profile: 'corp:bot' };
const third = await readyChannel(thirdClient, config, name);
await thirdClient.emit(
1,
message(
'user_im_message_receive_group_all',
'degraded-self-2',
'own echo',
{
senderId: 'open-self-old',
},
),
);
expect(third.inbound).toEqual([]);
});

it('retains rotated self sender IDs within the same profile', async () => {
const config = makeConfig({
dmPolicy: 'disabled',
groups: { '*': { requireMention: false } },
});
const name = 'rotated-self-id-dws';
const firstClient = new FakeDwsClient();
firstClient.identity = {
profile: 'corp:bot',
selfSenderIds: ['open-self-a'],
};
const first = await readyChannel(firstClient, config, name);
first.disconnect();

const secondClient = new FakeDwsClient();
secondClient.identity = {
profile: 'corp:bot',
selfSenderIds: ['open-self-b'],
};
const second = await readyChannel(secondClient, config, name);
await secondClient.emit(
1,
message(
'user_im_message_receive_group_all',
'rotated-self-a',
'old echo',
{
senderId: 'open-self-a',
},
),
);
await secondClient.emit(
1,
message(
'user_im_message_receive_group_all',
'rotated-self-b',
'new echo',
{
senderId: 'open-self-b',
},
),
);
expect(second.inbound).toEqual([]);
});

it('drops self sender history after a profile switch', async () => {
const config = makeConfig({
dmPolicy: 'disabled',
groups: { '*': { requireMention: false } },
});
const name = 'profile-self-id-dws';
const firstClient = new FakeDwsClient();
firstClient.identity = {
profile: 'corp:one',
selfSenderIds: ['open-self-a'],
};
const first = await readyChannel(firstClient, config, name);
first.disconnect();

const secondClient = new FakeDwsClient();
secondClient.identity = {
profile: 'corp:two',
selfSenderIds: ['open-self-b'],
};
const second = await readyChannel(secondClient, config, name);
await secondClient.emit(
1,
message(
'user_im_message_receive_group_all',
'old-profile-sender',
'peer text',
{
senderId: 'open-self-a',
},
),
);
expect(second.inbound.map((item) => item.text)).toEqual(['peer text']);
});

it('drops unverified direct targets after self identity becomes authoritative', async () => {
const name = 'legacy-direct-target-dws';
const client = new FakeDwsClient();
Expand Down
12 changes: 10 additions & 2 deletions packages/channels/dws/src/dws-channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,7 @@ export class DwsChannel extends PollingChannelBase<DwsCursor> {
identity.profile,
);
if (this.cursor.selfProfile !== identity.profile) {
this.cursor.selfSenderIds = [];
this.cursor.selfProfile = identity.profile;
this.cursor.todosInitialized = false;
this.cursor.todoTasks = [];
Expand Down Expand Up @@ -628,12 +629,19 @@ export class DwsChannel extends PollingChannelBase<DwsCursor> {
'DWS direct messages require the authenticated identity to expose an openDingTalkId.',
);
}
if (this.cursor.selfSenderIds.length === 0 && selfSenderIds.length > 0) {
const previousSelfSenderIds = this.cursor.selfSenderIds;
if (previousSelfSenderIds.length === 0 && selfSenderIds.length > 0) {
this.cursor.imTargets = this.cursor.imTargets.filter(
({ target }) => target.kind !== 'direct',
);
}
this.cursor.selfSenderIds = selfSenderIds;
if (selfSenderIds.length > 0) {
const freshSelfSenderIds = new Set(selfSenderIds);
this.cursor.selfSenderIds = [
...previousSelfSenderIds.filter((id) => !freshSelfSenderIds.has(id)),
...selfSenderIds,
].slice(-MAX_SELF_SENDER_IDS);
}
Comment on lines +593 to +606

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。验证:dws-channel.test.ts 82/82 通过,profile 切换后 pending 文档与旧 IM target 均不会重放。

Comment on lines +593 to +606

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复(commit 423b896c28)。验证:DWS 全包 130/130、15 个定向回归通过,仓库 build + bundle 通过。

this.connected = true;
try {
await Promise.all(
Expand Down
10 changes: 7 additions & 3 deletions packages/channels/dws/src/dws-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,11 @@ describe('DwsClient', () => {
runner,
);

await expect(client.listMentionedMessages(1, 2)).resolves.toEqual({
const startTime = new Date(2026, 0, 2, 3, 4, 5).getTime();
const endTime = new Date(2026, 0, 2, 3, 4, 6).getTime();
await expect(
client.listMentionedMessages(startTime, endTime),
).resolves.toEqual({
messages: [
{
type: 'user_im_message_receive_at',
Expand All @@ -794,9 +798,9 @@ describe('DwsClient', () => {
'message',
'list-mentions',
'--start',
'1970-01-01 08:00:00',
'2026-01-02 03:04:05',
'--end',
'1970-01-01 08:00:00',
'2026-01-02 03:04:06',
'--limit',
'50',
'--cursor',
Expand Down
Loading