@module-federation/retry-plugin 0.18.2 → 0.18.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @module-federation/retry-plugin
2
2
 
3
+ ## 0.18.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 143034b: feat(retry-plugin): Add getRetryPath support in retry plugin to allow users to customize retry path
8
+ - Updated dependencies [8061f8c]
9
+ - @module-federation/sdk@0.18.4
10
+
11
+ ## 0.18.3
12
+
13
+ ### Patch Changes
14
+
15
+ - @module-federation/sdk@0.18.3
16
+
3
17
  ## 0.18.2
4
18
 
5
19
  ### Patch Changes
package/dist/esm/index.js CHANGED
@@ -12,23 +12,32 @@ var logger = createLogger(PLUGIN_IDENTIFIER);
12
12
  var logger_default = logger;
13
13
 
14
14
  // packages/retry-plugin/src/fetch-retry.ts
15
- async function fetchWithRetry({ url, options = {}, retryTimes = defaultRetries, retryDelay = defaultRetryDelay, fallback }) {
15
+ async function fetchWithRetry(params, userOriginalRetryTimes) {
16
+ const { manifestUrl, options = {}, retryTimes = defaultRetries, retryDelay = defaultRetryDelay, fallback, getRetryPath } = params;
17
+ const url = manifestUrl || params.url;
18
+ if (!url) {
19
+ throw new Error("[retry-plugin] manifestUrl or url is required");
20
+ }
21
+ const originalRetryTimes = userOriginalRetryTimes ?? params.retryTimes ?? defaultRetries;
22
+ const isRetry = retryTimes !== originalRetryTimes;
23
+ const retryUrl = isRetry && getRetryPath ? getRetryPath(url) : null;
24
+ const requestUrl = retryUrl || url;
16
25
  try {
17
- const response = await fetch(url, options);
26
+ const response = await fetch(requestUrl, options);
18
27
  const responseClone = response.clone();
19
28
  if (!response.ok) {
20
29
  throw new Error(`Server error\uFF1A${response.status}`);
21
30
  }
22
31
  await responseClone.json().catch((error) => {
23
- throw new Error(`Json parse error: ${error}, url is: ${url}`);
32
+ throw new Error(`Json parse error: ${error}, url is: ${requestUrl}`);
24
33
  });
25
34
  return response;
26
35
  } catch (error) {
27
36
  if (retryTimes <= 0) {
28
- logger_default.log(`${PLUGIN_IDENTIFIER}: retry failed after ${retryTimes} times for url: ${url}, now will try fallbackUrl url`);
29
- if (fallback && typeof fallback === "function") {
37
+ logger_default.log(`${PLUGIN_IDENTIFIER}: retry failed after ${defaultRetries} times for url: ${requestUrl}, now will try fallbackUrl url`);
38
+ if (requestUrl && fallback && typeof fallback === "function") {
30
39
  return fetchWithRetry({
31
- url: fallback(url),
40
+ manifestUrl: fallback(requestUrl),
32
41
  options,
33
42
  retryTimes: 0,
34
43
  retryDelay: 0
@@ -42,102 +51,107 @@ async function fetchWithRetry({ url, options = {}, retryTimes = defaultRetries,
42
51
  retryDelay > 0 && await new Promise((resolve) => setTimeout(resolve, retryDelay));
43
52
  logger_default.log(`Trying again. Number of retries available\uFF1A${retryTimes - 1}`);
44
53
  return await fetchWithRetry({
45
- url,
46
- options,
47
- retryTimes: retryTimes - 1,
48
- retryDelay,
49
- fallback
50
- });
54
+ ...params,
55
+ retryTimes: retryTimes - 1
56
+ }, originalRetryTimes);
51
57
  }
52
58
  }
53
59
  }
54
60
  __name(fetchWithRetry, "fetchWithRetry");
55
61
 
56
- // packages/retry-plugin/src/util.ts
57
- function scriptCommonRetry({ scriptOption, moduleInfo, retryFn, beforeExecuteRetry = /* @__PURE__ */ __name(() => {
62
+ // packages/retry-plugin/src/script-retry.ts
63
+ function scriptRetry({ scriptOption, moduleInfo, retryFn, beforeExecuteRetry = /* @__PURE__ */ __name(() => {
58
64
  }, "beforeExecuteRetry") }) {
59
- return async function(...args) {
60
- let retryResponse;
65
+ return async function(params) {
66
+ let retryWrapper;
61
67
  const { retryTimes = defaultRetries, retryDelay = defaultRetryDelay } = scriptOption || {};
62
- if (scriptOption?.moduleName && scriptOption?.moduleName.some((m) => moduleInfo.name === m || moduleInfo?.alias === m) || scriptOption?.moduleName === void 0) {
68
+ const shouldRetryThisModule = shouldRetryModule(scriptOption, moduleInfo);
69
+ if (shouldRetryThisModule) {
63
70
  let attempts = 0;
64
- while (attempts - 1 < retryTimes) {
71
+ while (attempts < retryTimes) {
65
72
  try {
66
73
  beforeExecuteRetry();
67
- retryResponse = await retryFn(...args);
74
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
75
+ retryWrapper = await retryFn({
76
+ ...params,
77
+ // add getRetryPath to load entry url passed by user
78
+ getEntryUrl: scriptOption?.getRetryPath
79
+ });
68
80
  break;
69
81
  } catch (error) {
70
82
  attempts++;
71
- if (attempts - 1 >= retryTimes) {
83
+ if (attempts < retryTimes) {
84
+ logger_default.log(`${PLUGIN_IDENTIFIER}: script resource retrying ${attempts} times`);
85
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
86
+ } else {
72
87
  scriptOption?.cb && await new Promise((resolve) => scriptOption?.cb && scriptOption?.cb(resolve, error));
73
88
  throw error;
74
89
  }
75
- logger_default.log(`${PLUGIN_IDENTIFIER}: script resource retrying ${attempts} times`);
76
- await new Promise((resolve) => setTimeout(resolve, retryDelay));
77
90
  }
78
91
  }
79
92
  }
80
- return retryResponse;
93
+ return retryWrapper;
81
94
  };
82
95
  }
83
- __name(scriptCommonRetry, "scriptCommonRetry");
96
+ __name(scriptRetry, "scriptRetry");
97
+ function shouldRetryModule(scriptOption, moduleInfo) {
98
+ if (!scriptOption?.moduleName) {
99
+ return true;
100
+ }
101
+ const moduleNames = scriptOption.moduleName;
102
+ const currentModuleName = moduleInfo.name;
103
+ const currentModuleAlias = moduleInfo?.alias;
104
+ return moduleNames.some((targetName) => targetName === currentModuleName || targetName === currentModuleAlias);
105
+ }
106
+ __name(shouldRetryModule, "shouldRetryModule");
84
107
 
85
108
  // packages/retry-plugin/src/index.ts
109
+ var loadEntryErrorCache = /* @__PURE__ */ new Set();
86
110
  var RetryPlugin = /* @__PURE__ */ __name(({ fetch: fetchOption, script: scriptOption }) => ({
87
111
  name: "retry-plugin",
88
- async fetch(url, options) {
89
- const _options = {
90
- ...options,
91
- ...fetchOption?.options
92
- };
112
+ async fetch(manifestUrl, options) {
113
+ const { retryTimes, fallback, getRetryPath } = fetchOption || {};
93
114
  if (fetchOption) {
94
- if (fetchOption.url) {
95
- if (url === fetchOption?.url) {
96
- return fetchWithRetry({
97
- url: fetchOption.url,
98
- options: _options,
99
- retryTimes: fetchOption?.retryTimes,
100
- fallback: fetchOption?.fallback
101
- });
102
- }
103
- } else {
104
- return fetchWithRetry({
105
- url,
106
- options: _options,
107
- retryTimes: fetchOption?.retryTimes,
108
- fallback: fetchOption?.fallback
109
- });
110
- }
115
+ return fetchWithRetry({
116
+ manifestUrl,
117
+ options: {
118
+ ...options,
119
+ ...fetchOption?.options
120
+ },
121
+ retryTimes,
122
+ fallback,
123
+ getRetryPath
124
+ });
111
125
  }
112
- return fetch(url, options);
126
+ return fetch(manifestUrl, options);
113
127
  },
114
128
  async loadEntryError({ getRemoteEntry, origin, remoteInfo, remoteEntryExports, globalLoading, uniqueKey }) {
115
- if (!scriptOption)
129
+ if (!scriptOption || loadEntryErrorCache.has(uniqueKey)) {
130
+ logger_default.log(`${PLUGIN_IDENTIFIER}: loadEntryError already processed for uniqueKey: ${uniqueKey}, skipping retry`);
116
131
  return;
117
- const retryFn = getRemoteEntry;
118
- const beforeExecuteRetry = /* @__PURE__ */ __name(() => delete globalLoading[uniqueKey], "beforeExecuteRetry");
119
- const getRemoteEntryRetry = scriptCommonRetry({
132
+ }
133
+ loadEntryErrorCache.add(uniqueKey);
134
+ const beforeExecuteRetry = /* @__PURE__ */ __name(() => {
135
+ delete globalLoading[uniqueKey];
136
+ }, "beforeExecuteRetry");
137
+ const getRemoteEntryRetry = scriptRetry({
120
138
  scriptOption,
121
139
  moduleInfo: remoteInfo,
122
- retryFn,
140
+ retryFn: getRemoteEntry,
123
141
  beforeExecuteRetry
124
142
  });
125
- return getRemoteEntryRetry({
126
- origin,
127
- remoteInfo,
128
- remoteEntryExports
129
- });
130
- },
131
- async getModuleFactory({ remoteEntryExports, expose, moduleInfo }) {
132
- if (!scriptOption)
133
- return;
134
- const retryFn = remoteEntryExports.get;
135
- const getRemoteEntryRetry = scriptCommonRetry({
136
- scriptOption,
137
- moduleInfo,
138
- retryFn
139
- });
140
- return getRemoteEntryRetry(expose);
143
+ try {
144
+ const result = await getRemoteEntryRetry({
145
+ origin,
146
+ remoteInfo,
147
+ remoteEntryExports
148
+ });
149
+ loadEntryErrorCache.delete(uniqueKey);
150
+ return result;
151
+ } catch (error) {
152
+ loadEntryErrorCache.delete(uniqueKey);
153
+ throw error;
154
+ }
141
155
  }
142
156
  }), "RetryPlugin");
143
157
  export {
package/dist/index.d.mts CHANGED
@@ -1,20 +1,21 @@
1
1
  import { ModuleFederationRuntimePlugin } from '@module-federation/runtime/types';
2
2
 
3
3
  interface FetchWithRetryOptions {
4
- url?: string;
4
+ manifestUrl?: string;
5
5
  options?: RequestInit;
6
6
  retryTimes?: number;
7
7
  retryDelay?: number;
8
8
  fallback?:
9
9
  | (() => string)
10
10
  | ((url: string | URL | globalThis.Request) => string);
11
+ getRetryPath?: (url: string) => string;
11
12
  }
12
-
13
13
  interface ScriptWithRetryOptions {
14
14
  retryTimes?: number;
15
15
  retryDelay?: number;
16
16
  moduleName?: Array<string>;
17
17
  cb?: (resolve: (value: unknown) => void, error: any) => void;
18
+ getRetryPath?: (url: string) => string;
18
19
  }
19
20
 
20
21
  type RetryPluginParams = {
package/dist/index.d.ts CHANGED
@@ -1,20 +1,21 @@
1
1
  import { ModuleFederationRuntimePlugin } from '@module-federation/runtime/types';
2
2
 
3
3
  interface FetchWithRetryOptions {
4
- url?: string;
4
+ manifestUrl?: string;
5
5
  options?: RequestInit;
6
6
  retryTimes?: number;
7
7
  retryDelay?: number;
8
8
  fallback?:
9
9
  | (() => string)
10
10
  | ((url: string | URL | globalThis.Request) => string);
11
+ getRetryPath?: (url: string) => string;
11
12
  }
12
-
13
13
  interface ScriptWithRetryOptions {
14
14
  retryTimes?: number;
15
15
  retryDelay?: number;
16
16
  moduleName?: Array<string>;
17
17
  cb?: (resolve: (value: unknown) => void, error: any) => void;
18
+ getRetryPath?: (url: string) => string;
18
19
  }
19
20
 
20
21
  type RetryPluginParams = {
package/dist/index.js CHANGED
@@ -36,23 +36,32 @@ var logger = (0, import_sdk.createLogger)(PLUGIN_IDENTIFIER);
36
36
  var logger_default = logger;
37
37
 
38
38
  // packages/retry-plugin/src/fetch-retry.ts
39
- async function fetchWithRetry({ url, options = {}, retryTimes = defaultRetries, retryDelay = defaultRetryDelay, fallback }) {
39
+ async function fetchWithRetry(params, userOriginalRetryTimes) {
40
+ const { manifestUrl, options = {}, retryTimes = defaultRetries, retryDelay = defaultRetryDelay, fallback, getRetryPath } = params;
41
+ const url = manifestUrl || params.url;
42
+ if (!url) {
43
+ throw new Error("[retry-plugin] manifestUrl or url is required");
44
+ }
45
+ const originalRetryTimes = userOriginalRetryTimes ?? params.retryTimes ?? defaultRetries;
46
+ const isRetry = retryTimes !== originalRetryTimes;
47
+ const retryUrl = isRetry && getRetryPath ? getRetryPath(url) : null;
48
+ const requestUrl = retryUrl || url;
40
49
  try {
41
- const response = await fetch(url, options);
50
+ const response = await fetch(requestUrl, options);
42
51
  const responseClone = response.clone();
43
52
  if (!response.ok) {
44
53
  throw new Error(`Server error\uFF1A${response.status}`);
45
54
  }
46
55
  await responseClone.json().catch((error) => {
47
- throw new Error(`Json parse error: ${error}, url is: ${url}`);
56
+ throw new Error(`Json parse error: ${error}, url is: ${requestUrl}`);
48
57
  });
49
58
  return response;
50
59
  } catch (error) {
51
60
  if (retryTimes <= 0) {
52
- logger_default.log(`${PLUGIN_IDENTIFIER}: retry failed after ${retryTimes} times for url: ${url}, now will try fallbackUrl url`);
53
- if (fallback && typeof fallback === "function") {
61
+ logger_default.log(`${PLUGIN_IDENTIFIER}: retry failed after ${defaultRetries} times for url: ${requestUrl}, now will try fallbackUrl url`);
62
+ if (requestUrl && fallback && typeof fallback === "function") {
54
63
  return fetchWithRetry({
55
- url: fallback(url),
64
+ manifestUrl: fallback(requestUrl),
56
65
  options,
57
66
  retryTimes: 0,
58
67
  retryDelay: 0
@@ -66,102 +75,107 @@ async function fetchWithRetry({ url, options = {}, retryTimes = defaultRetries,
66
75
  retryDelay > 0 && await new Promise((resolve) => setTimeout(resolve, retryDelay));
67
76
  logger_default.log(`Trying again. Number of retries available\uFF1A${retryTimes - 1}`);
68
77
  return await fetchWithRetry({
69
- url,
70
- options,
71
- retryTimes: retryTimes - 1,
72
- retryDelay,
73
- fallback
74
- });
78
+ ...params,
79
+ retryTimes: retryTimes - 1
80
+ }, originalRetryTimes);
75
81
  }
76
82
  }
77
83
  }
78
84
  __name(fetchWithRetry, "fetchWithRetry");
79
85
 
80
- // packages/retry-plugin/src/util.ts
81
- function scriptCommonRetry({ scriptOption, moduleInfo, retryFn, beforeExecuteRetry = /* @__PURE__ */ __name(() => {
86
+ // packages/retry-plugin/src/script-retry.ts
87
+ function scriptRetry({ scriptOption, moduleInfo, retryFn, beforeExecuteRetry = /* @__PURE__ */ __name(() => {
82
88
  }, "beforeExecuteRetry") }) {
83
- return async function(...args) {
84
- let retryResponse;
89
+ return async function(params) {
90
+ let retryWrapper;
85
91
  const { retryTimes = defaultRetries, retryDelay = defaultRetryDelay } = scriptOption || {};
86
- if (scriptOption?.moduleName && scriptOption?.moduleName.some((m) => moduleInfo.name === m || moduleInfo?.alias === m) || scriptOption?.moduleName === void 0) {
92
+ const shouldRetryThisModule = shouldRetryModule(scriptOption, moduleInfo);
93
+ if (shouldRetryThisModule) {
87
94
  let attempts = 0;
88
- while (attempts - 1 < retryTimes) {
95
+ while (attempts < retryTimes) {
89
96
  try {
90
97
  beforeExecuteRetry();
91
- retryResponse = await retryFn(...args);
98
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
99
+ retryWrapper = await retryFn({
100
+ ...params,
101
+ // add getRetryPath to load entry url passed by user
102
+ getEntryUrl: scriptOption?.getRetryPath
103
+ });
92
104
  break;
93
105
  } catch (error) {
94
106
  attempts++;
95
- if (attempts - 1 >= retryTimes) {
107
+ if (attempts < retryTimes) {
108
+ logger_default.log(`${PLUGIN_IDENTIFIER}: script resource retrying ${attempts} times`);
109
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
110
+ } else {
96
111
  scriptOption?.cb && await new Promise((resolve) => scriptOption?.cb && scriptOption?.cb(resolve, error));
97
112
  throw error;
98
113
  }
99
- logger_default.log(`${PLUGIN_IDENTIFIER}: script resource retrying ${attempts} times`);
100
- await new Promise((resolve) => setTimeout(resolve, retryDelay));
101
114
  }
102
115
  }
103
116
  }
104
- return retryResponse;
117
+ return retryWrapper;
105
118
  };
106
119
  }
107
- __name(scriptCommonRetry, "scriptCommonRetry");
120
+ __name(scriptRetry, "scriptRetry");
121
+ function shouldRetryModule(scriptOption, moduleInfo) {
122
+ if (!scriptOption?.moduleName) {
123
+ return true;
124
+ }
125
+ const moduleNames = scriptOption.moduleName;
126
+ const currentModuleName = moduleInfo.name;
127
+ const currentModuleAlias = moduleInfo?.alias;
128
+ return moduleNames.some((targetName) => targetName === currentModuleName || targetName === currentModuleAlias);
129
+ }
130
+ __name(shouldRetryModule, "shouldRetryModule");
108
131
 
109
132
  // packages/retry-plugin/src/index.ts
133
+ var loadEntryErrorCache = /* @__PURE__ */ new Set();
110
134
  var RetryPlugin = /* @__PURE__ */ __name(({ fetch: fetchOption, script: scriptOption }) => ({
111
135
  name: "retry-plugin",
112
- async fetch(url, options) {
113
- const _options = {
114
- ...options,
115
- ...fetchOption?.options
116
- };
136
+ async fetch(manifestUrl, options) {
137
+ const { retryTimes, fallback, getRetryPath } = fetchOption || {};
117
138
  if (fetchOption) {
118
- if (fetchOption.url) {
119
- if (url === fetchOption?.url) {
120
- return fetchWithRetry({
121
- url: fetchOption.url,
122
- options: _options,
123
- retryTimes: fetchOption?.retryTimes,
124
- fallback: fetchOption?.fallback
125
- });
126
- }
127
- } else {
128
- return fetchWithRetry({
129
- url,
130
- options: _options,
131
- retryTimes: fetchOption?.retryTimes,
132
- fallback: fetchOption?.fallback
133
- });
134
- }
139
+ return fetchWithRetry({
140
+ manifestUrl,
141
+ options: {
142
+ ...options,
143
+ ...fetchOption?.options
144
+ },
145
+ retryTimes,
146
+ fallback,
147
+ getRetryPath
148
+ });
135
149
  }
136
- return fetch(url, options);
150
+ return fetch(manifestUrl, options);
137
151
  },
138
152
  async loadEntryError({ getRemoteEntry, origin, remoteInfo, remoteEntryExports, globalLoading, uniqueKey }) {
139
- if (!scriptOption)
153
+ if (!scriptOption || loadEntryErrorCache.has(uniqueKey)) {
154
+ logger_default.log(`${PLUGIN_IDENTIFIER}: loadEntryError already processed for uniqueKey: ${uniqueKey}, skipping retry`);
140
155
  return;
141
- const retryFn = getRemoteEntry;
142
- const beforeExecuteRetry = /* @__PURE__ */ __name(() => delete globalLoading[uniqueKey], "beforeExecuteRetry");
143
- const getRemoteEntryRetry = scriptCommonRetry({
156
+ }
157
+ loadEntryErrorCache.add(uniqueKey);
158
+ const beforeExecuteRetry = /* @__PURE__ */ __name(() => {
159
+ delete globalLoading[uniqueKey];
160
+ }, "beforeExecuteRetry");
161
+ const getRemoteEntryRetry = scriptRetry({
144
162
  scriptOption,
145
163
  moduleInfo: remoteInfo,
146
- retryFn,
164
+ retryFn: getRemoteEntry,
147
165
  beforeExecuteRetry
148
166
  });
149
- return getRemoteEntryRetry({
150
- origin,
151
- remoteInfo,
152
- remoteEntryExports
153
- });
154
- },
155
- async getModuleFactory({ remoteEntryExports, expose, moduleInfo }) {
156
- if (!scriptOption)
157
- return;
158
- const retryFn = remoteEntryExports.get;
159
- const getRemoteEntryRetry = scriptCommonRetry({
160
- scriptOption,
161
- moduleInfo,
162
- retryFn
163
- });
164
- return getRemoteEntryRetry(expose);
167
+ try {
168
+ const result = await getRemoteEntryRetry({
169
+ origin,
170
+ remoteInfo,
171
+ remoteEntryExports
172
+ });
173
+ loadEntryErrorCache.delete(uniqueKey);
174
+ return result;
175
+ } catch (error) {
176
+ loadEntryErrorCache.delete(uniqueKey);
177
+ throw error;
178
+ }
165
179
  }
166
180
  }), "RetryPlugin");
167
181
  // Annotate the CommonJS export names for ESM import in node:
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/retry-plugin",
3
- "version": "0.18.2",
3
+ "version": "0.18.4",
4
4
  "author": "danpeen <dapeen.feng@gmail.com>",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/retry-plugin",
3
- "version": "0.18.2",
3
+ "version": "0.18.4",
4
4
  "author": "danpeen <dapeen.feng@gmail.com>",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -33,9 +33,9 @@
33
33
  }
34
34
  },
35
35
  "devDependencies": {
36
- "@module-federation/runtime": "0.18.2"
36
+ "@module-federation/runtime": "0.18.4"
37
37
  },
38
38
  "dependencies": {
39
- "@module-federation/sdk": "0.18.2"
39
+ "@module-federation/sdk": "0.18.4"
40
40
  }
41
41
  }