fix: implement channel group routing failover

This commit is contained in:
hectorzhao
2026-07-03 11:07:43 +08:00
parent 131f344ac4
commit a890b03163
16 changed files with 853 additions and 121 deletions
+32 -3
View File
@@ -6,6 +6,7 @@ export interface CreateChannelDto {
code: string;
name: string;
carrier?: string;
sendRegion?: string;
protocol?: string;
gatewayHost: string;
gatewayPort: number;
@@ -25,6 +26,8 @@ export interface CreateChannelGroupDto {
name: string;
description?: string;
status?: string;
retryEnabled?: boolean;
retryTimeLimitHours?: number;
}
export interface CreateChannelGroupItemDto {
@@ -143,6 +146,7 @@ export class ChannelsService {
code: data.code,
name: data.name,
carrier: data.carrier,
sendRegion: data.sendRegion ?? '全国',
protocol: data.protocol ?? 'CMPP',
gatewayHost: data.gatewayHost,
gatewayPort,
@@ -207,6 +211,7 @@ export class ChannelsService {
account: source.account,
passwordCipher: source.passwordCipher,
srcId: source.srcId,
sendRegion: source.sendRegion,
cmppVersion: source.cmppVersion,
rateLimitPerSecond: source.rateLimitPerSecond,
unitPrice: source.unitPrice,
@@ -382,17 +387,29 @@ export class ChannelsService {
}
createGroup(data: CreateChannelGroupDto) {
const retryTimeLimitHours = data.retryTimeLimitHours ?? 72;
if (!Number.isInteger(retryTimeLimitHours) || retryTimeLimitHours <= 0 || retryTimeLimitHours > 72) {
throw new BadRequestException('retryTimeLimitHours must be an integer between 1 and 72');
}
return this.prisma.smsChannelGroup.create({
data: {
code: data.code,
name: data.name,
description: data.description,
status: data.status ?? 'active',
retryEnabled: data.retryEnabled ?? true,
retryTimeLimitHours,
},
});
}
addGroupItem(data: CreateChannelGroupItemDto) {
async addGroupItem(data: CreateChannelGroupItemDto) {
const existing = await this.prisma.smsChannelGroupItem.findFirst({
where: { groupId: data.groupId, channelId: data.channelId },
});
if (existing) {
throw new BadRequestException('通道组内不能重复配置同一通道');
}
return this.prisma.smsChannelGroupItem.create({
data: {
groupId: data.groupId,
@@ -416,14 +433,26 @@ export class ChannelsService {
}
createRouteRule(data: CreateRouteRuleDto) {
if (!data.applicationId) {
throw new BadRequestException('applicationId is required for channel group routing');
}
if (!data.carrier) {
throw new BadRequestException('carrier is required for application channel group routing');
}
if (data.channelId) {
throw new BadRequestException('Route rules can only bind channel groups, not single channels');
}
if (data.province) {
throw new BadRequestException('Province routing must be configured inside the channel group');
}
return this.prisma.channelRouteRule.create({
data: {
tenantId: data.tenantId,
applicationId: data.applicationId,
groupId: data.groupId,
channelId: data.channelId,
channelId: undefined,
carrier: data.carrier,
province: data.province,
province: undefined,
priority: data.priority ?? 100,
status: data.status ?? 'active',
},