You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In an environment where DNS resolution works but network packets may be
dropped, the CLI can hang for up to 15 minutes trying to refresh
notices. We tried to set a timeout of 3 seconds on this, but did it in a
way that didn't work.
Turns out that the `request.on('timeout')` event in NodeJS doesn't actually stop
the request: it just notifies the listener that it's been a long time
since we saw network bytes, leaving the listener to do with that
what they want (potentially show a dialog box to a waiting user or
whatever). In our case, we had to do an additional `request.destroy()`
to actually stop the request.
Without doing this, the Promise would resolve correctly and the CLI
would continue, but the actual HTTP request would still be going on
in the background, preventing Node from shutting down.
This PR also changes the behavior of reporting a download failure: it
used to be that we would successfully resolve to a `[]` response if
the HTTP request failed (which would then be cached). Instead, after
this change we reject the Promise if anything goes wrong, so that the
next invocation will try again.
Fixes#19542.
----
*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@@ -123,29 +121,39 @@ export class WebsiteNoticeDataSource implements NoticeDataSource {
123
121
res.on('end',()=>{
124
122
try{
125
123
constdata=JSON.parse(rawData).noticesasNotice[];
124
+
if(!data){
125
+
thrownewError("'notices' key is missing");
126
+
}
127
+
debug('Notices refreshed');
126
128
resolve(data??[]);
127
129
}catch(e){
128
-
debug(`Failed to parse notices: ${e}`);
129
-
resolve([]);
130
+
reject(newError(`Failed to parse notices: ${e.message}`));
130
131
}
131
132
});
132
133
res.on('error',e=>{
133
-
debug(`Failed to fetch notices: ${e}`);
134
-
resolve([]);
134
+
reject(newError(`Failed to fetch notices: ${e.message}`));
135
135
});
136
136
}else{
137
-
debug(`Failed to fetch notices. Status code: ${res.statusCode}`);
138
-
resolve([]);
137
+
reject(newError(`Failed to fetch notices. Status code: ${res.statusCode}`));
139
138
}
140
139
});
141
-
req.on('error',e=>{
142
-
debug(`Error on request: ${e}`);
143
-
resolve([]);
140
+
req.on('error',reject);
141
+
req.on('timeout',()=>{
142
+
// The 'timeout' event doesn't stop anything by itself, it just
143
+
// notifies that it has been long time since we saw bytes.
144
+
// In our case, we want to give up.
145
+
req.destroy(newError('Request timed out'));
144
146
});
145
-
req.on('timeout',_=>resolve([]));
147
+
148
+
// It's not like I don't *trust* the 'timeout' event... but I don't trust it.
149
+
// Add a backup timer that will destroy the request after all.
150
+
// (This is at least necessary to make the tests pass, but that's probably because of 'nock'.
151
+
// It's not clear whether users will hit this).
152
+
setTimeout(()=>{
153
+
req.destroy(newError('Request timed out. You should never see this message; if you do, please let us know at https://github.com/aws/aws-cdk/issues'));
154
+
},timeout+200);
146
155
}catch(e){
147
-
debug(`HTTPS 'get' call threw an error: ${e}`);
148
-
resolve([]);
156
+
reject(newError(`HTTPS 'get' call threw an error: ${e.message}`));
0 commit comments