@@ -27,9 +27,17 @@ export const runPolling = async <Client, Input>(
2727 input : Input ,
2828 acceptorChecks : ( client : Client , input : Input ) => Promise < WaiterResult >
2929) : Promise < WaiterResult > => {
30+ const observedResponses : Record < string , number > = { } ;
31+
3032 const { state, reason } = await acceptorChecks ( client , input ) ;
33+ if ( reason ) {
34+ const message = createMessageFromResponse ( reason ) ;
35+ observedResponses [ message ] |= 0 ;
36+ observedResponses [ message ] += 1 ;
37+ }
38+
3139 if ( state !== WaiterState . RETRY ) {
32- return { state, reason } ;
40+ return { state, reason, observedResponses } ;
3341 }
3442
3543 let currentAttempt = 1 ;
@@ -39,20 +47,53 @@ export const runPolling = async <Client, Input>(
3947 const attemptCeiling = Math . log ( maxDelay / minDelay ) / Math . log ( 2 ) + 1 ;
4048 while ( true ) {
4149 if ( abortController ?. signal ?. aborted || abortSignal ?. aborted ) {
42- return { state : WaiterState . ABORTED } ;
50+ const message = "AbortController signal aborted." ;
51+ observedResponses [ message ] |= 0 ;
52+ observedResponses [ message ] += 1 ;
53+ return { state : WaiterState . ABORTED , observedResponses } ;
4354 }
4455 const delay = exponentialBackoffWithJitter ( minDelay , maxDelay , attemptCeiling , currentAttempt ) ;
4556 // Resolve the promise explicitly at timeout or aborted. Otherwise this while loop will keep making API call until
4657 // `acceptorCheck` returns non-retry status, even with the Promise.race() outside.
4758 if ( Date . now ( ) + delay * 1000 > waitUntil ) {
48- return { state : WaiterState . TIMEOUT } ;
59+ return { state : WaiterState . TIMEOUT , observedResponses } ;
4960 }
5061 await sleep ( delay ) ;
5162 const { state, reason } = await acceptorChecks ( client , input ) ;
63+
64+ if ( reason ) {
65+ const message = createMessageFromResponse ( reason ) ;
66+ observedResponses [ message ] |= 0 ;
67+ observedResponses [ message ] += 1 ;
68+ }
69+
5270 if ( state !== WaiterState . RETRY ) {
53- return { state, reason } ;
71+ return { state, reason, observedResponses } ;
5472 }
5573
5674 currentAttempt += 1 ;
5775 }
5876} ;
77+
78+ /**
79+ * @internal
80+ * convert the result of an SDK operation, either an error or response object, to a
81+ * readable string.
82+ */
83+ const createMessageFromResponse = ( reason : any ) : string => {
84+ if ( reason ?. $responseBodyText ) {
85+ // is a deserialization error.
86+ return `Deserialization error for body: ${ reason . $responseBodyText } ` ;
87+ }
88+ if ( reason ?. $metadata ?. httpStatusCode ) {
89+ // has a status code.
90+ if ( reason . $response || reason . message ) {
91+ // is an error object.
92+ return `${ reason . $response . statusCode ?? reason . $metadata . httpStatusCode ?? "Unknown" } : ${ reason . message } ` ;
93+ }
94+ // is an output object.
95+ return `${ reason . $metadata . httpStatusCode } : OK` ;
96+ }
97+ // is an unknown object.
98+ return String ( reason ?. message ?? JSON . stringify ( reason ) ?? "Unknown" ) ;
99+ } ;
0 commit comments