How to only use my max api calls php - php

I am using the raw blockchain api and the docs say that I can do 1 request every 10 seconds, how would I make sure that I don't go over this limit? I'd prefer to keep it server side with php. Thank you for the response

After each call to the API add to your internal time counter 10 seconds to know when the next call will be allowed.
class ApiRequest{
private $nextRequestTime = time();
private function allowRequest(){
$local_time = now();
if($local_time >= $this->nextRequestTime ){
$this->nextRequestTime = ($local_time + 10);
return true;
}
return false;
}
public function doRequest($request){
if($this->allowRequest()){
// process the $request...
}
}
}
When function ApiRequest::allowRequest() returns false you know that you should process the request later.

Related

Twilio REST API unresponsive

I have created a soft phone for use with Twilio, using Twilio.js (1.4) and the Twilio REST API.
On the connection callback, I have a need to fetch the childSid for a call. To accommodate this I created a route in my Laravel app to use the Calls list resource and get it into the browser using jQuery.get() on the connection callback.
For some reason the API does not respond at all if I don't first wait about 12 seconds after the initial connection. After using sleep(12) in my PHP function I can successfully read the calls and filter for the ParentSid with no issues.
Is there a reason the API will not respond if invoked too soon after a connection is made via Twilio.js? It seems to only do this when I'm using $client->calls>read(). I have no problem retrieving a parentCallSid from a call immediately using $client->calls($callSid)->fetch().
Here is the original code:
public function showChildCallSid(Request $request, Client $client) {
$callSid = $request->input('CallSid');
sleep(12); // only works after waiting about 12 seconds
$call = $client->calls->read(['ParentCallSid' => $callSid])[0];
return $call->sid;
}
I believe the issue was ultimately a problem with syntax. I revised to the code as shown below and it works very well now (only needing a 1-second pause usually):
public function showChildCallSid(Request $request, Client $client) {
$callSid = $request->input('CallSid');
$attempt = 1;
$maxAttempts = 15;
do {
$calls = $client->calls->read(['ParentCallSid' => $callSid]);
if (sizeof($calls) > 0) {
break;
}
sleep(1);
$attempt++;
} while ($attempt < $maxAttempts);
$childSid = $calls[0]->sid;
return $childSid;
}

Nice way to add retry functionality to api calls?

