Commit 677442d5 authored by Sebastian Kummer's avatar Sebastian Kummer

Merge pull request #216 in ZP/z-push from...

Merge pull request #216 in ZP/z-push from feature/ZP-837-have-a-configurable-sync_max_response_time to develop

* commit 'a88cd476':
  ZP-837 Fixed even more tpos.
  ZP-837 Fixed tpo!.
  ZP-837 Added config options do categorize devices, when exporting keep looking at the total runtime and stop in time.
parents 7f31028e a88cd476
...@@ -258,6 +258,20 @@ ...@@ -258,6 +258,20 @@
// The minimum accepted value is 1 second. The maximum accepted value is 3540 seconds (59 minutes). // The minimum accepted value is 1 second. The maximum accepted value is 3540 seconds (59 minutes).
define('PING_HIGHER_BOUND_LIFETIME', false); define('PING_HIGHER_BOUND_LIFETIME', false);
// Maximum response time
// Mobiles implement different timeouts to their TCP/IP connections. Android devices for example
// have a hard timeout of 30 seconds. If the server is not able to answer a request within this timeframe,
// the answer will not be recieved and the device will send a new one overloading the server.
// There are three categories
// - Short timeout - server has up within 30 seconds - is automatically applied for not categorized types
// - Medium timeout - server has up to 90 seconds to respond
// - Long timeout - server has up to 4 minutes to respond
// If a timeout is almost reached the server will break and sent the results it has until this
// point. You can add DeviceType strings to the categories.
// In general longer timeouts are better, because more data can be streamed at once.
define('SYNC_TIMEOUT_MEDIUM_DEVICETYPES', "SAMSUNGGTI");
define('SYNC_TIMEOUT_LONG_DEVICETYPES', "iPod, iPad, iPhone, WP, WindowsOutlook");
/********************************************************************************** /**********************************************************************************
* Backend settings * Backend settings
*/ */
......
...@@ -191,9 +191,7 @@ class FolderSync extends RequestProcessor { ...@@ -191,9 +191,7 @@ class FolderSync extends RequestProcessor {
$exporter->InitializeExporter($changesMem); $exporter->InitializeExporter($changesMem);
// Stream all changes to the ImportExportChangesMem // Stream all changes to the ImportExportChangesMem
$maxExporttime = Request::GetExpectedConnectionTimeout();
$totalChanges = $exporter->GetChangeCount(); $totalChanges = $exporter->GetChangeCount();
$started = time();
$exported = 0; $exported = 0;
$partial = false; $partial = false;
while(is_array($exporter->Synchronize())) { while(is_array($exporter->Synchronize())) {
...@@ -204,8 +202,8 @@ class FolderSync extends RequestProcessor { ...@@ -204,8 +202,8 @@ class FolderSync extends RequestProcessor {
} }
// if partial sync is allowed, stop if this takes too long // if partial sync is allowed, stop if this takes too long
if (USE_PARTIAL_FOLDERSYNC && (time() - $started) > $maxExporttime) { if (USE_PARTIAL_FOLDERSYNC && Request::IsRequestTimeoutReached()) {
ZLog::Write(LOGLEVEL_WARN, sprintf("Request->HandleFolderSync(): Exporting folders is too slow. In %d seconds only %d from %d changes were processed.",(time() - $started), $exported, $totalChanges)); ZLog::Write(LOGLEVEL_WARN, sprintf("Request->HandleFolderSync(): Exporting folders is too slow. In %d seconds only %d from %d changes were processed.",(time() - $_SERVER["REQUEST_TIME"]), $exported, $totalChanges));
self::$topCollector->AnnounceInformation(sprintf("Partial export of %d out of %d folders", $exported, $totalChanges), true); self::$topCollector->AnnounceInformation(sprintf("Partial export of %d out of %d folders", $exported, $totalChanges), true);
self::$deviceManager->SetFolderSyncComplete(false); self::$deviceManager->SetFolderSyncComplete(false);
$partial = true; $partial = true;
......
...@@ -97,7 +97,7 @@ class Request { ...@@ -97,7 +97,7 @@ class Request {
static private $koeVersion; static private $koeVersion;
static private $koeBuild; static private $koeBuild;
static private $koeBuildDate; static private $koeBuildDate;
static private $expectedConnectionTimeout;
/** /**
* Initializes request data * Initializes request data
...@@ -626,17 +626,32 @@ class Request { ...@@ -626,17 +626,32 @@ class Request {
// The amount of time returned is somehow lower than the max timeout so we have // The amount of time returned is somehow lower than the max timeout so we have
// time for processing. // time for processing.
// Apple and Windows Phone have higher timeouts (4min = 240sec) if (!isset(self::$expectedConnectionTimeout)) {
if (in_array(self::GetDeviceType(), array("iPod", "iPad", "iPhone", "WP"))) { // Apple and Windows Phone have higher timeouts (4min = 240sec)
return 200; if (stripos(SYNC_TIMEOUT_LONG_DEVICETYPES, self::GetDeviceType()) !== false) {
} self::$expectedConnectionTimeout = 210;
// Samsung devices have a intermediate timeout (90sec) }
if (in_array(self::GetDeviceType(), array("SAMSUNGGTI"))) { // Samsung devices have a intermediate timeout (90sec)
return 50; else if (stripos(SYNC_TIMEOUT_MEDIUM_DEVICETYPES, self::GetDeviceType()) !== false) {
self::$expectedConnectionTimeout = 85;
}
else {
// for all other devices, a timeout of 30 seconds is expected
self::$expectedConnectionTimeout = 28;
}
} }
return self::$expectedConnectionTimeout;
}
// for all other devices, a timeout of 30 seconds is expected /**
return 20; * Indicates if the maximum timeout for the devicetype of this request is
* almost reached.
*
* @access public
* @return boolean
*/
static public function IsRequestTimeoutReached() {
return (time() - $_SERVER["REQUEST_TIME"]) >= self::GetExpectedConnectionTimeout();
} }
/**---------------------------------------------------------------------------------------------------------- /**----------------------------------------------------------------------------------------------------------
......
...@@ -782,6 +782,11 @@ class Sync extends RequestProcessor { ...@@ -782,6 +782,11 @@ class Sync extends RequestProcessor {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("Sync(): no exporter setup for '%s' as GlobalWindowSize is full.", $spa->GetFolderId())); ZLog::Write(LOGLEVEL_DEBUG, sprintf("Sync(): no exporter setup for '%s' as GlobalWindowSize is full.", $spa->GetFolderId()));
$setupExporter = false; $setupExporter = false;
} }
// if the maximum request timeout is reached, stop processing other collections
if (Request::IsRequestTimeoutReached()) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("Sync(): no exporter setup for '%s' as request timeout reached, omitting output for collection.", $spa->GetFolderId()));
$setupExporter = false;
}
// compare the folder statistics if the backend supports this // compare the folder statistics if the backend supports this
if ($setupExporter && self::$backend->HasFolderStats()) { if ($setupExporter && self::$backend->HasFolderStats()) {
...@@ -1084,6 +1089,7 @@ class Sync extends RequestProcessor { ...@@ -1084,6 +1089,7 @@ class Sync extends RequestProcessor {
} }
if($sc->GetParameter($spa, "getchanges") && $spa->HasFolderId() && $spa->HasContentClass() && $spa->HasSyncKey()) { if($sc->GetParameter($spa, "getchanges") && $spa->HasFolderId() && $spa->HasContentClass() && $spa->HasSyncKey()) {
$moreAvailableSent = false;
$windowSize = self::$deviceManager->GetWindowSize($spa->GetFolderId(), $spa->GetUuid(), $spa->GetUuidCounter(), $changecount); $windowSize = self::$deviceManager->GetWindowSize($spa->GetFolderId(), $spa->GetUuid(), $spa->GetUuidCounter(), $changecount);
// limit windowSize to the max available limit of the global window size left // limit windowSize to the max available limit of the global window size left
...@@ -1096,6 +1102,7 @@ class Sync extends RequestProcessor { ...@@ -1096,6 +1102,7 @@ class Sync extends RequestProcessor {
// or there is a move state (another sync should be done afterwards) // or there is a move state (another sync should be done afterwards)
if($changecount > $windowSize || $spa->GetMoveState() !== false) { if($changecount > $windowSize || $spa->GetMoveState() !== false) {
self::$encoder->startTag(SYNC_MOREAVAILABLE, false, true); self::$encoder->startTag(SYNC_MOREAVAILABLE, false, true);
$moreAvailableSent = true;
$spa->DelFolderStat(); $spa->DelFolderStat();
} }
} }
...@@ -1141,7 +1148,7 @@ class Sync extends RequestProcessor { ...@@ -1141,7 +1148,7 @@ class Sync extends RequestProcessor {
} }
} }
if($n >= $windowSize) { if($n >= $windowSize || Request::IsRequestTimeoutReached()) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): Exported maxItems of messages: %d / %d", $n, $changecount)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): Exported maxItems of messages: %d / %d", $n, $changecount));
break; break;
} }
...@@ -1154,6 +1161,18 @@ class Sync extends RequestProcessor { ...@@ -1154,6 +1161,18 @@ class Sync extends RequestProcessor {
} }
self::$encoder->endTag(); self::$encoder->endTag();
// log the request timeout
if (Request::IsRequestTimeoutReached()) {
ZLog::Write(LOGLEVEL_DEBUG, "HandleSync(): Stopping export as maximum request timeout is almost reached!");
// Send a <MoreAvailable/> tag if we reached the request timeout, there are more changes and a moreavailable was not already send
if (!$moreAvailableSent && ($n > $windowSize)) {
self::$encoder->startTag(SYNC_MOREAVAILABLE, false, true);
$spa->DelFolderStat();
$moreAvailableSent = true;
}
}
self::$topCollector->AnnounceInformation(sprintf("Outgoing %d objects%s", $n, ($n >= $windowSize)?" of ".$changecount:""), $this->singleFolder); self::$topCollector->AnnounceInformation(sprintf("Outgoing %d objects%s", $n, ($n >= $windowSize)?" of ".$changecount:""), $this->singleFolder);
$this->saveMultiFolderInfo("outgoing", $n); $this->saveMultiFolderInfo("outgoing", $n);
$this->saveMultiFolderInfo("queued", $changecount); $this->saveMultiFolderInfo("queued", $changecount);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment