private function connect(Request $request) { $promise = httpClient()->request($request, [HttpClient::OP_DISCARD_BODY => true, HttpClient::OP_MS_TRANSFER_TIMEOUT => null]); // yes, yes not spec compliant but it *gets the job done* until we can implement something better $chunkCombiner = new JsonChunkCombiner(); $stats = new Stats(); $logger = $this->logger; $callback = function (array $notifyData) use($chunkCombiner, $stats, $logger) { $event = array_shift($notifyData); if ($event === Notify::REQUEST_SENT) { $stats->increment('connectionAttempts'); $msg = "Connection request #{$stats->connectionAttempts()} sent"; $logger->info($msg); } if ($event === Notify::RESPONSE_HEADERS) { $stats->streamEstablished(); $prettyTime = date('Y-m-d H:i:s', $stats->startTime()); $logger->info("Twitter responded at {$prettyTime} UTC"); } if ($event === Notify::RESPONSE_BODY_DATA) { $data = trim($notifyData[0]); if (!empty($data)) { $chunkCombiner->push($data); if ($chunkCombiner->isValidJson()) { // TODO pass $json to Storage when implemented $json = $chunkCombiner->getCombinedChunksAsJson(); $chunkCombiner->clearChunks(); $stats->increment('statusUpdates'); } } } }; $promise->watch($callback); $promise->when(function ($err, $response) use($logger) { if ($err) { $exceptionType = get_class($err); $msg = "{$exceptionType}('{$err->getMessage()}') in {$err->getFile()} on L{$err->getLine()}"; $logger->critical($msg); // TODO if an exception was thrown should decide if we want to stop execution; this should probably not happen in normal circumstances } else { $msg = "Connection ended: {$response->getStatus()} {$response->getReason()}"; $logger->error($msg); } // TODO remove this when we have the reconnection/backoff implemented \Amp\stop(); }); $statUpdate = function () use($stats) { $runningTime = time() - $stats->startTime(); $this->logger->info("Stats: {$stats->statusUpdates()} statuses. Running for {$runningTime} seconds."); }; $statUpdate = $statUpdate->bindTo($this, $this); repeat($statUpdate, 15000); }
public function testIsValidJson() { $chunks = $this->chunks(); $chunkCombiner = new JsonChunkCombiner(); $chunkCombiner->push($chunks[0]); $this->assertFalse($chunkCombiner->isValidJson(), 'Should not be valid JSON after 1 chunk'); $chunkCombiner->push($chunks[1]); $this->assertFalse($chunkCombiner->isValidJson(), 'Should not be valid JSON after 2 chunks'); $chunkCombiner->push($chunks[2]); $this->assertTrue($chunkCombiner->isValidJson(), 'Should be valid JSON after 3 chunks'); }