fix: harden channel retry attribution and operations UI
This commit is contained in:
@@ -545,6 +545,50 @@ describe('ChannelsService', () => {
|
||||
resourceId: 'channel-1',
|
||||
}),
|
||||
});
|
||||
expect(mockFetch).toHaveBeenCalledWith('http://127.0.0.1:8090/connections/connect', expect.objectContaining({
|
||||
method: 'POST',
|
||||
}));
|
||||
});
|
||||
|
||||
it('does not request a reconnect when only non-connection channel fields change', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
const service = new ChannelsService(prisma as never);
|
||||
|
||||
await service.updateChannel('channel-1', {
|
||||
name: '主通道-新名称',
|
||||
carrier: 'unicom',
|
||||
sendRegion: '上海',
|
||||
rateLimitPerSecond: 200,
|
||||
unitPrice: 5,
|
||||
});
|
||||
|
||||
expect(prisma.smsChannel.update).toHaveBeenCalled();
|
||||
expect(prisma.cmppConnectionState.create).not.toHaveBeenCalled();
|
||||
expect(prisma.cmppConnectionState.update).not.toHaveBeenCalled();
|
||||
expect(mockFetch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not request a reconnect when a full edit payload keeps connection settings unchanged', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
const service = new ChannelsService(prisma as never);
|
||||
|
||||
await service.updateChannel('channel-1', {
|
||||
name: '主通道-完整保存',
|
||||
gatewayHost: '127.0.0.1',
|
||||
gatewayPort: 17890,
|
||||
account: 'sp',
|
||||
passwordCipher: 'secret',
|
||||
cmppVersion: '2.0',
|
||||
desiredConnections: 1,
|
||||
windowSize: 16,
|
||||
heartbeatIntervalSeconds: 30,
|
||||
heartbeatMissThreshold: 3,
|
||||
rateLimitPerSecond: 300,
|
||||
config: { serviceId: 'SMS' },
|
||||
});
|
||||
|
||||
expect(prisma.smsChannel.update).toHaveBeenCalled();
|
||||
expect(mockFetch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('persists an arbitrary integer extension digit count within the supported range', async () => {
|
||||
@@ -663,8 +707,22 @@ describe('ChannelsService', () => {
|
||||
smsChannelGroupItem: { deleteMany: jest.fn(), createMany: jest.fn() },
|
||||
smsChannelGroup: {
|
||||
update: jest.fn(),
|
||||
findUnique: jest.fn().mockResolvedValue({ id: 'group-1' }),
|
||||
findUnique: jest.fn().mockResolvedValue({
|
||||
id: 'group-1',
|
||||
code: 'G-MOBILE',
|
||||
name: '移动组更新',
|
||||
carrier: 'mobile',
|
||||
description: null,
|
||||
status: 'active',
|
||||
retryEnabled: true,
|
||||
retryTimeLimitMinutes: 750,
|
||||
items: [
|
||||
{ channelId: 'channel-national', carrier: 'mobile', province: null, priority: 1, weight: 1, isBackup: false, channel: { code: 'CMPP-N', name: '全国通道' } },
|
||||
{ channelId: 'channel-sd', carrier: 'mobile', province: '山东', priority: 10, weight: 1, isBackup: false, channel: { code: 'CMPP-SD', name: '山东通道' } },
|
||||
],
|
||||
}),
|
||||
},
|
||||
operationLog: { create: jest.fn() },
|
||||
};
|
||||
await transactionCallback(tx);
|
||||
expect(tx.smsChannelGroup.update).toHaveBeenCalledWith({
|
||||
@@ -674,6 +732,22 @@ describe('ChannelsService', () => {
|
||||
for (const item of tx.smsChannelGroupItem.createMany.mock.calls[0][0].data) {
|
||||
expect(item).not.toHaveProperty('rateLimitPerSecond');
|
||||
}
|
||||
expect(tx.operationLog.create).toHaveBeenCalledWith({
|
||||
data: expect.objectContaining({
|
||||
action: 'sms_channel_group.update',
|
||||
resource: 'sms_channel_group',
|
||||
resourceId: 'group-1',
|
||||
detail: expect.objectContaining({
|
||||
before: expect.objectContaining({ name: '移动组' }),
|
||||
after: expect.objectContaining({
|
||||
name: '移动组更新',
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({ channelId: 'channel-national', priority: 1, channelName: '全国通道' }),
|
||||
]),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
await expect(service.updateGroup('group-1', {
|
||||
carrier: 'mobile',
|
||||
|
||||
Reference in New Issue
Block a user