Skip to content

Commit 13de51f

Browse files
authored
Fix/autoupdating cdn downtime (#2467)
1 parent 0c2037d commit 13de51f

File tree

2 files changed

+44
-30
lines changed

2 files changed

+44
-30
lines changed

.github/workflows/publish.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ jobs:
136136
with:
137137
subject-path: './sdk'
138138

139+
- name: Generate last_updated.json
140+
if: (env.DRY_RUN) == 'false'
141+
run: |
142+
echo "{\"last_updated\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\"}" > ./sdk/last_updated.json
143+
cp ./sdk/last_updated.json ./sdk/dist/
144+
139145
- name: Authenticate NPM
140146
if: contains(env.RELEASE_TYPE, 'release')
141147
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.TS_IMMUTABLE_SDK_NPM_TOKEN }}

packages/checkout/sdk/src/widgets/version.ts

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -84,33 +84,6 @@ export async function getLatestVersionFromNpm(): Promise<string> {
8484
}
8585
}
8686

87-
/**
88-
* Checks if the provided version is available on the CDN.
89-
* @param {string} version - The version to check.
90-
* @returns {Promise<boolean>} A promise resolving to a boolean indicating if the version is available on the CDN.
91-
*/
92-
async function isVersionAvailableOnCDN(version: string): Promise<boolean> {
93-
const files = ['widgets-esm.js', 'widgets.js'];
94-
const baseUrl = `https://cdn.jsdelivr.net/npm/@imtbl/sdk@${version}/dist/browser/checkout/`;
95-
96-
try {
97-
const checks = files.map(async (file) => {
98-
const response = await fetch(`${baseUrl}${file}`, { method: 'HEAD' });
99-
if (!response.ok) {
100-
return false;
101-
}
102-
return true;
103-
});
104-
105-
const results = await Promise.all(checks);
106-
const allFilesAvailable = results.every((isAvailable) => isAvailable);
107-
108-
return allFilesAvailable;
109-
} catch {
110-
return false;
111-
}
112-
}
113-
11487
/**
11588
* Returns the latest compatible version based on the provided checkout version config.
11689
* If no compatible version markers are provided, it returns 'latest'.
@@ -127,6 +100,40 @@ function latestCompatibleVersion(
127100
return 'latest';
128101
}
129102

103+
/**
104+
* Checks if the last_updated.json file exists on the CDN and validates its timestamp.
105+
* @param {string} version - The version to check.
106+
* @returns {Promise<boolean>} A promise resolving to `true` if last_updated.json exists and is older than 15 minutes, `false` otherwise.
107+
*/
108+
async function checkLastUpdatedTimestamp(version: string): Promise<boolean> {
109+
const WAIT_TIME_IN_MINUTES = 20;
110+
111+
const lastUpdatedJsonUrl = `https://cdn.jsdelivr.net/npm/@imtbl/sdk@${version}/dist/last_updated.json`;
112+
113+
try {
114+
const response = await fetch(lastUpdatedJsonUrl);
115+
116+
if (!response.ok) {
117+
return false;
118+
}
119+
120+
const lastUpdatedData = await response.json();
121+
122+
if (lastUpdatedData.timestamp) {
123+
const timestamp = new Date(lastUpdatedData.timestamp);
124+
const now = new Date();
125+
const diffInMs = now.getTime() - timestamp.getTime();
126+
const diffInMinutes = diffInMs / (1000 * 60);
127+
128+
return diffInMinutes > WAIT_TIME_IN_MINUTES;
129+
}
130+
} catch (error) {
131+
return false;
132+
}
133+
134+
return false;
135+
}
136+
130137
/**
131138
* Determines the version of the widgets to use based on the provided validated build version and checkout version config.
132139
* If a version is provided in the widget init parameters, it uses that version.
@@ -158,13 +165,14 @@ export async function determineWidgetsVersion(
158165
versionConfig.compatibleVersionMarkers,
159166
);
160167

161-
// If `latest` is returned, query NPM registry for the actual latest version and check if it's available on the CDN
168+
// If `latest` is returned, query NPM registry for the actual latest version and check timestamp
162169
if (compatibleVersion === 'latest') {
163170
const latestVersion = await getLatestVersionFromNpm();
164-
const isAvailable = await isVersionAvailableOnCDN(latestVersion);
165-
if (isAvailable) {
171+
172+
if (await checkLastUpdatedTimestamp(latestVersion)) {
166173
return latestVersion;
167174
}
175+
168176
return 'latest';
169177
}
170178

0 commit comments

Comments
 (0)