This is an automated email from the ASF dual-hosted git repository.
dengliming pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 759ea514bb fix: Non-default HTTP retry backoff strategies cannot be
selected (#6529)
759ea514bb is described below
commit 759ea514bbda8d5216044683c1696e58c7b8c655
Author: hengyuss <[email protected]>
AuthorDate: Fri Sep 18 17:48:15 2026 +0800
fix: Non-default HTTP retry backoff strategies cannot be selected (#6529)
* fix: Non-default HTTP retry backoff strategies cannot be selected
* fix: add tests, fix sort conflict, and hide custom backoff strategy
- Add HttpRetryBackoffSpecEnumTest for acquireByName coverage
- Add retryBackOffSpec getter/setter test in DivideRuleHandleTest
- Add DividePluginTest assertions for HTTP_RETRY_BACK_OFF_SPEC attribute
- Fix plugin_handle sort conflict: retryBackOffSpec sort 0→1
- Disable custom dict entry (enabled 1→0) in all SQL dialects
- Remove CUSTOM_BACKOFF enum value and CustomRetryStrategy class
- Remove CUSTOM_BACKOFF case from AbstractHttpClientPlugin switch
* test: add tests
* fix: fix tests
* trigger CI
* fix: delete `custom` in shenyu.dict
* fix: fix tests
---------
Co-authored-by: Liming Deng <[email protected]>
---
db/init/mysql/schema.sql | 4 ++
db/init/ob/schema.sql | 4 ++
db/init/og/create-table.sql | 4 ++
db/init/oracle/schema.sql | 13 ++++++
db/init/pg/create-table.sql | 4 ++
db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql | 6 +++
db/upgrade/2.7.0-upgrade-2.7.1-ob.sql | 6 +++
db/upgrade/2.7.0-upgrade-2.7.1-og.sql | 6 +++
db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql | 10 +++++
db/upgrade/2.7.0-upgrade-2.7.1-pg.sql | 6 +++
.../src/main/resources/sql-script/h2/schema.sql | 4 ++
.../apache/shenyu/common/constant/Constants.java | 2 +-
.../dto/convert/rule/impl/DivideRuleHandle.java | 21 +++++++--
.../common/enums/HttpRetryBackoffSpecEnum.java | 7 +--
.../convert/rule/impl/DivideRuleHandleTest.java | 3 ++
.../common/enums/HttpRetryBackoffSpecEnumTest.java | 52 ++++++++++++++++++++++
.../httpclient/AbstractHttpClientPlugin.java | 11 ++---
.../plugin/httpclient/CustomRetryStrategy.java | 51 ---------------------
.../apache/shenyu/plugin/divide/DividePlugin.java | 2 +
.../shenyu/plugin/divide/DividePluginTest.java | 32 ++++++++++++-
20 files changed, 179 insertions(+), 69 deletions(-)
diff --git a/db/init/mysql/schema.sql b/db/init/mysql/schema.sql
index d88db8536d..1810760524 100644
--- a/db/init/mysql/schema.sql
+++ b/db/init/mysql/schema.sql
@@ -1102,6 +1102,7 @@ INSERT INTO `plugin_handle` VALUES
('1529402613199978551', '5', 'multiRuleHandle
INSERT INTO `plugin_handle` VALUES ('1529402613199978552', '5',
'headerMaxSize', 'headerMaxSize', 1, 2, 3,
'{\"defaultValue\":\"10240\",\"rule\":\"\"}', '2022-05-25 18:02:53',
'2022-05-25 18:02:53');
INSERT INTO `plugin_handle` VALUES ('1529402613199978553', '5',
'requestMaxSize', 'requestMaxSize', 1, 2, 4,
'{\"defaultValue\":\"102400\",\"rule\":\"\"}', '2022-05-25 18:02:53',
'2022-05-25 18:02:53');
INSERT INTO `plugin_handle` VALUES ('1529402613199978554', '5',
'retryStrategy', 'retryStrategy', 3, 2, 0,
'{\"required\":\"0\",\"defaultValue\":\"current\",\"placeholder\":\"retryStrategy\",\"rule\":\"\"}',
'2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1529402613199979560', '5',
'retryBackOffSpec', 'retryBackOffSpec', 3, 2, 1,
'{\"required\":\"0\",\"defaultValue\":\"default\",\"placeholder\":\"retryBackOffSpec\",\"rule\":\"\"}',
'2026-07-31 18:02:53', '2026-07-31 18:02:53');
INSERT INTO `plugin_handle` VALUES ('1529402613199978555', '13',
'upstreamHost', 'host', 2, 1, 0, NULL, '2022-05-25 18:02:53', '2022-05-25
18:02:53');
INSERT INTO `plugin_handle` VALUES ('1529402613199978556', '13', 'protocol',
'protocol', 2, 1, 2, '{\"defaultValue\":\"\",\"rule\":\"\"}', '2022-05-25
18:02:53', '2022-05-25 18:02:53');
INSERT INTO `plugin_handle` VALUES ('1529402613199978557', '13',
'upstreamUrl', 'ip:port', 2, 1, 1,
'{\"required\":\"1\",\"placeholder\":\"\",\"rule\":\"\"}', '2022-05-25
18:02:53', '2022-05-25 18:02:53');
@@ -2279,6 +2280,9 @@ INSERT INTO `shenyu_dict` VALUES ('1529402613195784237',
'threadpool', 'THREADPO
INSERT INTO `shenyu_dict` VALUES ('1529402613195784238', 'threadpool',
'THREADPOOL', 'limited', 'limited', '', 1, 1, '2022-05-25 18:02:53',
'2022-05-25 18:02:53');
INSERT INTO `shenyu_dict` VALUES ('1529402613195784239', 'retryStrategy',
'RETRY_STRATEGY', 'current', 'current', 'current', 0, 1, '2022-05-25 18:02:53',
'2022-05-25 18:02:53');
INSERT INTO `shenyu_dict` VALUES ('1529402613195784240', 'retryStrategy',
'RETRY_STRATEGY', 'failover', 'failover', 'failover', 1, 1, '2022-05-25
18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `shenyu_dict` VALUES ('1529402613195784250', 'retryBackOffSpec',
'RETRY_BACKOFF_SPEC', 'default', 'default', 'default', 0, 1, '2026-07-31
18:02:53', '2026-07-31 18:02:53');
+INSERT INTO `shenyu_dict` VALUES ('1529402613195784251', 'retryBackOffSpec',
'RETRY_BACKOFF_SPEC', 'fixed', 'fixed', 'fixed', 1, 1, '2026-07-31 18:02:53',
'2026-07-31 18:02:53');
+INSERT INTO `shenyu_dict` VALUES ('1529402613195784252', 'retryBackOffSpec',
'RETRY_BACKOFF_SPEC', 'exponential', 'exponential', 'exponential', 2, 1,
'2026-07-31 18:02:53', '2026-07-31 18:02:53');
INSERT INTO `shenyu_dict` VALUES ('1529402613195784241', 'table', 'INIT_FLAG',
'status', 'true', 'table(resource,permission) init status', 0, 0, '2022-05-25
18:02:53', '2022-05-25 18:02:58');
INSERT INTO `shenyu_dict` VALUES ('1529402613195784242', 'compressAlg',
'COMPRESS_ALG', 'none', 'none', '', 0, 1, '2022-05-25 18:02:53', '2022-05-25
18:02:53');
INSERT INTO `shenyu_dict` VALUES ('1529402613195784243', 'compressAlg',
'COMPRESS_ALG', 'LZ4', 'LZ4', '', 1, 1, '2022-05-25 18:02:53', '2022-05-25
18:02:53');
diff --git a/db/init/ob/schema.sql b/db/init/ob/schema.sql
index 2f259975fe..9741b14b0e 100644
--- a/db/init/ob/schema.sql
+++ b/db/init/ob/schema.sql
@@ -1069,6 +1069,7 @@ INSERT INTO `plugin_handle` VALUES
('1529402613199978551', '5', 'multiRuleHandle
INSERT INTO `plugin_handle` VALUES ('1529402613199978552', '5',
'headerMaxSize', 'headerMaxSize', 1, 2, 3,
'{\"defaultValue\":\"10240\",\"rule\":\"\"}', '2022-05-25 18:02:53',
'2022-05-25 18:02:53');
INSERT INTO `plugin_handle` VALUES ('1529402613199978553', '5',
'requestMaxSize', 'requestMaxSize', 1, 2, 4,
'{\"defaultValue\":\"102400\",\"rule\":\"\"}', '2022-05-25 18:02:53',
'2022-05-25 18:02:53');
INSERT INTO `plugin_handle` VALUES ('1529402613199978554', '5',
'retryStrategy', 'retryStrategy', 3, 2, 0,
'{\"required\":\"0\",\"defaultValue\":\"current\",\"placeholder\":\"retryStrategy\",\"rule\":\"\"}',
'2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1529402613199979560', '5',
'retryBackOffSpec', 'retryBackOffSpec', 3, 2, 1,
'{\"required\":\"0\",\"defaultValue\":\"default\",\"placeholder\":\"retryBackOffSpec\",\"rule\":\"\"}',
'2022-05-25 18:02:53', '2022-05-25 18:02:53');
INSERT INTO `plugin_handle` VALUES ('1529402613199978555', '13',
'upstreamHost', 'host', 2, 1, 0, NULL, '2022-05-25 18:02:53', '2022-05-25
18:02:53');
INSERT INTO `plugin_handle` VALUES ('1529402613199978556', '13', 'protocol',
'protocol', 2, 1, 2, '{\"defaultValue\":\"\",\"rule\":\"\"}', '2022-05-25
18:02:53', '2022-05-25 18:02:53');
INSERT INTO `plugin_handle` VALUES ('1529402613199978557', '13',
'upstreamUrl', 'ip:port', 2, 1, 1,
'{\"required\":\"1\",\"placeholder\":\"\",\"rule\":\"\"}', '2022-05-25
18:02:53', '2022-05-25 18:02:53');
@@ -2209,6 +2210,9 @@ INSERT INTO `shenyu_dict` VALUES ('1529402613195784237',
'threadpool', 'THREADPO
INSERT INTO `shenyu_dict` VALUES ('1529402613195784238', 'threadpool',
'THREADPOOL', 'limited', 'limited', '', 1, 1, '2022-05-25 18:02:53',
'2022-05-25 18:02:53');
INSERT INTO `shenyu_dict` VALUES ('1529402613195784239', 'retryStrategy',
'RETRY_STRATEGY', 'current', 'current', 'current', 0, 1, '2022-05-25 18:02:53',
'2022-05-25 18:02:53');
INSERT INTO `shenyu_dict` VALUES ('1529402613195784240', 'retryStrategy',
'RETRY_STRATEGY', 'failover', 'failover', 'failover', 1, 1, '2022-05-25
18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `shenyu_dict` VALUES ('1529402613195784250', 'retryBackOffSpec',
'RETRY_BACKOFF_SPEC', 'default', 'default', 'default', 0, 1, '2022-05-25
18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `shenyu_dict` VALUES ('1529402613195784251', 'retryBackOffSpec',
'RETRY_BACKOFF_SPEC', 'fixed', 'fixed', 'fixed', 1, 1, '2022-05-25 18:02:53',
'2022-05-25 18:02:53');
+INSERT INTO `shenyu_dict` VALUES ('1529402613195784252', 'retryBackOffSpec',
'RETRY_BACKOFF_SPEC', 'exponential', 'exponential', 'exponential', 2, 1,
'2022-05-25 18:02:53', '2022-05-25 18:02:53');
INSERT INTO `shenyu_dict` VALUES ('1529402613195784241', 'table', 'INIT_FLAG',
'status', 'true', 'table(resource,permission) init status', 0, 0, '2022-05-25
18:02:53', '2022-05-25 18:02:58');
INSERT INTO `shenyu_dict` VALUES ('1529402613195784242', 'compressAlg',
'COMPRESS_ALG', 'none', 'none', '', 0, 1, '2022-05-25 18:02:53', '2022-05-25
18:02:53');
INSERT INTO `shenyu_dict` VALUES ('1529402613195784243', 'compressAlg',
'COMPRESS_ALG', 'LZ4', 'LZ4', '', 1, 1, '2022-05-25 18:02:53', '2022-05-25
18:02:53');
diff --git a/db/init/og/create-table.sql b/db/init/og/create-table.sql
index 97a90b57fe..7f28716848 100644
--- a/db/init/og/create-table.sql
+++ b/db/init/og/create-table.sql
@@ -1090,6 +1090,7 @@ INSERT INTO "public"."plugin_handle" VALUES
('1529403902779330564', '5', 'multiR
INSERT INTO "public"."plugin_handle" VALUES ('1529403902779330565', '5',
'headerMaxSize', 'headerMaxSize', 1, 2, 3,
'{"defaultValue":"10240","rule":""}', '2022-05-25 18:08:01', '2022-05-25
18:08:01');
INSERT INTO "public"."plugin_handle" VALUES ('1529403902779330566', '5',
'requestMaxSize', 'requestMaxSize', 1, 2, 4,
'{"defaultValue":"102400","rule":""}', '2022-05-25 18:08:01', '2022-05-25
18:08:01');
INSERT INTO "public"."plugin_handle" VALUES ('1529403902779330567', '5',
'retryStrategy', 'retryStrategy', 3, 2, 0,
'{"required":"0","defaultValue":"current","placeholder":"retryStrategy","rule":""}',
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1529402613199979560', '5',
'retryBackOffSpec', 'retryBackOffSpec', 3, 2, 1,
'{"required":"0","defaultValue":"default","placeholder":"retryBackOffSpec","rule":""}',
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
INSERT INTO "public"."plugin_handle" VALUES ('1529403902779330568', '13',
'upstreamHost', 'host', 2, 1, 0, NULL, '2022-05-25 18:08:01', '2022-05-25
18:08:01');
INSERT INTO "public"."plugin_handle" VALUES ('1529403902779330569', '13',
'protocol', 'protocol', 2, 1, 2, '{"defaultValue":"","rule":""}', '2022-05-25
18:08:01', '2022-05-25 18:08:01');
INSERT INTO "public"."plugin_handle" VALUES ('1529403902779330570', '13',
'upstreamUrl', 'ip:port', 2, 1, 1,
'{"required":"1","placeholder":"","rule":""}', '2022-05-25 18:08:01',
'2022-05-25 18:08:01');
@@ -2165,6 +2166,9 @@ INSERT INTO "public"."shenyu_dict" VALUES
('1529403902800302089', 'threadpool',
INSERT INTO "public"."shenyu_dict" VALUES ('1529403902800302090',
'threadpool', 'THREADPOOL', 'limited', 'limited', '', 1, 1, '2022-05-25
18:08:02', '2022-05-25 18:08:02');
INSERT INTO "public"."shenyu_dict" VALUES ('1529403902800302091',
'retryStrategy', 'RETRY_STRATEGY', 'current', 'current', 'current', 0, 1,
'2022-05-25 18:08:02', '2022-05-25 18:08:02');
INSERT INTO "public"."shenyu_dict" VALUES ('1529403902800302092',
'retryStrategy', 'RETRY_STRATEGY', 'failover', 'failover', 'failover', 1, 1,
'2022-05-25 18:08:02', '2022-05-25 18:08:02');
+INSERT INTO "public"."shenyu_dict" VALUES ('1529402613195784250',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'default', 'default', 'default', 0,
1, '2022-05-25 18:08:02', '2022-05-25 18:08:02');
+INSERT INTO "public"."shenyu_dict" VALUES ('1529402613195784251',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'fixed', 'fixed', 'fixed', 1, 1,
'2022-05-25 18:08:02', '2022-05-25 18:08:02');
+INSERT INTO "public"."shenyu_dict" VALUES ('1529402613195784252',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'exponential', 'exponential',
'exponential', 2, 1, '2022-05-25 18:08:02', '2022-05-25 18:08:02');
INSERT INTO "public"."shenyu_dict" VALUES ('1529403902800302094',
'compressAlg', 'COMPRESS_ALG', 'none', 'none', '', 0, 1, '2022-05-25 18:08:02',
'2022-05-25 18:08:02');
INSERT INTO "public"."shenyu_dict" VALUES ('1529403902800302095',
'compressAlg', 'COMPRESS_ALG', 'LZ4', 'LZ4', '', 1, 1, '2022-05-25 18:08:02',
'2022-05-25 18:08:02');
INSERT INTO "public"."shenyu_dict" VALUES ('1529403902800302096', 'cacheType',
'CACHE_TYPE_MEMORY', 'memory', 'memory', 'use memory to cache data', 0, 1,
'2022-05-25 18:08:02', '2022-05-25 18:08:02');
diff --git a/db/init/oracle/schema.sql b/db/init/oracle/schema.sql
index aa44e96a33..8bb7ebadd2 100644
--- a/db/init/oracle/schema.sql
+++ b/db/init/oracle/schema.sql
@@ -1089,6 +1089,16 @@ values ('1518229897206079525', 'retryStrategy',
'RETRY_STRATEGY', 'current', 'cu
insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name))
*/ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT,
ENABLED)
values ('1518229897206079526', 'retryStrategy', 'RETRY_STRATEGY', 'failover',
'failover', 'failover', 1, 1);
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name))
*/ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT,
ENABLED)
+values ('1529402613195784250', 'retryBackOffSpec', 'RETRY_BACKOFF_SPEC',
'default', 'default', 'default', 0, 1);
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name))
*/ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT,
ENABLED)
+values ('1529402613195784251', 'retryBackOffSpec', 'RETRY_BACKOFF_SPEC',
'fixed', 'fixed', 'fixed', 1, 1);
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name))
*/ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT,
ENABLED)
+values ('1529402613195784252', 'retryBackOffSpec', 'RETRY_BACKOFF_SPEC',
'exponential', 'exponential', 'exponential', 2, 1);
+
+
insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name))
*/ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT,
ENABLED)
values ('1518229897206079527', 'table', 'INIT_FLAG', 'status', 'false',
'table(resource,permission) init status', 0, 0);
@@ -1595,6 +1605,9 @@ values ('1518229897210273844', '5', 'requestMaxSize',
'requestMaxSize', 1, 2, 4,
insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type))
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT,
EXT_OBJ)
values ('1518229897210273845', '5', 'retryStrategy', 'retryStrategy', 3, 2, 0,
'{"required":"0","defaultValue":"current","placeholder":"retryStrategy","rule":""}');
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type))
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT,
EXT_OBJ)
+values ('1529402613199979560', '5', 'retryBackOffSpec', 'retryBackOffSpec', 3,
2, 1,
'{"required":"0","defaultValue":"default","placeholder":"retryBackOffSpec","rule":""}');
+
insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type))
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT,
EXT_OBJ)
values ('1518229897210273846', '13', 'upstreamHost', 'host', 2, 1, 0, null);
diff --git a/db/init/pg/create-table.sql b/db/init/pg/create-table.sql
index f8e452297a..5cbf6c4df3 100644
--- a/db/init/pg/create-table.sql
+++ b/db/init/pg/create-table.sql
@@ -1148,6 +1148,7 @@ INSERT INTO "public"."plugin_handle" VALUES
('1529403902779330564', '5', 'multiR
INSERT INTO "public"."plugin_handle" VALUES ('1529403902779330565', '5',
'headerMaxSize', 'headerMaxSize', 1, 2, 3,
'{"defaultValue":"10240","rule":""}', '2022-05-25 18:08:01', '2022-05-25
18:08:01');
INSERT INTO "public"."plugin_handle" VALUES ('1529403902779330566', '5',
'requestMaxSize', 'requestMaxSize', 1, 2, 4,
'{"defaultValue":"102400","rule":""}', '2022-05-25 18:08:01', '2022-05-25
18:08:01');
INSERT INTO "public"."plugin_handle" VALUES ('1529403902779330567', '5',
'retryStrategy', 'retryStrategy', 3, 2, 0,
'{"required":"0","defaultValue":"current","placeholder":"retryStrategy","rule":""}',
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1529402613199979560', '5',
'retryBackOffSpec', 'retryBackOffSpec', 3, 2, 1,
'{"required":"0","defaultValue":"default","placeholder":"retryBackOffSpec","rule":""}',
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
INSERT INTO "public"."plugin_handle" VALUES ('1529403902779330568', '13',
'upstreamHost', 'host', 2, 1, 0, NULL, '2022-05-25 18:08:01', '2022-05-25
18:08:01');
INSERT INTO "public"."plugin_handle" VALUES ('1529403902779330569', '13',
'protocol', 'protocol', 2, 1, 2, '{"defaultValue":"","rule":""}', '2022-05-25
18:08:01', '2022-05-25 18:08:01');
INSERT INTO "public"."plugin_handle" VALUES ('1529403902779330570', '13',
'upstreamUrl', 'ip:port', 2, 1, 1,
'{"required":"1","placeholder":"","rule":""}', '2022-05-25 18:08:01',
'2022-05-25 18:08:01');
@@ -2289,6 +2290,9 @@ INSERT INTO "public"."shenyu_dict" VALUES
('1529403902800302089', 'threadpool',
INSERT INTO "public"."shenyu_dict" VALUES ('1529403902800302090',
'threadpool', 'THREADPOOL', 'limited', 'limited', '', 1, 1, '2022-05-25
18:08:02', '2022-05-25 18:08:02');
INSERT INTO "public"."shenyu_dict" VALUES ('1529403902800302091',
'retryStrategy', 'RETRY_STRATEGY', 'current', 'current', 'current', 0, 1,
'2022-05-25 18:08:02', '2022-05-25 18:08:02');
INSERT INTO "public"."shenyu_dict" VALUES ('1529403902800302092',
'retryStrategy', 'RETRY_STRATEGY', 'failover', 'failover', 'failover', 1, 1,
'2022-05-25 18:08:02', '2022-05-25 18:08:02');
+INSERT INTO "public"."shenyu_dict" VALUES ('1529402613195784250',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'default', 'default', 'default', 0,
1, '2022-05-25 18:08:02', '2022-05-25 18:08:02');
+INSERT INTO "public"."shenyu_dict" VALUES ('1529402613195784251',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'fixed', 'fixed', 'fixed', 1, 1,
'2022-05-25 18:08:02', '2022-05-25 18:08:02');
+INSERT INTO "public"."shenyu_dict" VALUES ('1529402613195784252',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'exponential', 'exponential',
'exponential', 2, 1, '2022-05-25 18:08:02', '2022-05-25 18:08:02');
INSERT INTO "public"."shenyu_dict" VALUES ('1529403902800302094',
'compressAlg', 'COMPRESS_ALG', 'none', 'none', '', 0, 1, '2022-05-25 18:08:02',
'2022-05-25 18:08:02');
INSERT INTO "public"."shenyu_dict" VALUES ('1529403902800302095',
'compressAlg', 'COMPRESS_ALG', 'LZ4', 'LZ4', '', 1, 1, '2022-05-25 18:08:02',
'2022-05-25 18:08:02');
INSERT INTO "public"."shenyu_dict" VALUES ('1529403902800302096', 'cacheType',
'CACHE_TYPE_MEMORY', 'memory', 'memory', 'use memory to cache data', 0, 1,
'2022-05-25 18:08:02', '2022-05-25 18:08:02');
diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql
b/db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql
index 978b4b53e7..7f9ce09ac3 100755
--- a/db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql
+++ b/db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql
@@ -360,3 +360,9 @@ DELETE FROM `namespace_plugin_rel` WHERE `plugin_id` = '17';
DELETE FROM `plugin_handle` WHERE `plugin_id` = '17';
DELETE FROM `plugin` WHERE `id` = '17';
ALTER TABLE `api` MODIFY COLUMN `rpc_type` varchar(64) CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci NOT NULL COMMENT
'http,dubbo,sofa,tars,websocket,springCloud,grpc';
+
+INSERT INTO `plugin_handle` VALUES ('1529402613199979560', '5',
'retryBackOffSpec', 'retryBackOffSpec', 3, 2, 1,
'{\"required\":\"0\",\"defaultValue\":\"default\",\"placeholder\":\"retryBackOffSpec\",\"rule\":\"\"}',
'2026-07-31 18:02:53', '2026-07-31 18:02:53');
+
+INSERT INTO `shenyu_dict` VALUES ('1529402613195784250', 'retryBackOffSpec',
'RETRY_BACKOFF_SPEC', 'default', 'default', 'default', 0, 1, '2026-07-31
18:02:53', '2026-07-31 18:02:53');
+INSERT INTO `shenyu_dict` VALUES ('1529402613195784251', 'retryBackOffSpec',
'RETRY_BACKOFF_SPEC', 'fixed', 'fixed', 'fixed', 1, 1, '2026-07-31 18:02:53',
'2026-07-31 18:02:53');
+INSERT INTO `shenyu_dict` VALUES ('1529402613195784252', 'retryBackOffSpec',
'RETRY_BACKOFF_SPEC', 'exponential', 'exponential', 'exponential', 2, 1,
'2026-07-31 18:02:53', '2026-07-31 18:02:53');
diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-ob.sql
b/db/upgrade/2.7.0-upgrade-2.7.1-ob.sql
index 6b8aac0afa..792719b3aa 100755
--- a/db/upgrade/2.7.0-upgrade-2.7.1-ob.sql
+++ b/db/upgrade/2.7.0-upgrade-2.7.1-ob.sql
@@ -352,3 +352,9 @@ DELETE FROM `namespace_plugin_rel` WHERE `plugin_id` = '17';
DELETE FROM `plugin_handle` WHERE `plugin_id` = '17';
DELETE FROM `plugin` WHERE `id` = '17';
ALTER TABLE `api` MODIFY COLUMN `rpc_type` varchar(64) CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci NOT NULL COMMENT
'http,dubbo,sofa,tars,websocket,springCloud,grpc';
+
+INSERT INTO `plugin_handle` VALUES ('1529402613199979560', '5',
'retryBackOffSpec', 'retryBackOffSpec', 3, 2, 1,
'{\"required\":\"0\",\"defaultValue\":\"default\",\"placeholder\":\"retryBackOffSpec\",\"rule\":\"\"}',
'2026-07-31 18:02:53', '2026-07-31 18:02:53');
+
+INSERT INTO `shenyu_dict` VALUES ('1529402613195784250', 'retryBackOffSpec',
'RETRY_BACKOFF_SPEC', 'default', 'default', 'default', 0, 1, '2026-07-31
18:02:53', '2026-07-31 18:02:53');
+INSERT INTO `shenyu_dict` VALUES ('1529402613195784251', 'retryBackOffSpec',
'RETRY_BACKOFF_SPEC', 'fixed', 'fixed', 'fixed', 1, 1, '2026-07-31 18:02:53',
'2026-07-31 18:02:53');
+INSERT INTO `shenyu_dict` VALUES ('1529402613195784252', 'retryBackOffSpec',
'RETRY_BACKOFF_SPEC', 'exponential', 'exponential', 'exponential', 2, 1,
'2026-07-31 18:02:53', '2026-07-31 18:02:53');
diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-og.sql
b/db/upgrade/2.7.0-upgrade-2.7.1-og.sql
index 36f6b4e122..5794093625 100644
--- a/db/upgrade/2.7.0-upgrade-2.7.1-og.sql
+++ b/db/upgrade/2.7.0-upgrade-2.7.1-og.sql
@@ -380,3 +380,9 @@ DELETE FROM "public"."namespace_plugin_rel" WHERE
"plugin_id" = '17';
DELETE FROM "public"."plugin_handle" WHERE "plugin_id" = '17';
DELETE FROM "public"."plugin" WHERE "id" = '17';
COMMENT ON COLUMN "public"."api"."rpc_type" IS
'http,dubbo,sofa,tars,websocket,springCloud,grpc';
+
+INSERT INTO "public"."plugin_handle" VALUES ('1529402613199979560', '5',
'retryBackOffSpec', 'retryBackOffSpec', 3, 2, 1,
'{"required":"0","defaultValue":"default","placeholder":"retryBackOffSpec","rule":""}',
'2026-07-31 18:02:53', '2026-07-31 18:02:53');
+
+INSERT INTO "public"."shenyu_dict" VALUES ('1529402613195784250',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'default', 'default', 'default', 0,
1, '2026-07-31 18:02:53', '2026-07-31 18:02:53');
+INSERT INTO "public"."shenyu_dict" VALUES ('1529402613195784251',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'fixed', 'fixed', 'fixed', 1, 1,
'2026-07-31 18:02:53', '2026-07-31 18:02:53');
+INSERT INTO "public"."shenyu_dict" VALUES ('1529402613195784252',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'exponential', 'exponential',
'exponential', 2, 1, '2026-07-31 18:02:53', '2026-07-31 18:02:53');
diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql
b/db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql
index c3ec9c2f9c..5aef068397 100755
--- a/db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql
+++ b/db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql
@@ -735,3 +735,13 @@ DELETE FROM namespace_plugin_rel WHERE plugin_id = '17';
DELETE FROM plugin_handle WHERE plugin_id = '17';
DELETE FROM plugin WHERE id = '17';
COMMENT ON COLUMN api.rpc_type IS
'http,dubbo,sofa,tars,websocket,springCloud,grpc';
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type))
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT,
EXT_OBJ)
+values ('1529402613199979560', '5', 'retryBackOffSpec', 'retryBackOffSpec', 3,
2, 1,
'{"required":"0","defaultValue":"default","placeholder":"retryBackOffSpec","rule":""}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name))
*/ into shenyu_dict (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "DESC", SORT,
ENABLED)
+values ('1529402613195784250', 'retryBackOffSpec', 'RETRY_BACKOFF_SPEC',
'default', 'default', 'default', 0, 1);
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name))
*/ into shenyu_dict (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "DESC", SORT,
ENABLED)
+values ('1529402613195784251', 'retryBackOffSpec', 'RETRY_BACKOFF_SPEC',
'fixed', 'fixed', 'fixed', 1, 1);
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name))
*/ into shenyu_dict (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "DESC", SORT,
ENABLED)
+values ('1529402613195784252', 'retryBackOffSpec', 'RETRY_BACKOFF_SPEC',
'exponential', 'exponential', 'exponential', 2, 1);
diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-pg.sql
b/db/upgrade/2.7.0-upgrade-2.7.1-pg.sql
index eca5d2cc53..55ee08a4ce 100755
--- a/db/upgrade/2.7.0-upgrade-2.7.1-pg.sql
+++ b/db/upgrade/2.7.0-upgrade-2.7.1-pg.sql
@@ -378,3 +378,9 @@ DELETE FROM "public"."namespace_plugin_rel" WHERE
"plugin_id" = '17';
DELETE FROM "public"."plugin_handle" WHERE "plugin_id" = '17';
DELETE FROM "public"."plugin" WHERE "id" = '17';
COMMENT ON COLUMN "public"."api"."rpc_type" IS
'http,dubbo,sofa,tars,websocket,springCloud,grpc';
+
+INSERT INTO "public"."plugin_handle" VALUES ('1529402613199979560', '5',
'retryBackOffSpec', 'retryBackOffSpec', 3, 2, 1,
'{"required":"0","defaultValue":"default","placeholder":"retryBackOffSpec","rule":""}',
'2026-07-31 18:02:53', '2026-07-31 18:02:53');
+
+INSERT INTO "public"."shenyu_dict" VALUES ('1529402613195784250',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'default', 'default', 'default', 0,
1, '2026-07-31 18:02:53', '2026-07-31 18:02:53');
+INSERT INTO "public"."shenyu_dict" VALUES ('1529402613195784251',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'fixed', 'fixed', 'fixed', 1, 1,
'2026-07-31 18:02:53', '2026-07-31 18:02:53');
+INSERT INTO "public"."shenyu_dict" VALUES ('1529402613195784252',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'exponential', 'exponential',
'exponential', 2, 1, '2026-07-31 18:02:53', '2026-07-31 18:02:53');
diff --git a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
index c38496b3e4..95e3f9951a 100644
--- a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
+++ b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
@@ -494,6 +494,9 @@ INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`,
`dict_name`, `dict_v
INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`,
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1529402613195784238',
'threadpool', 'THREADPOOL', 'limited', 'limited', '', 1, 1);
INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`,
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1529402613195784239',
'retryStrategy', 'RETRY_STRATEGY', 'current', 'current', 'current', 0, 1);
INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`,
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1529402613195784240',
'retryStrategy', 'RETRY_STRATEGY', 'failover', 'failover', 'failover', 1, 1);
+INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`,
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1529402613195784250',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'default', 'default', 'default', 0,
1);
+INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`,
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1529402613195784251',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'fixed', 'fixed', 'fixed', 1, 1);
+INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`,
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1529402613195784252',
'retryBackOffSpec', 'RETRY_BACKOFF_SPEC', 'exponential', 'exponential',
'exponential', 2, 1);
INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`,
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1529402613195784241',
'table', 'INIT_FLAG', 'status', 'false', 'table(resource,permission) init
status', 0, 1);
INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`,
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1529402613195784242',
'compressAlg', 'COMPRESS_ALG', 'none', 'none', '', 0, 1);
INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`,
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1529402613195784243',
'compressAlg', 'COMPRESS_ALG', 'LZ4', 'LZ4', '', 1, 1);
@@ -670,6 +673,7 @@ INSERT IGNORE INTO plugin_handle (`id`,
`plugin_id`,`field`,`label`,`data_type`,
INSERT IGNORE INTO plugin_handle (`id`,
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES
('1529402613199978552', '5', 'headerMaxSize', 'headerMaxSize', 1, 2, 3,
'{"defaultValue":"10240","rule":""}');
INSERT IGNORE INTO plugin_handle (`id`,
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES
('1529402613199978553', '5', 'requestMaxSize', 'requestMaxSize', 1, 2, 4,
'{"defaultValue":"102400","rule":""}');
INSERT IGNORE INTO plugin_handle (`id`,
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES
('1529402613199978554', '5', 'retryStrategy', 'retryStrategy', 3, 2, 0,
'{"required":"0","defaultValue":"current","placeholder":"retryStrategy","rule":""}');
+INSERT IGNORE INTO plugin_handle (`id`,
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES
('1529402613199979560', '5', 'retryBackOffSpec', 'retryBackOffSpec', 3, 2, 1,
'{"required":"0","defaultValue":"default","placeholder":"retryBackOffSpec","rule":""}');
INSERT IGNORE INTO plugin_handle (`id`,
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`) VALUES
('1529402613199978555', '13', 'upstreamHost', 'host', 2, 1, 0);
INSERT IGNORE INTO plugin_handle (`id`,
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES
('1529402613199978556', '13', 'protocol', 'protocol', 2, 1, 2,
'{"defaultValue":"","rule":""}');
INSERT IGNORE INTO plugin_handle (`id`,
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES
('1529402613199978557', '13', 'upstreamUrl', 'ip:port', 2, 1, 1,
'{"required":"1","placeholder":"","rule":""}');
diff --git
a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
index c852bfe5a9..ccc6c0e36c 100644
---
a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
+++
b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
@@ -1011,7 +1011,7 @@ public interface Constants {
/**
* Http request retry policy.
*/
- String HTTP_RETRY_BACK_OFF_SPEC = "default";
+ String HTTP_RETRY_BACK_OFF_SPEC = "httpRetryBackOffSpec";
/**
* The constant Content.
diff --git
a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/DivideRuleHandle.java
b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/DivideRuleHandle.java
index 20b1864bd9..84be0832c1 100644
---
a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/DivideRuleHandle.java
+++
b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/DivideRuleHandle.java
@@ -19,6 +19,7 @@ package org.apache.shenyu.common.dto.convert.rule.impl;
import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.dto.convert.rule.RuleHandle;
+import org.apache.shenyu.common.enums.HttpRetryBackoffSpecEnum;
import org.apache.shenyu.common.enums.LoadBalanceEnum;
import org.apache.shenyu.common.enums.RetryEnum;
@@ -41,6 +42,8 @@ public class DivideRuleHandle implements RuleHandle {
*/
private String retryStrategy = RetryEnum.CURRENT.getName();
+ private String retryBackOffSpec = HttpRetryBackoffSpecEnum.getDefault();
+
/**
* http retry.
*/
@@ -178,6 +181,14 @@ public class DivideRuleHandle implements RuleHandle {
this.requestMaxSize = requestMaxSize;
}
+ public String getRetryBackOffSpec() {
+ return retryBackOffSpec;
+ }
+
+ public void setRetryBackOffSpec(final String retryBackOffSpec) {
+ this.retryBackOffSpec = retryBackOffSpec;
+ }
+
@Override
public boolean equals(final Object o) {
if (this == o) {
@@ -189,12 +200,13 @@ public class DivideRuleHandle implements RuleHandle {
DivideRuleHandle that = (DivideRuleHandle) o;
return retry == that.retry && timeout == that.timeout && headerMaxSize
== that.headerMaxSize
&& requestMaxSize == that.requestMaxSize &&
Objects.equals(loadBalance, that.loadBalance)
- && Objects.equals(retryStrategy, that.retryStrategy);
+ && Objects.equals(retryStrategy, that.retryStrategy)
+ && Objects.equals(retryBackOffSpec, that.retryBackOffSpec);
}
@Override
public int hashCode() {
- return Objects.hash(loadBalance, retryStrategy, retry, timeout,
headerMaxSize, requestMaxSize);
+ return Objects.hash(loadBalance, retryStrategy, retryBackOffSpec,
retry, timeout, headerMaxSize, requestMaxSize);
}
@Override
@@ -203,9 +215,12 @@ public class DivideRuleHandle implements RuleHandle {
+ "loadBalance='"
+ loadBalance
+ '\''
- + "retryStrategy='"
+ + ", retryStrategy='"
+ retryStrategy
+ '\''
+ + ", retryBackOffSpec='"
+ + retryBackOffSpec
+ + '\''
+ ", retry="
+ retry
+ ", timeout="
diff --git
a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/HttpRetryBackoffSpecEnum.java
b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/HttpRetryBackoffSpecEnum.java
index f3583503e9..511456d0ce 100644
---
a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/HttpRetryBackoffSpecEnum.java
+++
b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/HttpRetryBackoffSpecEnum.java
@@ -37,12 +37,7 @@ public enum HttpRetryBackoffSpecEnum {
/**
* Exponential retry.
*/
- EXPONENTIAL_BACKOFF("exponential"),
-
- /**
- * Custom retry.
- */
- CUSTOM_BACKOFF("custom");
+ EXPONENTIAL_BACKOFF("exponential");
private final String name;
diff --git
a/shenyu-common/src/test/java/org/apache/shenyu/common/dto/convert/rule/impl/DivideRuleHandleTest.java
b/shenyu-common/src/test/java/org/apache/shenyu/common/dto/convert/rule/impl/DivideRuleHandleTest.java
index 1b11ee10f0..e705b66269 100644
---
a/shenyu-common/src/test/java/org/apache/shenyu/common/dto/convert/rule/impl/DivideRuleHandleTest.java
+++
b/shenyu-common/src/test/java/org/apache/shenyu/common/dto/convert/rule/impl/DivideRuleHandleTest.java
@@ -18,6 +18,7 @@
package org.apache.shenyu.common.dto.convert.rule.impl;
import com.google.common.collect.ImmutableSet;
+import org.apache.shenyu.common.enums.HttpRetryBackoffSpecEnum;
import org.apache.shenyu.common.enums.LoadBalanceEnum;
import org.apache.shenyu.common.enums.RetryEnum;
import org.junit.jupiter.api.Test;
@@ -37,6 +38,7 @@ public class DivideRuleHandleTest {
handle.setLoadBalance(LoadBalanceEnum.HASH.getName());
handle.setRetryStrategy(RetryEnum.FAILOVER.getName());
+
handle.setRetryBackOffSpec(HttpRetryBackoffSpecEnum.FIXED_BACKOFF.getName());
handle.setRetry(1);
handle.setTimeout(1000L);
handle.setHeaderMaxSize(100L);
@@ -44,6 +46,7 @@ public class DivideRuleHandleTest {
assertThat(handle.getLoadBalance(),
is(LoadBalanceEnum.HASH.getName()));
assertThat(handle.getRetryStrategy(),
is(RetryEnum.FAILOVER.getName()));
+ assertThat(handle.getRetryBackOffSpec(),
is(HttpRetryBackoffSpecEnum.FIXED_BACKOFF.getName()));
assertThat(handle.getRetry(), is(1));
assertThat(handle.getTimeout(), is(1000L));
assertThat(handle.getHeaderMaxSize(), is(100L));
diff --git
a/shenyu-common/src/test/java/org/apache/shenyu/common/enums/HttpRetryBackoffSpecEnumTest.java
b/shenyu-common/src/test/java/org/apache/shenyu/common/enums/HttpRetryBackoffSpecEnumTest.java
new file mode 100644
index 0000000000..454d70328f
--- /dev/null
+++
b/shenyu-common/src/test/java/org/apache/shenyu/common/enums/HttpRetryBackoffSpecEnumTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.common.enums;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class HttpRetryBackoffSpecEnumTest {
+
+ @Test
+ public void testAcquireByName() {
+ assertEquals(HttpRetryBackoffSpecEnum.DEFAULT_BACKOFF,
HttpRetryBackoffSpecEnum.acquireByName(HttpRetryBackoffSpecEnum.DEFAULT_BACKOFF.getName()));
+ assertEquals(HttpRetryBackoffSpecEnum.FIXED_BACKOFF,
HttpRetryBackoffSpecEnum.acquireByName(HttpRetryBackoffSpecEnum.FIXED_BACKOFF.getName()));
+ assertEquals(HttpRetryBackoffSpecEnum.EXPONENTIAL_BACKOFF,
HttpRetryBackoffSpecEnum.acquireByName(HttpRetryBackoffSpecEnum.EXPONENTIAL_BACKOFF.getName()));
+ }
+
+ @Test
+ public void testAcquireByNameNull() {
+ assertEquals(HttpRetryBackoffSpecEnum.DEFAULT_BACKOFF,
HttpRetryBackoffSpecEnum.acquireByName(null));
+ }
+
+ @Test
+ public void testAcquireByNameEmpty() {
+ assertEquals(HttpRetryBackoffSpecEnum.DEFAULT_BACKOFF,
HttpRetryBackoffSpecEnum.acquireByName(""));
+ }
+
+ @Test
+ public void testAcquireByNameUnknown() {
+ assertEquals(HttpRetryBackoffSpecEnum.DEFAULT_BACKOFF,
HttpRetryBackoffSpecEnum.acquireByName("notExist"));
+ }
+
+ @Test
+ public void testGetDefault() {
+ assertEquals("default", HttpRetryBackoffSpecEnum.getDefault());
+ }
+}
diff --git
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/AbstractHttpClientPlugin.java
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/AbstractHttpClientPlugin.java
index dd624417c9..ed67c79ceb 100644
---
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/AbstractHttpClientPlugin.java
+++
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/AbstractHttpClientPlugin.java
@@ -81,18 +81,15 @@ public abstract class AbstractHttpClientPlugin<R>
implements ShenyuPlugin {
.timeout(duration, Mono.error(() -> new
TimeoutException("Response took longer than timeout: " + duration)))
.doOnError(e -> LOG.error(e.getMessage(), e));
RetryStrategy<R> strategy;
- //Is it better to go with the configuration file here?
String retryStrategyType = (String)
Optional.ofNullable(exchange.getAttribute(Constants.HTTP_RETRY_BACK_OFF_SPEC)).orElse(HttpRetryBackoffSpecEnum.getDefault());
- switch (retryStrategyType) {
- case "exponential":
+ HttpRetryBackoffSpecEnum spec =
HttpRetryBackoffSpecEnum.acquireByName(retryStrategyType);
+ switch (spec) {
+ case EXPONENTIAL_BACKOFF:
strategy = new ExponentialRetryBackoffStrategy<>(this);
break;
- case "fixed":
+ case FIXED_BACKOFF:
strategy = new FixedRetryStrategy<>(this);
break;
- case "custom":
- strategy = new CustomRetryStrategy<>(this);
- break;
default:
strategy = new DefaultRetryStrategy<>(this);
}
diff --git
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/CustomRetryStrategy.java
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/CustomRetryStrategy.java
deleted file mode 100644
index cd98b498d5..0000000000
---
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/CustomRetryStrategy.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shenyu.plugin.httpclient;
-
-import java.time.Duration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.server.ServerWebExchange;
-import reactor.core.publisher.Mono;
-
-/**
- * Custom retry policy.
- * Also please achieve your own
- */
-public class CustomRetryStrategy<R> implements RetryStrategy<R> {
- private static final Logger LOG =
LoggerFactory.getLogger(CustomRetryStrategy.class);
-
- private final AbstractHttpClientPlugin<R> httpClientPlugin;
-
- public CustomRetryStrategy(final AbstractHttpClientPlugin<R>
httpClientPlugin) {
- this.httpClientPlugin = httpClientPlugin;
- }
-
- /**
- * Custom retry policy.
- *
- * @param response he Mono object of the response
- * @param exchange Current Server Exchange Object
- * @param duration Timeout
- * @param retryTimes Number of retries
- * @return Response Mono object after retry processing
- */
- public Mono<R> execute(final Mono<R> response, final ServerWebExchange
exchange, final Duration duration, final int retryTimes) {
- return null;
- }
-}
diff --git
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide/src/main/java/org/apache/shenyu/plugin/divide/DividePlugin.java
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide/src/main/java/org/apache/shenyu/plugin/divide/DividePlugin.java
index 3826a7ccd7..cffa736a3a 100644
---
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide/src/main/java/org/apache/shenyu/plugin/divide/DividePlugin.java
+++
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide/src/main/java/org/apache/shenyu/plugin/divide/DividePlugin.java
@@ -23,6 +23,7 @@ import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.dto.RuleData;
import org.apache.shenyu.common.dto.SelectorData;
import org.apache.shenyu.common.dto.convert.rule.impl.DivideRuleHandle;
+import org.apache.shenyu.common.enums.HttpRetryBackoffSpecEnum;
import org.apache.shenyu.common.enums.LoadBalanceEnum;
import org.apache.shenyu.common.enums.PluginEnum;
import org.apache.shenyu.common.enums.RetryEnum;
@@ -125,6 +126,7 @@ public class DividePlugin extends AbstractShenyuPlugin {
exchange.getAttributes().put(Constants.HTTP_TIME_OUT,
ruleHandle.getTimeout());
exchange.getAttributes().put(Constants.HTTP_RETRY,
ruleHandle.getRetry());
// set retry strategy stuff
+ exchange.getAttributes().put(Constants.HTTP_RETRY_BACK_OFF_SPEC,
StringUtils.defaultIfEmpty(ruleHandle.getRetryBackOffSpec(),
HttpRetryBackoffSpecEnum.getDefault()));
exchange.getAttributes().put(Constants.RETRY_STRATEGY,
StringUtils.defaultIfEmpty(ruleHandle.getRetryStrategy(),
RetryEnum.CURRENT.getName()));
exchange.getAttributes().put(Constants.LOAD_BALANCE,
StringUtils.defaultIfEmpty(ruleHandle.getLoadBalance(),
LoadBalanceEnum.RANDOM.getName()));
exchange.getAttributes().put(Constants.DIVIDE_SELECTOR_ID,
selector.getId());
diff --git
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide/src/test/java/org/apache/shenyu/plugin/divide/DividePluginTest.java
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide/src/test/java/org/apache/shenyu/plugin/divide/DividePluginTest.java
index 04b44d7fc8..d1b73b0808 100644
---
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide/src/test/java/org/apache/shenyu/plugin/divide/DividePluginTest.java
+++
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide/src/test/java/org/apache/shenyu/plugin/divide/DividePluginTest.java
@@ -24,6 +24,7 @@ import org.apache.shenyu.common.dto.RuleData;
import org.apache.shenyu.common.dto.SelectorData;
import org.apache.shenyu.common.dto.convert.rule.impl.DivideRuleHandle;
import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.enums.HttpRetryBackoffSpecEnum;
import org.apache.shenyu.common.enums.RpcTypeEnum;
import org.apache.shenyu.common.utils.GsonUtils;
import org.apache.shenyu.common.utils.UpstreamCheckUtils;
@@ -89,6 +90,8 @@ public final class DividePluginTest {
private DiscoverySyncData discoverySyncData;
+ private DivideUpstreamDataHandler divideUpstreamDataHandler;
+
private ServerWebExchange exchange;
private ServerWebExchange postExchange;
@@ -178,6 +181,33 @@ public final class DividePluginTest {
StepVerifier.create(result).expectSubscription().verifyComplete();
}
+ @Test
+ public void testRetryBackOffSpecAttributeSet() {
+ DivideRuleHandle handle = new DivideRuleHandle();
+
handle.setRetryBackOffSpec(HttpRetryBackoffSpecEnum.FIXED_BACKOFF.getName());
+
when(ruleData.getHandle()).thenReturn(GsonUtils.getGson().toJson(handle));
+ DividePluginDataHandler dividePluginDataHandler = new
DividePluginDataHandler();
+ dividePluginDataHandler.handlerRule(ruleData);
+ dividePluginDataHandler.handlerSelector(selectorData);
+
divideUpstreamDataHandler.handlerDiscoveryUpstreamData(discoverySyncData);
+ when(chain.execute(exchange)).thenReturn(Mono.empty());
+ dividePlugin.doExecute(exchange, chain, selectorData, ruleData);
+ assertEquals(HttpRetryBackoffSpecEnum.FIXED_BACKOFF.getName(),
exchange.getAttribute(Constants.HTTP_RETRY_BACK_OFF_SPEC));
+ }
+
+ @Test
+ public void testRetryBackOffSpecDefaultAttribute() {
+ DivideRuleHandle handle = new DivideRuleHandle();
+
when(ruleData.getHandle()).thenReturn(GsonUtils.getGson().toJson(handle));
+ DividePluginDataHandler dividePluginDataHandler = new
DividePluginDataHandler();
+ dividePluginDataHandler.handlerRule(ruleData);
+ dividePluginDataHandler.handlerSelector(selectorData);
+
divideUpstreamDataHandler.handlerDiscoveryUpstreamData(discoverySyncData);
+ when(chain.execute(exchange)).thenReturn(Mono.empty());
+ dividePlugin.doExecute(exchange, chain, selectorData, ruleData);
+ assertEquals(HttpRetryBackoffSpecEnum.getDefault(),
exchange.getAttribute(Constants.HTTP_RETRY_BACK_OFF_SPEC));
+ }
+
/**
* Skip.
*/
@@ -255,7 +285,7 @@ public final class DividePluginTest {
when(discoverySyncData.getUpstreamDataList()).thenReturn(divideUpstreamList);
when(discoverySyncData.getSelectorId()).thenReturn("mock");
DividePluginDataHandler dividePluginDataHandler = new
DividePluginDataHandler();
- DivideUpstreamDataHandler divideUpstreamDataHandler = new
DivideUpstreamDataHandler();
+ divideUpstreamDataHandler = new DivideUpstreamDataHandler();
dividePluginDataHandler.handlerRule(ruleData);
dividePluginDataHandler.handlerSelector(selectorData);
divideUpstreamDataHandler.handlerDiscoveryUpstreamData(discoverySyncData);