I have an api class to contact a REST api for mailing list management. It includes methods such as subscribe(), unsubscribe(), update(), etc.
In my client code, I have lines such as
Api::subscribe($email, array(..));
Because of occasional failures, we want to add retry functionality to each call. If a call fails the first time, we want to retry once or twice more, before we finally give up.
The straight-forward way to do this is
public static function subscribe($email, array $lists ) {
$success = FALSE;
$retries = 3;
while ( ! success && retries > 0 ) {
// API call goes here
$retries--;
}
}
Rinse and repeat for each method.
In the interests of DRY (Don't Repeat Yourself), I was wondering if there was a nice, design-patterny way to wrap my calls in retries without having to repeat the while loop for each method.
If not, and the simple way is the best fit, that's fine. I just wanted to see if there was a better way out there that I was not aware of.
public function retry($apiCall, $retries) {
$success = false;
while (!$success && $retries > 0 ) {
$success |= $apiCall();
$retries--;
}
}
public static function subscribe($email, array $lists) {
retry(function() {
// your API call here
}, 3);
}
You simply construct an anomymous function and pass the anonomous function to the code that handles the retrying. Obviously this should be a bit more elaborate to allow returning values (which can be added quite trivially) or to be observable.
One way to make it observable is by passing a callback:
public function retry($apiCall, $retries, $callback) {
$success = false;
while (!$success && $retries > 0 ) {
$success |= $apiCall();
$retries--;
}
$callback($success);
}
You'd simply need to pass the proper callback that does the notification. You can expand greatly on this by passing more elaborate parameters about the kind of event and kind of failure, number of retries etc. depending on your exact needs.

How to make Behat wait for an AJAX call?

Scenario: Modify and save an incomplete change to a Campaign
Given I click on the Campaign section folder
And I press Save in the selected Campaign
Then I should see an error balloon informing the changes cannot be saved
Point is that this 'error balloon' in the final step is a ajax call which will then bring a green or red balloon according to the success of the operation. Currently what I do is after
'And I press Save...' I will do a sleep(3) to give it time for this balloon to show up. This doesn't seem very smart coz you are wasting time and also because some times it can take more or less time for this call to be processed.
How do you guys make your behat tests wait for Ajax do be done instead of just putting the beasts to sleep?
thank you very much for any feedback!
This is done by waiting for your outstanding ajax calls to hit 0. jQuery.active will check just that for you.
In your FeatureContext.php, you can do something like;
public function iShouldSeeAnErrorBalloon($title)
{
$time = 5000; // time should be in milliseconds
$this->getSession()->wait($time, '(0 === jQuery.active)');
// asserts below
}
And do make sure you use a Mink Driver that runs javascript and ajax (the default does not).
I do it by waiting for the DOM to change as a result of the Ajax Call. I made a subclass of DocumentElement, calling it AsyncDocumentElement and overriding the findAll method:
public function findAll($selector, $locator, $waitms=5000)
{
$xpath = $this->getSession()->getSelectorsHandler()->selectorToXpath($selector, $locator);
// add parent xpath before element selector
if (0 === strpos($xpath, '/')) {
$xpath = $this->getXpath().$xpath;
} else {
$xpath = $this->getXpath().'/'.$xpath;
}
$page = $this->getSession()->getPage();
// my code to wait until the xpath expression provides an element
if ($waitms && !($this->getSession()->getDriver() instanceof \Behat\Symfony2Extension\Driver\KernelDriver)) {
$templ = 'document.evaluate("%s", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null ).snapshotLength > 0;';
$waitJs = sprintf($templ, $xpath);
$this->getSession()->wait($waitms, $waitJs);
}
return $this->getSession()->getDriver()->find($xpath);
}
Then in \Behat\Mink\Session I changed the constructor to use that class.
public function __construct(DriverInterface $driver, SelectorsHandler $selectorsHandler = null)
{
$driver->setSession($this);
if (null === $selectorsHandler) {
$selectorsHandler = new SelectorsHandler();
}
$this->driver = $driver;
$this->page = new AsyncDocumentElement($this);
$this->selectorsHandler = $selectorsHandler;
}
Once I did this, I found my AngularJS tests were working. So far, I've only tested in Firefox.
In case you are using Prototypejs (e.g Magento), the equivalent code is:
public function iShouldSeeAnErrorBalloon($title)
{
$this->getSession()->wait($duration, '(0 === Ajax.activeRequestCount)');
// asserts below
}

curl_multi_exec kills whole process when there ia a single timeout

I am using curl_multi to send out emails out in a rolling curl script similar to this one but i added a curlopt_timeout of 10 seconds and a curlopt_connecttimeout of 20 seconds
http://www.onlineaspect.com/2009/01/26/how-to-use-curl_multi-without-blocking/
while testing it i reduced the timeouts to 1ms by using timeout_ms and connecttimeout_ms respectively, just to see how it handles a timeout. But the timeout kills the entire curl process. Is there a way to continue with the other threads even if one times out??
Thanks.
-devo
https://github.com/krakjoe/pthreads
<?php
class Possibilities extends Thread {
public function __construct($url){
$this->url = $url;
}
public function run(){
/*
* Or use curl, this is quicker to make an example ...
*/
return file_get_contents($this->url);
}
}
$threads = array();
$urls = get_my_urls_from_somewhere();
foreach($urls as $index => $url){
$threads[$index]=new Possibilities($url);
$threads[$index]->start();
}
foreach($threads as $index => $thread ){
if( ( $response = $threads[$index]->join() ) ){
/** good, got a response */
} else { /** we do not care **/ }
}
?>
My guess is, you are using curl multi as it's the only option for concurrent execution of the code sending out emails ... if this is the case, I do not suggest that you use anything like the code above, I suggest that you thread the calls to mail() directly as this will be faster and more efficient by far.
But now you know, you can thread in PHP .. enjoy :)

PHP Timeout not working on webservice

I am trying to force PHP to NEVER try to connect and send information to a webservice over
a set period of time. I am using below and for some reason it will run over the time allowed and I can't figure out why. For example if I set it to 30 seconds, I will see that it takes a lot longer in some cases. I need to figure out a way to 100% kill connection if it takes too long.
TIA,
Will
$intTimeout = $this->getTimeout();
$client = new SoapClient("{$this->url}?WSDL", array('trace' => 0, 'connection_timeout'=>$intTimeout));
try {
$this->response = $client->someService($objPerson);
}
catch(Exception $e) {
}
$this->restoreTimeout();
function getTimeout()
{
$intTimeout = #$this->timeout ? $this->timeout : 60;
$_SESSION['old_sock'] = ini_get('default_socket_timeout');
ini_set('default_socket_timeout', $intTimeout);
return $intTimeout;
}
function restoreTimeout()
{
$intCurSockTime = #$_SESSION['old_sock'];
if($intCurSockTime) ini_set('default_socket_timeout', $intCurSockTime);
}
the problem is: default_socket_timeout is counting before socket responds, as long as it gets response, it will wait forever.
this is a good example using curl with timeout as fallback: http://www.darqbyte.com/2009/10/21/timing-out-php-soap-calls/
similar question: PHP SoapClient Timeout

Categories