13
13
14
14
use Psr \Log \LoggerInterface ;
15
15
use Psr \Log \NullLogger ;
16
+ use Symfony \Component \HttpClient \Chunk \ErrorChunk ;
16
17
use Symfony \Component \HttpClient \Response \AsyncContext ;
17
18
use Symfony \Component \HttpClient \Response \AsyncResponse ;
19
+ use Symfony \Component \HttpClient \Response \MockResponse ;
18
20
use Symfony \Component \HttpClient \Retry \ExponentialBackOff ;
19
21
use Symfony \Component \HttpClient \Retry \HttpCodeDecider ;
20
22
use Symfony \Component \HttpClient \Retry \RetryBackOffInterface ;
@@ -57,16 +59,14 @@ public function request(string $method, string $url, array $options = []): Respo
57
59
return new AsyncResponse ($ this ->client , $ method , $ url , $ options , function (ChunkInterface $ chunk , AsyncContext $ context ) use ($ method , $ url , $ options , &$ retryCount ) {
58
60
$ exception = null ;
59
61
try {
60
- // clone the chunk to let the original value of `$didthrow`
61
- $ clonedChunk = clone $ chunk ;
62
- if ($ clonedChunk ->isTimeout () || null !== $ clonedChunk ->getInformationalStatus ()) {
62
+ if ($ chunk ->isTimeout () || null !== $ chunk ->getInformationalStatus ()) {
63
63
yield $ chunk ;
64
64
65
65
return ;
66
66
}
67
67
68
68
// only retry first chunk
69
- if (!$ clonedChunk ->isFirst ()) {
69
+ if (!$ chunk ->isFirst ()) {
70
70
$ context ->passthru ();
71
71
yield $ chunk ;
72
72
@@ -76,32 +76,37 @@ public function request(string $method, string $url, array $options = []): Respo
76
76
// catch TransportExceptionInterface to send it to strategy.
77
77
}
78
78
79
- if ($ retryCount >= $ this ->maxRetries || !$ this ->decider ->shouldRetry ($ method , $ url , $ options , $ response = $ context ->getResponse ( ), $ exception )) {
79
+ if ($ retryCount >= $ this ->maxRetries || !$ this ->decider ->shouldRetry ($ method , $ url , $ options , $ partialResponse = new MockResponse ( $ context ->getContent (), [ ' http_code ' => $ statusCode = $ context -> getStatusCode (), ' headers ' => $ headers = $ context -> getHeaders ()] ), $ exception )) {
80
80
$ context ->passthru ();
81
81
yield $ chunk ;
82
82
83
83
return ;
84
84
}
85
85
86
86
$ context ->setInfo ('retry_count ' , $ retryCount );
87
- $ response ->cancel ();
87
+ $ context -> getResponse () ->cancel ();
88
88
89
- $ delay = $ this ->getDelayFromHeader ($ response ) ?? $ this ->strategy ->getDelay ($ retryCount , $ method , $ url , $ options , $ response = $ context -> getResponse () , $ exception );
89
+ $ delay = $ this ->getDelayFromHeader ($ headers ) ?? $ this ->strategy ->getDelay ($ retryCount , $ method , $ url , $ options , $ partialResponse , $ exception );
90
90
++$ retryCount ;
91
91
92
- $ this ->logger ->info ('Error returned by the server. Retrying #{retryCount} using {delay} ms delay: ' .($ exception ? $ exception ->getMessage () : 'StatusCode: ' .$ response -> getStatusCode () ), [
92
+ $ this ->logger ->info ('Error returned by the server. Retrying #{retryCount} using {delay} ms delay: ' .($ exception ? $ exception ->getMessage () : 'StatusCode: ' .$ statusCode ), [
93
93
'retryCount ' => $ retryCount ,
94
94
'delay ' => $ delay ,
95
95
]);
96
96
97
+ try {
98
+ $ chunk ->getContent ();
99
+ } catch (TransportExceptionInterface $ exception ) {
100
+ // silent the failsafe exception
101
+ }
97
102
$ context ->replaceRequest ($ method , $ url , $ options );
98
103
$ context ->pause ($ delay / 1000 );
99
104
});
100
105
}
101
106
102
- private function getDelayFromHeader (ResponseInterface $ response ): ?int
107
+ private function getDelayFromHeader (array $ headers ): ?int
103
108
{
104
- if (null !== $ after = $ response -> getHeaders ( false ) ['retry-after ' ][0 ] ?? null ) {
109
+ if (null !== $ after = $ headers ['retry-after ' ][0 ] ?? null ) {
105
110
if (is_numeric ($ after )) {
106
111
return (int ) $ after * 1000 ;
107
112
}
0 commit comments