मेरे पास कई कतार श्रमिकों पर चलने वाली नौकरियां हैं, जिसमें गुज़ल का उपयोग करके कुछ HTTP अनुरोध शामिल हैं। हालाँकि, GuzzleHttp\Exception\RequestException
जब इस कार्य को पृष्ठभूमि प्रक्रिया में चलाया जा रहा है , तो इस नौकरी के अंदर की कोशिश को रोक नहीं लगता है । रनिंग प्रक्रिया php artisan queue:work
एक लारवेल कतार प्रणाली कार्यकर्ता है जो कतार की निगरानी करता है और नौकरियों को चुनता है।
इसके बजाय, जो अपवाद फेंका गया है GuzzleHttp\Promise\RejectionException
वह संदेश के साथ है:
वादे को अस्वीकार कर दिया गया था: cURL त्रुटि 28: ऑपरेशन 30001 मिलीसेकंड के बाद 0 बाइट्स के साथ प्राप्त हुआ (देखें https://curl.haxx.se/libcurl/c/libcurl-errin.html )
यह वास्तव में एक प्रच्छन्न है GuzzleHttp\Exception\ConnectException
(देखें https://github.com/guzzle/promises/blob/master/src/RejectionException.php#L22 ), क्योंकि अगर मैं नियमित रूप से PHP प्रक्रिया में एक समान काम चलाता हूं जो कि एक पर जाकर ट्रिगर होता है URL, मुझे ConnectException
संदेश के अनुसार इरादा मिलता है :
cURL त्रुटि 28: 100 मिलीसेकंड के बाद के ऑपरेशन में 0 बाइट्स में से 0 के साथ 100 मिलीसेकंड (देखें https://curl.haxx.se/libcurl/c/libcurl-errors.html )
सैंपल कोड जो इस टाइमआउट को ट्रिगर करेगा:
try {
$c = new \GuzzleHttp\Client([
'timeout' => 0.1
]);
$response = (string) $c->get('https://example.com')->getBody();
} catch(GuzzleHttp\Exception\RequestException $e) {
// This occasionally gets catched when a ConnectException (child) is thrown,
// but it doesnt happen with RejectionException because it is not a child
// of RequestException.
}
ऊपर कोड RejectionException
या तो या ConnectException
जब कार्यकर्ता प्रक्रिया में भाग जाता है, लेकिन हमेशा ConnectException
जब ब्राउज़र के माध्यम से मैन्युअल रूप से परीक्षण किया जाता है (जो मैं बता सकता हूं)।
इसलिए मूल रूप से जो मैं प्राप्त करता हूं, वह यह है कि यह RejectionException
संदेश को लपेट ConnectException
रहा है, हालांकि मैं गुज़ल के अतुल्यकालिक सुविधाओं का उपयोग नहीं कर रहा हूं। मेरे अनुरोध बस श्रृंखला में किए गए हैं। केवल एक चीज जो अलग है वह यह है कि कई PHP प्रक्रियाएं गुज़ल एचटीटीपी कॉल कर सकती हैं या यह कि जॉब्स खुद ही टाइम आउट कर रही हैं (जिसके परिणामस्वरूप एक अलग अपवाद लारवेल का होना चाहिए Illuminate\Queue\MaxAttemptsExceededException
), लेकिन मैं नहीं देखती कि यह कैसे कोड को अलग तरह से व्यवहार करने का कारण बनता है।
मैं Guzzle संकुल के अंदर किसी भी कोड को नहीं पा सकता php_sapi_name()
/ रही हूँ PHP_SAPI
(जो कि उपयोग किए गए इंटरफ़ेस को निर्धारित करता है) एक ब्राउज़र ट्रिगर के विपरीत, CLI से चलने पर विभिन्न सामानों को निष्पादित करने के लिए।
tl; डॉ
गुज़ले ने मुझे RejectionException
अपने कार्यकर्ता प्रक्रियाओं पर क्यों फेंका , लेकिन ConnectException
नियमित PHP लिपियों पर ब्राउज़र के माध्यम से ट्रिगर किया गया?
संपादित करें 1
अफसोस की बात है कि मैं एक न्यूनतम प्रजनन योग्य उदाहरण नहीं बना सकता। मुझे अपने संतरी अंक ट्रैकर में कई त्रुटि संदेश दिखाई देते हैं, ऊपर दिखाए गए सटीक अपवाद के साथ। स्रोत के रूप में कहा गया है Starting Artisan command: horizon:work
(जो लारवेल क्षितिज है, यह लारवेल कतारों की देखरेख करता है)। मैंने फिर से जाँच की है कि क्या PHP संस्करणों के बीच कोई विसंगति है, लेकिन वेबसाइट और कार्यकर्ता दोनों प्रक्रियाएं एक ही PHP को चलाती हैं 7.3.14
जो ठीक है:
PHP 7.3.14-1+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Jan 23 2020 13:59:16) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.14, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.3.14-1+ubuntu18.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies
- CURL संस्करण है
cURL 7.58.0
। - गुज़ले संस्करण है
guzzlehttp/guzzle 6.5.2
- लारवेल संस्करण है
laravel/framework 6.12.0
2 संपादित करें (स्टैक ट्रेस)
GuzzleHttp\Promise\RejectionException: The promise was rejected with reason: cURL error 28: Operation timed out after 30000 milliseconds with 0 bytes received (see https://curl.haxx.se/libcurl/c/libcurl-errors.html)
#44 /vendor/guzzlehttp/promises/src/functions.php(112): GuzzleHttp\Promise\exception_for
#43 /vendor/guzzlehttp/promises/src/Promise.php(75): GuzzleHttp\Promise\Promise::wait
#42 /vendor/guzzlehttp/guzzle/src/Client.php(183): GuzzleHttp\Client::request
#41 /app/Bumpers/Client.php(333): App\Bumpers\Client::callRequest
#40 /app/Bumpers/Client.php(291): App\Bumpers\Client::callFunction
#39 /app/Bumpers/Client.php(232): App\Bumpers\Client::bumpThread
#38 /app/Models/Bumper.php(206): App\Models\Bumper::post
#37 /app/Jobs/PostBumper.php(59): App\Jobs\PostBumper::handle
#36 [internal](0): call_user_func_array
#35 /vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(32): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}
#34 /vendor/laravel/framework/src/Illuminate/Container/Util.php(36): Illuminate\Container\Util::unwrapIfClosure
#33 /vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(90): Illuminate\Container\BoundMethod::callBoundMethod
#32 /vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(34): Illuminate\Container\BoundMethod::call
#31 /vendor/laravel/framework/src/Illuminate/Container/Container.php(590): Illuminate\Container\Container::call
#30 /vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(94): Illuminate\Bus\Dispatcher::Illuminate\Bus\{closure}
#29 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(130): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure}
#28 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(105): Illuminate\Pipeline\Pipeline::then
#27 /vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(98): Illuminate\Bus\Dispatcher::dispatchNow
#26 /vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(83): Illuminate\Queue\CallQueuedHandler::Illuminate\Queue\{closure}
#25 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(130): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure}
#24 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(105): Illuminate\Pipeline\Pipeline::then
#23 /vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(85): Illuminate\Queue\CallQueuedHandler::dispatchThroughMiddleware
#22 /vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(59): Illuminate\Queue\CallQueuedHandler::call
#21 /vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(88): Illuminate\Queue\Jobs\Job::fire
#20 /vendor/laravel/framework/src/Illuminate/Queue/Worker.php(354): Illuminate\Queue\Worker::process
#19 /vendor/laravel/framework/src/Illuminate/Queue/Worker.php(300): Illuminate\Queue\Worker::runJob
#18 /vendor/laravel/framework/src/Illuminate/Queue/Worker.php(134): Illuminate\Queue\Worker::daemon
#17 /vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(112): Illuminate\Queue\Console\WorkCommand::runWorker
#16 /vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(96): Illuminate\Queue\Console\WorkCommand::handle
#15 /vendor/laravel/horizon/src/Console/WorkCommand.php(46): Laravel\Horizon\Console\WorkCommand::handle
#14 [internal](0): call_user_func_array
#13 /vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(32): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}
#12 /vendor/laravel/framework/src/Illuminate/Container/Util.php(36): Illuminate\Container\Util::unwrapIfClosure
#11 /vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(90): Illuminate\Container\BoundMethod::callBoundMethod
#10 /vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(34): Illuminate\Container\BoundMethod::call
#9 /vendor/laravel/framework/src/Illuminate/Container/Container.php(590): Illuminate\Container\Container::call
#8 /vendor/laravel/framework/src/Illuminate/Console/Command.php(201): Illuminate\Console\Command::execute
#7 /vendor/symfony/console/Command/Command.php(255): Symfony\Component\Console\Command\Command::run
#6 /vendor/laravel/framework/src/Illuminate/Console/Command.php(188): Illuminate\Console\Command::run
#5 /vendor/symfony/console/Application.php(1012): Symfony\Component\Console\Application::doRunCommand
#4 /vendor/symfony/console/Application.php(272): Symfony\Component\Console\Application::doRun
#3 /vendor/symfony/console/Application.php(148): Symfony\Component\Console\Application::run
#2 /vendor/laravel/framework/src/Illuminate/Console/Application.php(93): Illuminate\Console\Application::run
#1 /vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(131): Illuminate\Foundation\Console\Kernel::handle
#0 /artisan(37): null
Client::callRequest()
समारोह बस एक guzzle ग्राहक जिस पर मैं फोन शामिल हैं $client->request($request['method'], $request['url'], $request['options']);
(ताकि im का उपयोग नहीं requestAsync()
)। मुझे लगता है कि इसके समानांतर चलने वाली नौकरियों के साथ कुछ करना है जो इस मुद्दे का कारण बनता है।
3 संपादित करें (समाधान पाया गया)
निम्नलिखित टेस्टकेस पर विचार करें जो एक HTTP अनुरोध करता है (जो एक नियमित 200 प्रतिक्रिया लौटना चाहिए):
try {
$c = new \GuzzleHttp\Client([
'base_uri' => 'https://example.com'
]);
$handler = $c->getConfig('handler');
$handler->push(\GuzzleHttp\Middleware::mapResponse(function(ResponseInterface $response) {
// Create a fake connection exception:
$e = new \GuzzleHttp\Exception\ConnectException('abc', new \GuzzleHttp\Psr7\Request('GET', 'https://example.com/2'));
// These 2 lines both cascade as `ConnectException`:
throw $e;
return \GuzzleHttp\Promise\rejection_for($e);
// This line cascades as a `RejectionException`:
return \GuzzleHttp\Promise\rejection_for($e->getMessage());
}));
$c->get('');
} catch(\Exception $e) {
var_dump($e);
}
अब मैंने rejection_for($e->getMessage())
जो किया वह मूल रूप से कॉल था जो RejectionException
संदेश स्ट्रिंग के आधार पर अपना स्वयं का बनाता है । कॉलिंग rejection_for($e)
यहाँ सही समाधान था। जवाब देने के लिए केवल एक चीज बची है, यदि यह rejection_for
फ़ंक्शन एक सरल के समान है throw $e
।
HandlerStack
?