Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catch down network exception and non-object responses in fetch #2491

Closed

Conversation

jms-pantheon
Copy link
Collaborator

Catching of exceptions arising from two states.

1) Network is completely down.

This would previously give an uncaught exception when doing any operation from Terminus.

$ terminus site:info jms-vanilla-wp
PHP Fatal error:  Uncaught Error: Call to a member function getBody() on null in phar:///usr/local/Cellar/terminus/3.2.1/bin/terminus/src/Request/Request.php:239
Stack trace:
#0 /Users/jms/.terminus/terminus-dependencies-27a446d993/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php(101): Pantheon\Terminus\Request\Request->Pantheon\Terminus\Request\{closure}(5, Object(GuzzleHttp\Psr7\Request), NULL, Object(GuzzleHttp\Exception\ConnectException))

That is now caught and handled

$ terminus site:info jms-vanilla-wp
 [error]  HTTP request GET https://terminus.pantheon.io/api/site-names/jms-vanilla-wp has failed with error Connection refused for URI https://terminus.pantheon.io/api/site-names/jms-vanilla-wp.
 [error]  Could not locate a site your user may access identified by jms-vanilla-wp: HTTP request has failed with error "Maximum retry attempts reached".

2) Invalid network responses.

This I couldn't reproduce, but based on a stack trace found that certain API responses would sometimes come back processed as a string rather than an object while monitoring workflow logs.

Previous uncaught fatal exception:

$ terminus workflow:wait d9-aus.dev
PHP Fatal error: Uncaught Error: Attempt to assign property "id" on string in /Users/jms/pantheon/terminus-repo/src/Collections/TerminusCollection.php:124
Stack trace:
#0 /Users/jms/pantheon/terminus-repo/src/Commands/Workflow/WaitCommand.php(69): Pantheon\Terminus\Collections\TerminusCollection->fetch(Array)
#1 /Users/jms/pantheon/terminus-repo/src/Commands/Workflow/WaitCommand.php(44): Pantheon\Terminus\Commands\Workflow\WaitCommand->waitForWorkflow(1693326839, Object(Pantheon\Terminus\Models\Site), 'dev', 'Sync code on de...', 180)
#2 [internal function]: Pantheon\Terminus\Commands\Workflow\WaitCommand->workflowWait('d9-aus.dev', '', Array)
#3 /Users/jms/pantheon/terminus-repo/vendor/consolidation/annotated-command/src/CommandProcessor.php(276): call_user_func_array(Array, Array)
#4 /Users/jms/pantheon/terminus-repo/vendor/consolidation/annotated-command/src/CommandProcessor.php(212): Consolidation\AnnotatedCommand\CommandProcessor->runCommandCallback(Array, Object(Consolidation\AnnotatedCommand\CommandData))
#5 /Users/jms/pantheon/terminus-repo/vendor/consolidation/annotated-command/src/CommandProcessor.php(176): Consolidation\AnnotatedCommand\CommandProcessor->validateRunAndAlter(Array, Array, Object(Consolidation\AnnotatedCommand\CommandData))
#6 /Users/jms/pantheon/terminus-repo/vendor/consolidation/annotated-command/src/AnnotatedCommand.php(391): Consolidation\AnnotatedCommand\CommandProcessor->process(Object(Symfony\Component\Console\Output\ConsoleOutput), Array, Array, Object(Consolidation\AnnotatedCommand\CommandData))
#7 /Users/jms/pantheon/terminus-repo/vendor/symfony/console/Command/Command.php(298): Consolidation\AnnotatedCommand\AnnotatedCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#8 /Users/jms/pantheon/terminus-repo/vendor/symfony/console/Application.php(1058): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#9 /Users/jms/pantheon/terminus-repo/vendor/symfony/console/Application.php(301): Symfony\Component\Console\Application->doRunCommand(Object(Consolidation\AnnotatedCommand\AnnotatedCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#10 /Users/jms/pantheon/terminus-repo/vendor/symfony/console/Application.php(171): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#11 /Users/jms/pantheon/terminus-repo/vendor/consolidation/robo/src/Runner.php(282): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#12 /Users/jms/pantheon/terminus-repo/src/Terminus.php(486): Robo\Runner->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput), Object(Symfony\Component\Console\Application), Array)
#13 /Users/jms/pantheon/terminus-repo/bin/terminus(80): Pantheon\Terminus\Terminus->run()
#14 {main}
thrown in /Users/jms/pantheon/terminus-repo/src/Collections/TerminusCollection.php on line 124

Since I wasn't able to reproduce this, I added a handler for it to give more details of the error and a clearer failure.

$ terminus workflow:wait d9-aus.dev
 [error]  Fetch failed from /Users/jms/pantheon/terminus-repo/src/Commands/Workflow/WaitCommand.php:69, model_data expected as object but returned as string. String value: Hello World

@jms-pantheon jms-pantheon requested a review from a team as a code owner August 29, 2023 17:49
@greg-1-anderson
Copy link
Member

Would you please push your branch to pantheon-systems/terminus so that the tests will run? I gave you write access so that you could do this.

Comment on lines +97 to +112
if (!is_object($model_data)) {
// For some reason I can't replicate, occasionally $model_data is just a string here.
$trace = debug_backtrace();
$error_message = "Fetch failed {file}:{line} model_data expected as object but returned as {type}.";
$context = [
'file' => $trace[0]['file'],
'line' => $trace[0]['line'],
'type' => gettype($model_data),
];
if (is_string($model_data)) {
$error_message .= " String value: {string}";
$context['string'] = strlen($model_data) > 250 ? substr($model_data, 0, 250) . '...' : $model_data;
}
$this->logger->error($error_message, $context);
break;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on board with this. I might even change 106 to is_scalar and add an else that gathered the value via $error_message .= " Value: " . print_r($model_data, true); .. but there might be a chance of print_r() out of memory'ing...

@jms-pantheon
Copy link
Collaborator Author

@greg-1-anderson @namespacebrian I'm closing this in favor of #2492 on pantheon-systems/terminus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants