我的第一个问题。
问题与此类似:PHP: Retrying a query a set number of times or until success
尝试以OO方式取得成功。 这里是我想要做的例子:
class Creatives {
public function run() {
$auth_token='mypassword';
$id=123123;
$this->retry_till_success ( $this->getCreatives, array($auth_token, $id) );
print $this->creatives;
}
public function getCreatives($auth_token, $id) {
$this->creatives = $this->campagin->get($auth_token, $id);
}
private function retry_till_success($method, $args) {
do {
$try_again = false;
try {
/* how to call the method with */
/* call user method with params pass */
/* do until success */
} catch (SoapFault $fault) {
if($fault->faultstring== 'couldnt connect to host')
$try_again=true;
}
} while ($try_again);
}
}
我读过call_user_func,但不知道我是否可以在课堂内使用它, 我需要在我的通话中取得99.9%的成功率,任何实现这一目标的建议都会很棒。 谢谢。
答案 0 :(得分:2)
最好的方法是扩展SoapClient并在__call方法中添加重试。
class LocalSoapClient extends SoapClient
{
public function __call($function_name, $arguments)
{
$result = false;
$max_retries = 5;
$retry_count = 0;
while(! $result && $retry_count < $max_retries)
{
try
{
$result = parent::__call($function_name, $arguments);
}
catch(SoapFault $fault)
{
if($fault->faultstring != 'Could not connect to host')
{
throw $fault;
}
}
sleep(1);
$retry_count ++;
}
if($retry_count == $max_retries)
{
throw new SoapFault('Could not connect to host after 5 attempts');
}
return $result;
}
}
然后当您实例化您的soap客户端时,请使用new LocalSoapClient()
而不是new SoapClient()
答案 1 :(得分:1)
$result = call_user_func_array( array($this, $method), $args );
第一个参数是回调pseudo-type,第二个参数是一个参数数组,它们将作为单独的参数传递给函数/方法。
作为旁注,您可能希望查看限制重试(例如,每次失败达到设定限制时,睡眠时间会加倍)。如果与主机的连接断开,那么尽可能快地重试可能没什么意义。
答案 2 :(得分:0)
private function retry_till_success($method, $args) {
...
$this->$method($args[0], $args[1]);
}
你也可以使用ReflectionClass / ReflectionMethod并调用InvokeArgs()来获取可变数量的args
答案 3 :(得分:0)
我不太清楚你的意思,但这就是call_user_func(_array)()的工作原理:
call_user_func($method, $arg); //call global function named $method like this: $method($arg)
call_user_func(array($this, $method), $arg); call class method on this class like this: $this->$method($arg);
//lets presume args is an array: $args = array(1, 2);
call_user_func_array($method, $args); //calls global function named $method like this: $method($args[0], $args[1]);
call_user_func_array(array($this, $method), $args); //calls class method like this: $this->$method($args[0], $args[1]);
另请参阅call_user_func的文档:
http://nl3.php.net/manual/en/function.call-user-func.php
并且对于call_user_func_array:
http://nl3.php.net/manual/en/function.call-user-func-array.php
答案 4 :(得分:0)
$this->getCreatives
将无法正常工作,因为PHP函数不是基类公民。您可以使用call_user_func[_array]
或为任务创建工厂,并将每个任务表示为实现接口的对象(即iRepeatableTask)。因此你可以打电话
try
{
$task->repeatUntilSuccess()
} catch (SoapFault $e) {...}
并且优点是这些目标在DB中易于保存/恢复以便稍后执行(即使用cronjob等)。
答案 5 :(得分:0)
这是我在制作中使用的最终解决方案。
protected function retry_till_success($method, $args) {
/*
* -1 : unrecoverable error
* 0 : recoverable error
* 1 : success
*/
$success = 0;
$tries = 0;
do {
$tries++;
$success = call_user_func_array( array($this, $method), $args );
if ($success===0) {
usleep(self::DELAY_MS);
}
} while ($success===0 && $tries < self::MAX_RETRIES);
if ($tries >= self::MAX_RETRIES)
return false;
return true;
}