re-try to send unshare notification if remote server is not available
This commit is contained in:
parent
1576a9a10b
commit
fbd5c28c39
|
@ -0,0 +1,142 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Björn Schießle <schiessle@owncloud.com>
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||||
|
* @license AGPL-3.0
|
||||||
|
*
|
||||||
|
* This code is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace OCA\FederatedFileSharing\BackgroundJob;
|
||||||
|
|
||||||
|
|
||||||
|
use OC\BackgroundJob\Job;
|
||||||
|
use OC\BackgroundJob\JobList;
|
||||||
|
use OCA\FederatedFileSharing\AddressHandler;
|
||||||
|
use OCA\FederatedFileSharing\DiscoveryManager;
|
||||||
|
use OCA\FederatedFileSharing\Notifications;
|
||||||
|
use OCP\BackgroundJob\IJobList;
|
||||||
|
use OCP\ILogger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UnShare
|
||||||
|
*
|
||||||
|
* Background job to re-send the un-share notification to the remote server in
|
||||||
|
* case the server was not available on the first try
|
||||||
|
*
|
||||||
|
* @package OCA\FederatedFileSharing\BackgroundJob
|
||||||
|
*/
|
||||||
|
class UnShare extends Job {
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $retainJob = true;
|
||||||
|
|
||||||
|
/** @var Notifications */
|
||||||
|
private $notifications;
|
||||||
|
|
||||||
|
/** @var int max number of attempts to send the un-share request */
|
||||||
|
private $maxTry = 10;
|
||||||
|
|
||||||
|
/** @var int how much time should be between two tries (12 hours) */
|
||||||
|
private $interval = 43200;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UnShare constructor.
|
||||||
|
*
|
||||||
|
* @param Notifications $notifications
|
||||||
|
*/
|
||||||
|
public function __construct(Notifications $notifications = null) {
|
||||||
|
if ($notifications) {
|
||||||
|
$this->notifications = $notifications;
|
||||||
|
} else {
|
||||||
|
$addressHandler = new AddressHandler(
|
||||||
|
\OC::$server->getURLGenerator(),
|
||||||
|
\OC::$server->getL10N('federatedfilesharing')
|
||||||
|
);
|
||||||
|
$discoveryManager = new DiscoveryManager(
|
||||||
|
\OC::$server->getMemCacheFactory(),
|
||||||
|
\OC::$server->getHTTPClientService()
|
||||||
|
);
|
||||||
|
$this->notifications = new Notifications(
|
||||||
|
$addressHandler,
|
||||||
|
\OC::$server->getHTTPClientService(),
|
||||||
|
$discoveryManager,
|
||||||
|
\OC::$server->getJobList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* run the job, then remove it from the jobList
|
||||||
|
*
|
||||||
|
* @param JobList $jobList
|
||||||
|
* @param ILogger $logger
|
||||||
|
*/
|
||||||
|
public function execute($jobList, ILogger $logger = null) {
|
||||||
|
|
||||||
|
if ($this->shouldRun($this->argument)) {
|
||||||
|
parent::execute($jobList, $logger);
|
||||||
|
$jobList->remove($this, $this->argument);
|
||||||
|
if ($this->retainJob) {
|
||||||
|
$this->reAddJob($jobList, $this->argument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function run($argument) {
|
||||||
|
$remote = $argument['remote'];
|
||||||
|
$id = (int)$argument['id'];
|
||||||
|
$token = $argument['token'];
|
||||||
|
$try = (int)$argument['try'] + 1;
|
||||||
|
|
||||||
|
$result = $this->notifications->sendRemoteUnShare($remote, $id, $token, $try);
|
||||||
|
|
||||||
|
if ($result === true || $try > $this->maxTry) {
|
||||||
|
$this->retainJob = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* re-add background job with new arguments
|
||||||
|
*
|
||||||
|
* @param IJobList $jobList
|
||||||
|
* @param array $argument
|
||||||
|
*/
|
||||||
|
protected function reAddJob(IJobList $jobList, array $argument) {
|
||||||
|
$jobList->add('OCA\FederatedFileSharing\BackgroundJob\UnShare',
|
||||||
|
[
|
||||||
|
'remote' => $argument['remote'],
|
||||||
|
'id' => $argument['id'],
|
||||||
|
'token' => $argument['token'],
|
||||||
|
'try' => (int)$argument['try'] + 1,
|
||||||
|
'lastRun' => time()
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test if it is time for the next run
|
||||||
|
*
|
||||||
|
* @param array $argument
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function shouldRun(array $argument) {
|
||||||
|
$lastRun = (int)$argument['lastRun'];
|
||||||
|
return ((time() - $lastRun) > $this->interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
namespace OCA\FederatedFileSharing;
|
namespace OCA\FederatedFileSharing;
|
||||||
|
|
||||||
|
use OCP\BackgroundJob\IJobList;
|
||||||
use OCP\Http\Client\IClientService;
|
use OCP\Http\Client\IClientService;
|
||||||
|
|
||||||
class Notifications {
|
class Notifications {
|
||||||
|
@ -30,24 +31,32 @@ class Notifications {
|
||||||
|
|
||||||
/** @var AddressHandler */
|
/** @var AddressHandler */
|
||||||
private $addressHandler;
|
private $addressHandler;
|
||||||
|
|
||||||
/** @var IClientService */
|
/** @var IClientService */
|
||||||
private $httpClientService;
|
private $httpClientService;
|
||||||
|
|
||||||
/** @var DiscoveryManager */
|
/** @var DiscoveryManager */
|
||||||
private $discoveryManager;
|
private $discoveryManager;
|
||||||
|
|
||||||
|
/** @var IJobList */
|
||||||
|
private $jobList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param AddressHandler $addressHandler
|
* @param AddressHandler $addressHandler
|
||||||
* @param IClientService $httpClientService
|
* @param IClientService $httpClientService
|
||||||
* @param DiscoveryManager $discoveryManager
|
* @param DiscoveryManager $discoveryManager
|
||||||
|
* @param IJobList $jobList
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
AddressHandler $addressHandler,
|
AddressHandler $addressHandler,
|
||||||
IClientService $httpClientService,
|
IClientService $httpClientService,
|
||||||
DiscoveryManager $discoveryManager
|
DiscoveryManager $discoveryManager,
|
||||||
|
IJobList $jobList
|
||||||
) {
|
) {
|
||||||
$this->addressHandler = $addressHandler;
|
$this->addressHandler = $addressHandler;
|
||||||
$this->httpClientService = $httpClientService;
|
$this->httpClientService = $httpClientService;
|
||||||
$this->discoveryManager = $discoveryManager;
|
$this->discoveryManager = $discoveryManager;
|
||||||
|
$this->jobList = $jobList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,16 +106,45 @@ class Notifications {
|
||||||
* @param string $remote url
|
* @param string $remote url
|
||||||
* @param int $id share id
|
* @param int $id share id
|
||||||
* @param string $token
|
* @param string $token
|
||||||
|
* @param int $try how often did we already tried to send the un-share request
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function sendRemoteUnShare($remote, $id, $token) {
|
public function sendRemoteUnShare($remote, $id, $token, $try = 0) {
|
||||||
$url = rtrim($remote, '/');
|
$url = rtrim($remote, '/');
|
||||||
$fields = array('token' => $token, 'format' => 'json');
|
$fields = array('token' => $token, 'format' => 'json');
|
||||||
$url = $this->addressHandler->removeProtocolFromUrl($url);
|
$url = $this->addressHandler->removeProtocolFromUrl($url);
|
||||||
$result = $this->tryHttpPostToShareEndpoint($url, '/'.$id.'/unshare', $fields);
|
$result = $this->tryHttpPostToShareEndpoint($url, '/'.$id.'/unshare', $fields);
|
||||||
$status = json_decode($result['result'], true);
|
$status = json_decode($result['result'], true);
|
||||||
|
|
||||||
return ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200));
|
if ($result['success'] &&
|
||||||
|
($status['ocs']['meta']['statuscode'] === 100 ||
|
||||||
|
$status['ocs']['meta']['statuscode'] === 200
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
} elseif ($try === 0) {
|
||||||
|
// only add new job on first try
|
||||||
|
$this->jobList->add('OCA\FederatedFileSharing\BackgroundJob\UnShare',
|
||||||
|
[
|
||||||
|
'remote' => $remote,
|
||||||
|
'id' => $id,
|
||||||
|
'token' => $token,
|
||||||
|
'try' => $try,
|
||||||
|
'lastRun' => $this->getTimestamp()
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return current timestamp
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected function getTimestamp() {
|
||||||
|
return time();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,7 +155,7 @@ class Notifications {
|
||||||
* @param array $fields post parameters
|
* @param array $fields post parameters
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields) {
|
protected function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields) {
|
||||||
$client = $this->httpClientService->newClient();
|
$client = $this->httpClientService->newClient();
|
||||||
$protocol = 'https://';
|
$protocol = 'https://';
|
||||||
$result = [
|
$result = [
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Björn Schießle <schiessle@owncloud.com>
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||||
|
* @license AGPL-3.0
|
||||||
|
*
|
||||||
|
* This code is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace OCA\FederatedFileSharing\Tests;
|
||||||
|
|
||||||
|
|
||||||
|
use OCA\FederatedFileSharing\AddressHandler;
|
||||||
|
use OCA\FederatedFileSharing\DiscoveryManager;
|
||||||
|
use OCA\FederatedFileSharing\Notifications;
|
||||||
|
use OCP\BackgroundJob\IJobList;
|
||||||
|
use OCP\Http\Client\IClientService;
|
||||||
|
use Test\TestCase;
|
||||||
|
|
||||||
|
class NotificationsTest extends TestCase {
|
||||||
|
|
||||||
|
/** @var AddressHandler | \PHPUnit_Framework_MockObject_MockObject */
|
||||||
|
private $addressHandler;
|
||||||
|
|
||||||
|
/** @var IClientService | \PHPUnit_Framework_MockObject_MockObject*/
|
||||||
|
private $httpClientService;
|
||||||
|
|
||||||
|
/** @var DiscoveryManager | \PHPUnit_Framework_MockObject_MockObject */
|
||||||
|
private $discoveryManager;
|
||||||
|
|
||||||
|
/** @var IJobList | \PHPUnit_Framework_MockObject_MockObject */
|
||||||
|
private $jobList;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->jobList = $this->getMock('OCP\BackgroundJob\IJobList');
|
||||||
|
$this->discoveryManager = $this->getMockBuilder('OCA\FederatedFileSharing\DiscoveryManager')
|
||||||
|
->disableOriginalConstructor()->getMock();
|
||||||
|
$this->httpClientService = $this->getMock('OCP\Http\Client\IClientService');
|
||||||
|
$this->addressHandler = $this->getMockBuilder('OCA\FederatedFileSharing\AddressHandler')
|
||||||
|
->disableOriginalConstructor()->getMock();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get instance of Notifications class
|
||||||
|
*
|
||||||
|
* @param array $mockedMethods methods which should be mocked
|
||||||
|
* @return Notifications | \PHPUnit_Framework_MockObject_MockObject
|
||||||
|
*/
|
||||||
|
private function getInstance(array $mockedMethods = []) {
|
||||||
|
if (empty($mockedMethods)) {
|
||||||
|
$instance = new Notifications(
|
||||||
|
$this->addressHandler,
|
||||||
|
$this->httpClientService,
|
||||||
|
$this->discoveryManager,
|
||||||
|
$this->jobList
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$instance = $this->getMockBuilder('OCA\FederatedFileSharing\Notifications')
|
||||||
|
->setConstructorArgs(
|
||||||
|
[
|
||||||
|
$this->addressHandler,
|
||||||
|
$this->httpClientService,
|
||||||
|
$this->discoveryManager,
|
||||||
|
$this->jobList
|
||||||
|
]
|
||||||
|
)->setMethods($mockedMethods)->getMock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataTestSendRemoteUnShare
|
||||||
|
*
|
||||||
|
* @param int $try
|
||||||
|
* @param array $httpRequestResult
|
||||||
|
* @param bool $expected
|
||||||
|
*/
|
||||||
|
public function testSendRemoteUnShare($try, $httpRequestResult, $expected) {
|
||||||
|
$remote = 'remote';
|
||||||
|
$id = 42;
|
||||||
|
$timestamp = 63576;
|
||||||
|
$token = 'token';
|
||||||
|
$instance = $this->getInstance(['tryHttpPostToShareEndpoint', 'getTimestamp']);
|
||||||
|
|
||||||
|
$instance->expects($this->any())->method('getTimestamp')->willReturn($timestamp);
|
||||||
|
|
||||||
|
$instance->expects($this->once())->method('tryHttpPostToShareEndpoint')
|
||||||
|
->with($remote, '/'.$id.'/unshare', ['token' => $token, 'format' => 'json'])
|
||||||
|
->willReturn($httpRequestResult);
|
||||||
|
|
||||||
|
$this->addressHandler->expects($this->once())->method('removeProtocolFromUrl')
|
||||||
|
->with($remote)->willReturn($remote);
|
||||||
|
|
||||||
|
// only add background job on first try
|
||||||
|
if ($try === 0 && $expected === false) {
|
||||||
|
$this->jobList->expects($this->once())->method('add')
|
||||||
|
->with(
|
||||||
|
'OCA\FederatedFileSharing\BackgroundJob\UnShare',
|
||||||
|
[
|
||||||
|
'remote' => $remote,
|
||||||
|
'id' => $id,
|
||||||
|
'token' => $token,
|
||||||
|
'try' => $try,
|
||||||
|
'lastRun' => $timestamp
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->jobList->expects($this->never())->method('add');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertSame($expected,
|
||||||
|
$instance->sendRemoteUnShare($remote, $id, $token, $try)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataTestSendRemoteUnshare() {
|
||||||
|
return [
|
||||||
|
// test if background job is added correctly
|
||||||
|
[0, ['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 200]]])], true],
|
||||||
|
[1, ['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 200]]])], true],
|
||||||
|
[0, ['success' => false, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 200]]])], false],
|
||||||
|
[1, ['success' => false, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 200]]])], false],
|
||||||
|
// test all combinations of 'statuscode' and 'success'
|
||||||
|
[0, ['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 200]]])], true],
|
||||||
|
[0, ['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])], true],
|
||||||
|
[0, ['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 400]]])], false],
|
||||||
|
[0, ['success' => false, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 200]]])], false],
|
||||||
|
[0, ['success' => false, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])], false],
|
||||||
|
[0, ['success' => false, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 400]]])], false],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -100,7 +100,8 @@ class ProviderFactory implements IProviderFactory {
|
||||||
$notifications = new Notifications(
|
$notifications = new Notifications(
|
||||||
$addressHandler,
|
$addressHandler,
|
||||||
$this->serverContainer->getHTTPClientService(),
|
$this->serverContainer->getHTTPClientService(),
|
||||||
$discoveryManager
|
$discoveryManager,
|
||||||
|
$this->serverContainer->getJobList()
|
||||||
);
|
);
|
||||||
$tokenHandler = new TokenHandler(
|
$tokenHandler = new TokenHandler(
|
||||||
$this->serverContainer->getSecureRandom()
|
$this->serverContainer->getSecureRandom()
|
||||||
|
|
Loading…
Reference in New Issue