|
|
|
@@ -69,55 +69,70 @@ const channelTestModes = [
|
|
|
|
|
'passive_recovery',
|
|
|
|
|
] as const
|
|
|
|
|
type ChannelTestMode = (typeof channelTestModes)[number]
|
|
|
|
|
const MAX_CHANNEL_TEST_CONCURRENCY = 32
|
|
|
|
|
|
|
|
|
|
const routingReliabilitySchema = z
|
|
|
|
|
.object({
|
|
|
|
|
RetryTimes: z.coerce.number().min(0).max(10),
|
|
|
|
|
ChannelDisableThreshold: numericString,
|
|
|
|
|
AutomaticDisableChannelEnabled: z.boolean(),
|
|
|
|
|
AutomaticEnableChannelEnabled: z.boolean(),
|
|
|
|
|
AutomaticDisableKeywords: z.string(),
|
|
|
|
|
AutomaticDisableStatusCodes: z.string(),
|
|
|
|
|
AutomaticRetryStatusCodes: z.string(),
|
|
|
|
|
monitor_setting: z.object({
|
|
|
|
|
auto_test_channel_enabled: z.boolean(),
|
|
|
|
|
auto_test_channel_minutes: z.coerce
|
|
|
|
|
.number()
|
|
|
|
|
.int()
|
|
|
|
|
.min(1, 'Interval must be at least 1 minute'),
|
|
|
|
|
channel_test_mode: z.enum(channelTestModes),
|
|
|
|
|
}),
|
|
|
|
|
})
|
|
|
|
|
.superRefine((values, ctx) => {
|
|
|
|
|
const disableParsed = parseHttpStatusCodeRules(
|
|
|
|
|
values.AutomaticDisableStatusCodes
|
|
|
|
|
)
|
|
|
|
|
if (!disableParsed.ok) {
|
|
|
|
|
ctx.addIssue({
|
|
|
|
|
code: 'custom',
|
|
|
|
|
path: ['AutomaticDisableStatusCodes'],
|
|
|
|
|
message: `Invalid status code rules: ${disableParsed.invalidTokens.join(
|
|
|
|
|
', '
|
|
|
|
|
)}`,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
const createRoutingReliabilitySchema = (
|
|
|
|
|
t: (key: string, options?: Record<string, unknown>) => string
|
|
|
|
|
) =>
|
|
|
|
|
z
|
|
|
|
|
.object({
|
|
|
|
|
RetryTimes: z.coerce.number().min(0).max(10),
|
|
|
|
|
ChannelDisableThreshold: numericString,
|
|
|
|
|
AutomaticDisableChannelEnabled: z.boolean(),
|
|
|
|
|
AutomaticEnableChannelEnabled: z.boolean(),
|
|
|
|
|
AutomaticDisableKeywords: z.string(),
|
|
|
|
|
AutomaticDisableStatusCodes: z.string(),
|
|
|
|
|
AutomaticRetryStatusCodes: z.string(),
|
|
|
|
|
monitor_setting: z.object({
|
|
|
|
|
auto_test_channel_enabled: z.boolean(),
|
|
|
|
|
auto_test_channel_minutes: z.coerce
|
|
|
|
|
.number()
|
|
|
|
|
.int()
|
|
|
|
|
.min(1, t('Interval must be at least 1 minute')),
|
|
|
|
|
channel_test_concurrency: z.coerce
|
|
|
|
|
.number()
|
|
|
|
|
.int(t('Enter a positive integer'))
|
|
|
|
|
.min(1, t('Channel test concurrency must be between 1 and 32'))
|
|
|
|
|
.max(
|
|
|
|
|
MAX_CHANNEL_TEST_CONCURRENCY,
|
|
|
|
|
t('Channel test concurrency must be between 1 and 32')
|
|
|
|
|
),
|
|
|
|
|
channel_test_mode: z.enum(channelTestModes),
|
|
|
|
|
}),
|
|
|
|
|
})
|
|
|
|
|
.superRefine((values, ctx) => {
|
|
|
|
|
const disableParsed = parseHttpStatusCodeRules(
|
|
|
|
|
values.AutomaticDisableStatusCodes
|
|
|
|
|
)
|
|
|
|
|
if (!disableParsed.ok) {
|
|
|
|
|
ctx.addIssue({
|
|
|
|
|
code: 'custom',
|
|
|
|
|
path: ['AutomaticDisableStatusCodes'],
|
|
|
|
|
message: t('Invalid status code rules: {{tokens}}', {
|
|
|
|
|
tokens: disableParsed.invalidTokens.join(', '),
|
|
|
|
|
}),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const retryParsed = parseHttpStatusCodeRules(
|
|
|
|
|
values.AutomaticRetryStatusCodes
|
|
|
|
|
)
|
|
|
|
|
if (!retryParsed.ok) {
|
|
|
|
|
ctx.addIssue({
|
|
|
|
|
code: 'custom',
|
|
|
|
|
path: ['AutomaticRetryStatusCodes'],
|
|
|
|
|
message: `Invalid status code rules: ${retryParsed.invalidTokens.join(
|
|
|
|
|
', '
|
|
|
|
|
)}`,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
const retryParsed = parseHttpStatusCodeRules(
|
|
|
|
|
values.AutomaticRetryStatusCodes
|
|
|
|
|
)
|
|
|
|
|
if (!retryParsed.ok) {
|
|
|
|
|
ctx.addIssue({
|
|
|
|
|
code: 'custom',
|
|
|
|
|
path: ['AutomaticRetryStatusCodes'],
|
|
|
|
|
message: t('Invalid status code rules: {{tokens}}', {
|
|
|
|
|
tokens: retryParsed.invalidTokens.join(', '),
|
|
|
|
|
}),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
type RoutingReliabilityFormValues = z.output<typeof routingReliabilitySchema>
|
|
|
|
|
type RoutingReliabilityFormInput = z.input<typeof routingReliabilitySchema>
|
|
|
|
|
type RoutingReliabilitySchema = ReturnType<
|
|
|
|
|
typeof createRoutingReliabilitySchema
|
|
|
|
|
>
|
|
|
|
|
type RoutingReliabilityFormValues = z.output<RoutingReliabilitySchema>
|
|
|
|
|
type RoutingReliabilityFormInput = z.input<RoutingReliabilitySchema>
|
|
|
|
|
|
|
|
|
|
type RoutingReliabilitySectionProps = {
|
|
|
|
|
defaultValues: {
|
|
|
|
@@ -130,6 +145,7 @@ type RoutingReliabilitySectionProps = {
|
|
|
|
|
AutomaticRetryStatusCodes: string
|
|
|
|
|
'monitor_setting.auto_test_channel_enabled': boolean
|
|
|
|
|
'monitor_setting.auto_test_channel_minutes': number
|
|
|
|
|
'monitor_setting.channel_test_concurrency': number
|
|
|
|
|
'monitor_setting.channel_test_mode': ChannelTestMode
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -148,6 +164,7 @@ type NormalizedRoutingReliabilityValues = {
|
|
|
|
|
AutomaticRetryStatusCodes: string
|
|
|
|
|
'monitor_setting.auto_test_channel_enabled': boolean
|
|
|
|
|
'monitor_setting.auto_test_channel_minutes': number
|
|
|
|
|
'monitor_setting.channel_test_concurrency': number
|
|
|
|
|
'monitor_setting.channel_test_mode': ChannelTestMode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -175,6 +192,8 @@ const buildFormDefaults = (
|
|
|
|
|
defaults['monitor_setting.auto_test_channel_enabled'],
|
|
|
|
|
auto_test_channel_minutes:
|
|
|
|
|
defaults['monitor_setting.auto_test_channel_minutes'],
|
|
|
|
|
channel_test_concurrency:
|
|
|
|
|
defaults['monitor_setting.channel_test_concurrency'],
|
|
|
|
|
channel_test_mode: normalizeChannelTestMode(
|
|
|
|
|
defaults['monitor_setting.channel_test_mode']
|
|
|
|
|
),
|
|
|
|
@@ -201,6 +220,8 @@ const normalizeDefaults = (
|
|
|
|
|
defaults['monitor_setting.auto_test_channel_enabled'],
|
|
|
|
|
'monitor_setting.auto_test_channel_minutes':
|
|
|
|
|
defaults['monitor_setting.auto_test_channel_minutes'],
|
|
|
|
|
'monitor_setting.channel_test_concurrency':
|
|
|
|
|
defaults['monitor_setting.channel_test_concurrency'],
|
|
|
|
|
'monitor_setting.channel_test_mode': normalizeChannelTestMode(
|
|
|
|
|
defaults['monitor_setting.channel_test_mode']
|
|
|
|
|
),
|
|
|
|
@@ -226,6 +247,8 @@ const normalizeFormValues = (
|
|
|
|
|
values.monitor_setting.auto_test_channel_enabled,
|
|
|
|
|
'monitor_setting.auto_test_channel_minutes':
|
|
|
|
|
values.monitor_setting.auto_test_channel_minutes,
|
|
|
|
|
'monitor_setting.channel_test_concurrency':
|
|
|
|
|
values.monitor_setting.channel_test_concurrency,
|
|
|
|
|
'monitor_setting.channel_test_mode': values.monitor_setting.channel_test_mode,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
@@ -234,6 +257,7 @@ export function RoutingReliabilitySection({
|
|
|
|
|
}: RoutingReliabilitySectionProps) {
|
|
|
|
|
const { t } = useTranslation()
|
|
|
|
|
const updateOption = useUpdateOption()
|
|
|
|
|
const routingReliabilitySchema = createRoutingReliabilitySchema(t)
|
|
|
|
|
const baselineRef = useRef<NormalizedRoutingReliabilityValues>(
|
|
|
|
|
normalizeDefaults(defaultValues)
|
|
|
|
|
)
|
|
|
|
@@ -484,6 +508,31 @@ export function RoutingReliabilitySection({
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<FormField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='monitor_setting.channel_test_concurrency'
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem>
|
|
|
|
|
<FormLabel>{t('Channel test concurrency')}</FormLabel>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
type='number'
|
|
|
|
|
min={1}
|
|
|
|
|
max={MAX_CHANNEL_TEST_CONCURRENCY}
|
|
|
|
|
step={1}
|
|
|
|
|
{...safeNumberFieldProps(field)}
|
|
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
<FormDescription>
|
|
|
|
|
{t(
|
|
|
|
|
'Maximum number of channels tested at the same time (1-32)'
|
|
|
|
|
)}
|
|
|
|
|
</FormDescription>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<FormField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='AutomaticEnableChannelEnabled'
|
|
|
|
|