/** * When $printStatus is true, the replication details are written to the * STDOUT. When $getFinalReport is true, detailed replication report is * returned and if false, only the success and failure counts are returned. * Both $printStatus and $getFinalReport are used only when the * replication is continuous and are ignored in case of normal replication. * * @param bool $printStatus * @param bool $getFinalReport * @return array * @throws HTTPException */ public function locateChangedDocumentsAndReplicate($printStatus, $getFinalReport) { $finalResponse = array('multipartResponse' => array(), 'bulkResponse' => array(), 'errorResponse' => array()); // Filtered changes stream is not supported. So Don't use the doc_ids // to specify the specific document ids. if ($this->task->getContinuous()) { $options = array('feed' => 'continuous', 'style' => $this->task->getStyle(), 'heartbeat' => $this->task->getHeartbeat(), 'since' => $this->task->getSinceSeq(), 'filter' => $this->task->getFilter()); if ($this->task->getHeartbeat() != null) { $options['heartbeat'] = $this->task->getHeartbeat(); } else { $options['timeout'] = $this->task->getTimeout() != null ? $this->task->getTimeout() : 10000; } $changesStream = $this->source->getChangesAsStream($options); $successCount = 0; $failureCount = 0; while (!feof($changesStream)) { $changes = fgets($changesStream); if ($changes == false || trim($changes) == '' || strpos($changes, 'last_seq') !== false) { sleep(2); continue; } $mapping = $this->getMapping($changes); $docId = array_keys($mapping)[0]; try { // getRevisionDifference throws bad request when JSON is // empty. So check before sending. $revDiff = count($mapping) > 0 ? $this->target->getRevisionDifference($mapping) : array(); $response = $this->replicateChanges($revDiff); if ($getFinalReport == true) { foreach ($response['multipartResponse'] as $docID => $res) { // Add the response of posting each revision of the // doc that had attachments. foreach ($res as $singleRevisionResponse) { // An Exception. if (is_a($singleRevisionResponse, 'Exception')) { // Note: In this case there is no 'rev' field in // the response. $finalResponse['errorResponse'][$docID][] = $singleRevisionResponse; } else { $finalResponse['multipartResponse'][$docID][] = $singleRevisionResponse; } } } foreach ($response['bulkResponse'] as $docID => $status) { $finalResponse['bulkResponse'][$docID][] = $status; } } if ($printStatus == true) { echo 'Document with id = ' . $docId . ' successfully replicated.' . "\n"; } $successCount++; } catch (\Exception $e) { if ($getFinalReport == true) { $finalResponse['errorResponse'][$docID][] = $e; } if ($printStatus == true) { echo 'Replication of document with id = ' . $docId . ' failed with code: ' . $e->getCode() . ".\n"; } $failureCount++; } } $finalResponse['successCount'] = $successCount; $finalResponse['failureCount'] = $failureCount; // The final response in case of continuous replication. // In case where $getFinalReport is true, response has five keys: // (i)multipartResponse, (ii) bulkResponse, (iii)errorResponse, // (iv) successCount, (v) failureCount. The errorResponse has the // responses from the failed replication attempt of docs having // attachments. To check failures related to bulk posting, the // returned status codes can be used. // When $getFinalReport is false, the returned response has only the // successCount and failureCount. return $finalResponse; } else { $changes = $this->source->getChanges(array('feed' => 'normal', 'style' => $this->task->getStyle(), 'since' => $this->task->getSinceSeq(), 'filter' => $this->task->getFilter(), 'doc_ids' => $this->task->getDocIds())); $mapping = $this->getMapping($changes); $revDiff = count($mapping) > 0 ? $this->target->getRevisionDifference($mapping) : array(); $response = $this->replicateChanges($revDiff); foreach ($response['multipartResponse'] as $docID => $res) { // Add the response of posting each revision of the // doc that had attachments. foreach ($res as $singleRevisionResponse) { // An Exception. if (is_a($singleRevisionResponse, 'Exception')) { // Note: In this case there is no 'rev' field in // the response. $finalResponse['errorResponse'][$docID][] = $singleRevisionResponse; } else { $finalResponse['multipartResponse'][$docID][] = $singleRevisionResponse; } } } foreach ($response['bulkResponse'] as $docID => $res) { $finalResponse['bulkResponse'][$docID][] = $res; } // In case of normal replication the $finalResponse has three // keys: (i) multipartResponse, (ii) bulkResponse, (iii) // errorResponse. return $finalResponse; } }