feat(1.4.0-beta1): 1. 场景支持配置阻塞策略

This commit is contained in:
opensnail 2025-02-22 23:28:54 +08:00
parent c6793e0382
commit ce1424825e
8 changed files with 170 additions and 110 deletions

View File

@ -730,6 +730,7 @@ const local: App.I18n.Schema = {
updateDt: 'Update time',
description: 'Describe',
routeKey: 'Routing strategy',
blockStrategy: 'Block strategy',
cbStatus: 'Callback status',
cbTriggerType: 'Callback TriggerType',
cbTriggerInterval: 'Callback Trigger Interval',

View File

@ -738,6 +738,7 @@ const local: App.I18n.Schema = {
updateDt: '更新时间',
description: '描述',
routeKey: '路由策略',
blockStrategy: '阻塞策略',
cbStatus: '回调开关',
cbTriggerType: '回调触发类型',
cbTriggerInterval: '回调触发间隔',

View File

@ -79,6 +79,9 @@ declare namespace Api {
/** 阻塞策略 1:丢弃 2:覆盖 3:并行 4:恢复 */
type BlockStrategy = 1 | 2 | 3 | 4;
/** 阻塞策略 1:丢弃 2:覆盖 3:并行 */
type RetryBlockStrategy = 1 | 2 | 3 | 4;
/** 失败策略 1:跳过 2:阻塞 */
type FailStrategy = 1 | 2;
@ -833,6 +836,7 @@ declare namespace Api {
*/
namespace RetryScene {
import EnableStatusNumber = Api.Common.EnableStatusNumber;
import RetryBlockStrategy = Api.Common.RetryBlockStrategy;
type CommonSearchParams = Pick<Common.PaginatingCommonParams, 'page' | 'size'>;
/** scene */
@ -843,6 +847,8 @@ declare namespace Api {
sceneName: string;
/** 通知场景ids */
notifyIds: number[];
/** 阻塞策略 */
blockStrategy: RetryBlockStrategy;
/** 状态 */
sceneStatus: EnableStatusNumber;
/** 退避策略 */

View File

@ -938,6 +938,7 @@ declare namespace App {
updateDt: string;
description: string;
routeKey: string;
blockStrategy: string;
cbStatus: string;
cbTriggerType: string;
cbTriggerInterval: string;

View File

@ -27,13 +27,19 @@ function search() {
</script>
<template>
<SearchForm btn-span="24 m:9 xl:3" :model="model" @search="search" @reset="reset">
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryLog.groupName')" path="groupName" class="pr-24px">
<SearchForm btn-span="12 s:24 m:10 l:12 xl:16" :model="model" @search="search" @reset="reset">
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryTask.groupName')" path="groupName" class="pr-24px">
<SelectGroup v-model:value="model.groupName" clearable />
</NFormItemGi>
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryLog.sceneName')" path="sceneName" class="pr-24px">
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryTask.sceneName')" path="sceneName" class="pr-24px">
<SelectScene v-model:value="model.sceneName" :group-name="model.groupName as string" clearable />
</NFormItemGi>
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retry.bizNo')" path="bizNo" class="pr-24px">
<NInput v-model:value="model.bizNo" :placeholder="$t('page.retry.form.bizNo')" clearable />
</NFormItemGi>
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retry.idempotentId')" path="idempotentId" class="pr-24px">
<NInput v-model:value="model.idempotentId" :placeholder="$t('page.retry.form.idempotentId')" clearable />
</NFormItemGi>
<NFormItemGi span="24 s:12 m:15 l:12 xl:9" :label="$t('page.common.createTime')" path="datetimeRange">
<DatetimeRange v-model:value="model.datetimeRange!" />
</NFormItemGi>

View File

@ -11,7 +11,13 @@ import {
import { $t } from '@/locales';
import { useAppStore } from '@/store/modules/app';
import { useTable, useTableOperate } from '@/hooks/common/table';
import { DelayLevel, backOffRecord, routeKeyRecord } from '@/constants/business';
import {
DelayLevel,
backOffRecord,
blockStrategyRecord,
groupConfigStatusRecord,
routeKeyRecord
} from '@/constants/business';
import StatusSwitch from '@/components/common/status-switch.vue';
import { downloadFetch } from '@/utils/download';
import { useAuth } from '@/hooks/business/auth';
@ -44,12 +50,12 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
align: 'center',
width: 48
},
{
key: 'id',
title: $t('common.index'),
align: 'center',
width: 64
},
// {
// key: 'id',
// title: $t('common.index'),
// align: 'center',
// width: 64
// },
{
key: 'sceneName',
align: 'center',
@ -72,13 +78,13 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
{
key: 'groupName',
title: $t('page.retryScene.groupName'),
align: 'left',
align: 'center',
width: 180
},
{
key: 'sceneStatus',
title: $t('page.retryScene.sceneStatus'),
align: 'left',
align: 'center',
width: 50,
render: row => {
const fetchFn = async (sceneStatus: Api.Common.EnableStatusNumber, callback: (flag: boolean) => void) => {
@ -96,7 +102,7 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
{
key: 'backOff',
title: $t('page.retryScene.backOff'),
align: 'left',
align: 'center',
width: 80,
render: row => {
const label = $t(backOffRecord[row.backOff!]);
@ -106,23 +112,37 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
{
key: 'routeKey',
title: $t('page.retryScene.routeKey'),
align: 'left',
align: 'center',
width: 80,
render: row => {
const label = $t(routeKeyRecord[row.routeKey!]);
return <NTag type="primary">{label}</NTag>;
}
},
{
key: 'cbStatus',
title: $t('page.retryScene.cbStatus'),
align: 'center',
width: 80,
render: row => {
const tagMap: Record<Api.Common.EnableStatusNumber, NaiveUI.ThemeColor> = {
0: 'error',
1: 'primary'
};
const label = $t(groupConfigStatusRecord[row.cbStatus!]);
return <NTag type={tagMap[row.cbStatus!]}>{label}</NTag>;
}
},
{
key: 'maxRetryCount',
title: $t('page.retryScene.maxRetryCount'),
align: 'left',
align: 'center',
width: 80
},
{
key: 'triggerInterval',
title: $t('page.retryScene.triggerInterval'),
align: 'left',
align: 'center',
width: 130,
render: row => {
if (row.backOff === 1) {
@ -133,33 +153,37 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
}
},
{
key: 'deadlineRequest',
title: $t('page.retryScene.deadlineRequest'),
align: 'left',
width: 120
key: 'blockStrategy',
title: $t('page.retryScene.blockStrategy'),
align: 'center',
width: 80,
render: row => {
const label = $t(blockStrategyRecord[row.blockStrategy!]);
return <NTag type="primary">{label}</NTag>;
}
},
{
key: 'executorTimeout',
title: $t('page.retryScene.executorTimeout'),
align: 'left',
align: 'center',
width: 80
},
{
key: 'createDt',
title: $t('page.retryScene.createDt'),
align: 'left',
align: 'center',
width: 120
},
{
key: 'updateDt',
title: $t('page.retryScene.updateDt'),
align: 'left',
align: 'center',
width: 120
},
{
key: 'description',
title: $t('page.retryScene.description'),
align: 'left',
align: 'center',
width: 120
},
{

View File

@ -12,6 +12,7 @@ import {
groupConfigYesOrNoOptions
} from '@/constants/business';
import { isNotNull, translateOptions } from '@/utils/common';
import BlockStrategy from '@/components/common/block-strategy.vue';
defineOptions({
name: 'SceneOperateDrawer'
@ -25,6 +26,7 @@ interface Props {
}
const delayLevelDesc = ref<string>('10s');
const callbackDelayLevelDesc = ref<string>('10s');
const notifyNameList = ref<CommonType.Option<number>[]>([]);
const props = defineProps<Props>();
@ -64,6 +66,7 @@ type Model = Pick<
| 'executorTimeout'
| 'description'
| 'routeKey'
| 'blockStrategy'
| 'cbStatus'
| 'cbTriggerType'
| 'cbTriggerInterval'
@ -96,9 +99,10 @@ function createDefaultModel(): Model {
executorTimeout: 60,
description: '',
routeKey: 4,
blockStrategy: 1,
cbStatus: 0,
cbTriggerType: 2,
cbTriggerInterval: '60',
cbTriggerType: 1,
cbTriggerInterval: '',
cbMaxCount: 16
};
}
@ -114,6 +118,7 @@ type RuleKey = Extract<
| 'deadlineRequest'
| 'executorTimeout'
| 'routeKey'
| 'blockStrategy'
| 'cbStatus'
| 'cbTriggerType'
| 'cbTriggerInterval'
@ -140,6 +145,7 @@ const rules = {
deadlineRequest: [defaultRequiredRule],
executorTimeout: [defaultRequiredRule],
routeKey: [defaultRequiredRule],
blockStrategy: [defaultRequiredRule],
cbStatus: [defaultRequiredRule],
cbTriggerType: [defaultRequiredRule],
cbMaxCount: [defaultRequiredRule],
@ -178,6 +184,7 @@ async function handleSubmit() {
deadlineRequest,
executorTimeout,
routeKey,
blockStrategy,
description,
cbStatus,
cbTriggerType,
@ -195,6 +202,7 @@ async function handleSubmit() {
deadlineRequest,
executorTimeout,
routeKey,
blockStrategy,
description,
cbStatus,
cbTriggerType,
@ -218,6 +226,7 @@ async function handleSubmit() {
deadlineRequest,
executorTimeout,
routeKey,
blockStrategy,
description,
cbStatus,
cbTriggerType,
@ -236,6 +245,7 @@ async function handleSubmit() {
deadlineRequest,
executorTimeout,
routeKey,
blockStrategy,
description,
cbStatus,
cbTriggerType,
@ -272,6 +282,14 @@ watch(
},
{ immediate: true }
);
watch(
() => model.cbMaxCount,
() => {
callbackDelayLevelDesc.value = Object.values(DelayLevel).slice(0, model.cbMaxCount).join(',');
},
{ immediate: true }
);
</script>
<template>
@ -310,14 +328,8 @@ watch(
</NFormItem>
</NGi>
<NGi>
<NFormItem :label="$t('page.retryScene.maxRetryCount')" path="maxRetryCount">
<NInputNumber
v-model:value="model.maxRetryCount"
:min="1"
:max="model.backOff === 1 ? 26 : 9999999"
:placeholder="$t('page.retryScene.form.maxRetryCount')"
clearable
/>
<NFormItem :label="$t('page.retryScene.blockStrategy')" path="blockStrategy">
<BlockStrategy v-model:value="model.blockStrategy" />
</NFormItem>
</NGi>
</NGrid>
@ -333,44 +345,53 @@ watch(
</NFormItem>
</NGi>
<NGi>
<NFormItem path="triggerInterval">
<SceneTriggerInterval
v-if="model.backOff !== 1"
v-model="model.triggerInterval"
:back-off="model.backOff"
<NFormItem :label="$t('page.retryScene.maxRetryCount')" path="maxRetryCount">
<NInputNumber
v-model:value="model.maxRetryCount"
:min="1"
:max="model.backOff === 1 ? 26 : 9999999"
:placeholder="$t('page.retryScene.form.maxRetryCount')"
clearable
/>
<NInput
v-else
v-model:value="delayLevelDesc"
type="textarea"
:autosize="{ minRows: 1, maxRows: 3 }"
readonly
/>
<template #label>
<div class="flex-center">
{{ $t('page.retryScene.triggerInterval') }}
<NTooltip v-if="model.backOff === 1" trigger="hover">
<template #trigger>
<NButton text class="ml-6px">
<SvgIcon icon="ant-design:info-circle-outlined" class="mb-1px text-16px" />
</NButton>
</template>
延迟等级是参考RocketMQ的messageDelayLevel设计实现具体延迟时间如下:
10s,15s,30s,35s,40s,50s,1m,2m,4m,6m,8m,10m,20m,40m,1h,2h,3h,4h,5h,6h,7h,8h,9h,10h,11h,12h
<br />
<NText strong>执行逻辑:</NText>
<NUl align-text>
<NLi>第一次执行间隔10s</NLi>
<NLi>第二次执行间隔15s</NLi>
<NLi>l第二次执行间隔30s</NLi>
<NLi>........... 依次类推</NLi>
</NUl>
</NTooltip>
</div>
</template>
</NFormItem>
</NGi>
</NGrid>
<NFormItem path="triggerInterval">
<SceneTriggerInterval
v-if="model.backOff !== 1"
v-model="model.triggerInterval"
:back-off="model.backOff"
/>
<NInput
v-else
v-model:value="delayLevelDesc"
type="textarea"
:autosize="{ minRows: 1, maxRows: 3 }"
readonly
/>
<template #label>
<div class="flex-center">
{{ $t('page.retryScene.triggerInterval') }}
<NTooltip v-if="model.backOff === 1" trigger="hover">
<template #trigger>
<NButton text class="ml-6px">
<SvgIcon icon="ant-design:info-circle-outlined" class="mb-1px text-16px" />
</NButton>
</template>
延迟等级是参考RocketMQ的messageDelayLevel设计实现具体延迟时间如下:
10s,15s,30s,35s,40s,50s,1m,2m,4m,6m,8m,10m,20m,40m,1h,2h,3h,4h,5h,6h,7h,8h,9h,10h,11h,12h
<br />
<NText strong>执行逻辑:</NText>
<NUl align-text>
<NLi>第一次执行间隔10s</NLi>
<NLi>第二次执行间隔15s</NLi>
<NLi>l第二次执行间隔30s</NLi>
<NLi>........... 依次类推</NLi>
</NUl>
</NTooltip>
</div>
</template>
</NFormItem>
<NGrid cols="2 s:1 m:2" responsive="screen" x-gap="20">
<NGi>
<NFormItem :label="$t('page.retryScene.executorTimeout')" path="executorTimeout">
@ -448,52 +469,52 @@ watch(
</NFormItem>
</NGi>
<NGi>
<NFormItem path="cbTriggerInterval">
<SceneTriggerInterval
v-if="model.cbTriggerType !== 1"
v-model="model.cbTriggerInterval"
:back-off="model.cbTriggerType"
<NFormItem :label="$t('page.retryScene.cbMaxCount')" path="cbMaxCount">
<NInputNumber
v-model:value="model.cbMaxCount"
:min="1"
:max="model.backOff === 1 ? 26 : 9999999"
:placeholder="$t('page.retryScene.form.cbMaxCount')"
clearable
/>
<NInput
v-else
v-model:value="delayLevelDesc"
type="textarea"
:autosize="{ minRows: 1, maxRows: 3 }"
readonly
/>
<template #label>
<div class="flex-center">
{{ $t('page.retryScene.cbTriggerInterval') }}
<NTooltip v-if="model.cbTriggerType === 1" trigger="hover">
<template #trigger>
<NButton text class="ml-6px">
<SvgIcon icon="ant-design:info-circle-outlined" class="mb-1px text-16px" />
</NButton>
</template>
延迟等级是参考RocketMQ的messageDelayLevel设计实现具体延迟时间如下:
10s,15s,30s,35s,40s,50s,1m,2m,4m,6m,8m,10m,20m,40m,1h,2h,3h,4h,5h,6h,7h,8h,9h,10h,11h,12h
<br />
<NText strong>执行逻辑:</NText>
<NUl align-text>
<NLi>第一次执行间隔10s</NLi>
<NLi>第二次执行间隔15s</NLi>
<NLi>l第二次执行间隔30s</NLi>
<NLi>........... 依次类推</NLi>
</NUl>
</NTooltip>
</div>
</template>
</NFormItem>
</NGi>
</NGrid>
<NFormItem :label="$t('page.retryScene.cbMaxCount')" path="cbMaxCount">
<NInputNumber
v-model:value="model.cbMaxCount"
:min="1"
:max="model.backOff === 1 ? 26 : 9999999"
:placeholder="$t('page.retryScene.form.cbMaxCount')"
clearable
<NFormItem path="cbTriggerInterval">
<SceneTriggerInterval
v-if="model.cbTriggerType !== 1"
v-model="model.cbTriggerInterval"
:back-off="model.cbTriggerType"
/>
<NInput
v-else
v-model:value="callbackDelayLevelDesc"
type="textarea"
:autosize="{ minRows: 1, maxRows: 3 }"
readonly
/>
<template #label>
<div class="flex-center">
{{ $t('page.retryScene.cbTriggerInterval') }}
<NTooltip v-if="model.cbTriggerType === 1" trigger="hover">
<template #trigger>
<NButton text class="ml-6px">
<SvgIcon icon="ant-design:info-circle-outlined" class="mb-1px text-16px" />
</NButton>
</template>
延迟等级是参考RocketMQ的messageDelayLevel设计实现具体延迟时间如下:
10s,15s,30s,35s,40s,50s,1m,2m,4m,6m,8m,10m,20m,40m,1h,2h,3h,4h,5h,6h,7h,8h,9h,10h,11h,12h
<br />
<NText strong>执行逻辑:</NText>
<NUl align-text>
<NLi>第一次执行间隔10s</NLi>
<NLi>第二次执行间隔15s</NLi>
<NLi>l第二次执行间隔30s</NLi>
<NLi>........... 依次类推</NLi>
</NUl>
</NTooltip>
</div>
</template>
</NFormItem>
</NCollapseItem>
</NCollapse>

View File

@ -29,7 +29,7 @@ function search() {
</script>
<template>
<SearchForm btn-span="24 xl:3" :model="model" @search="search" @reset="reset">
<SearchForm btn-span="12 s:24 m:10 l:12 xl:16" :model="model" @search="search" @reset="reset">
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryTask.groupName')" path="groupName" class="pr-24px">
<SelectGroup v-model:value="model.groupName" clearable />
</NFormItemGi>