From 2d12ee12930f859a0e5ee7e43a2429bb7f3113ad Mon Sep 17 00:00:00 2001 From: Fausto Quaggia Date: Sun, 7 Jul 2024 22:01:34 +0200 Subject: [PATCH] feat: index manager --- README.md | 28 +++++++ src/Manager/CloudManager.php | 13 ++-- src/Manager/IndexManager.php | 2 +- tests/Feature/IndexManagerTest.php | 114 +++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 8 deletions(-) create mode 100644 tests/Feature/IndexManagerTest.php diff --git a/README.md b/README.md index a380c48..372fe7f 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,34 @@ $query = (new Query()) $results = $client->search($query); ``` +## Managing your index + +```php +use OramaCloud\Manager\CloudManager; +use OramaCloud\Manager\IndexManager; + +$apiKey = 'HDks8Hkao82-ha9daj'; +$manager = new CloudManager($apiKey); + +$indexId = 'h7asdjk9d12kdlofabsha123'; +$index = new IndexManager($indexId, $manager); + +// Empty data +$index->empty(); + +// Insert records +$index->insert([ 'id' => 1, 'name' => 'John Doe', 'age' => 20 ]); + +// Update record +$index->update([ 'id' => 1, 'name' => 'Jane Doe', 'age' => 30 ]); + +// Delete record +$index->delete([ 'id' => 1 ]); + +// Trigger deployment +$index->deploy(); +``` + ## Run Tests ```sh diff --git a/src/Manager/CloudManager.php b/src/Manager/CloudManager.php index 0e4017f..2fa1dc4 100644 --- a/src/Manager/CloudManager.php +++ b/src/Manager/CloudManager.php @@ -11,15 +11,10 @@ class CloudManager private $apiKey; private $http; - public function __construct($apiKey) + public function __construct($apiKey, $http = null) { $this->apiKey = $apiKey; - $this->http = new HttpClient(); - } - - public function index(string $indexId): IndexManager - { - return new IndexManager($indexId, $this); + $this->http = is_null($http) ? new HttpClient() : $http; } public function setIndexId(string $id): void @@ -29,6 +24,10 @@ public function setIndexId(string $id): void public function callIndexWebhook(string $endpoint, $payload = null) { + if (!$this->indexId) { + throw new \Exception('Index ID is not set'); + } + $config = [ 'headers' => [ 'Content-Type' => 'application/json', diff --git a/src/Manager/IndexManager.php b/src/Manager/IndexManager.php index 2bc49c2..ded951a 100644 --- a/src/Manager/IndexManager.php +++ b/src/Manager/IndexManager.php @@ -50,7 +50,7 @@ public function deploy() public function hasPendingOperations() { $response = $this->callIndexWebhook(Endpoints::HAS_DATA); - return $response->hasData; + return property_exists($response, 'hasData') ? $response->hasData : false; } private function checkIndexID() diff --git a/tests/Feature/IndexManagerTest.php b/tests/Feature/IndexManagerTest.php new file mode 100644 index 0000000..342e65e --- /dev/null +++ b/tests/Feature/IndexManagerTest.php @@ -0,0 +1,114 @@ +capturedRequests = []; + + // Middleware to capture requests + $captureMiddleware = function (callable $handler) { + return function ($request, array $options) use ($handler) { + $this->capturedRequests[] = $request; + return $handler($request, $options); + }; + }; + + $mockResponse = new MockHandler([ + new Response(200, [], json_encode(['success' => true])) + ]); + + $handlerStack = HandlerStack::create($mockResponse); + $handlerStack->push($captureMiddleware, 'capture_middleware'); + $mockClient = new GuzzleClient(['handler' => $handlerStack]); + + $this->manager = new CloudManager('mock-api-key', $mockClient); + $this->index = new IndexManager('mock-index', $this->manager); +}); + +describe('Index manager', function () { + it('should empty the index', function () { + // Empty index + $result = $this->index->empty(); + expect($result)->toHaveKey('success'); + + $lastRequest = end($this->capturedRequests); + expect($lastRequest->getMethod())->toBe('POST'); + expect($lastRequest->getUri()->getPath())->toBe('/api/v1/webhooks/mock-index/snapshot'); + expect(json_decode($lastRequest->getBody()->getContents(), true))->toBe(null); + }); + + it('should insert a document', function () { + $data = ['id' => 1, 'name' => 'John Doe']; + // Insert document + $result = $this->index->insert($data); + expect($result)->toHaveKey('success'); + + $lastRequest = end($this->capturedRequests); + expect($lastRequest->getMethod())->toBe('POST'); + expect($lastRequest->getUri()->getPath())->toBe('/api/v1/webhooks/mock-index/notify'); + expect(json_decode($lastRequest->getBody()->getContents(), true))->toBe(['upsert' => $data]); + }); + + it('should update a document', function () { + $data = ['id' => 1, 'name' => 'Jane Doe']; + // Update document + $result = $this->index->update($data); + expect($result)->toHaveKey('success'); + + $lastRequest = end($this->capturedRequests); + expect($lastRequest->getMethod())->toBe('POST'); + expect($lastRequest->getUri()->getPath())->toBe('/api/v1/webhooks/mock-index/notify'); + expect(json_decode($lastRequest->getBody()->getContents(), true))->toBe(['upsert' => $data]); + }); + + it('should delete a document', function () { + // Delete index + $result = $this->index->delete(['id' => 1]); + expect($result)->toHaveKey('success'); + + $lastRequest = end($this->capturedRequests); + expect($lastRequest->getMethod())->toBe('POST'); + expect($lastRequest->getUri()->getPath())->toBe('/api/v1/webhooks/mock-index/notify'); + expect(json_decode($lastRequest->getBody()->getContents(), true))->toBe(['remove' => ['id' => 1]]); + }); + + it('should snapshot the index', function () { + $data = ['id' => 1, 'name' => 'John Doe']; + // Snapshot index + $result = $this->index->snapshot($data); + expect($result)->toHaveKey('success'); + + $lastRequest = end($this->capturedRequests); + expect($lastRequest->getMethod())->toBe('POST'); + expect($lastRequest->getUri()->getPath())->toBe('/api/v1/webhooks/mock-index/snapshot'); + expect(json_decode($lastRequest->getBody()->getContents(), true))->toBe($data); + }); + + it('should deploy the index', function () { + // Deploy index + $result = $this->index->deploy(); + expect($result)->toHaveKey('success'); + + $lastRequest = end($this->capturedRequests); + expect($lastRequest->getMethod())->toBe('POST'); + expect($lastRequest->getUri()->getPath())->toBe('/api/v1/webhooks/mock-index/deploy'); + expect(json_decode($lastRequest->getBody()->getContents(), true))->toBe(null); + }); + + it('should check for pending operations', function () { + // Check for pending operations + $result = $this->index->hasPendingOperations(); + expect($result)->toBe(false); + + $lastRequest = end($this->capturedRequests); + expect($lastRequest->getMethod())->toBe('POST'); + expect($lastRequest->getUri()->getPath())->toBe('/api/v1/webhooks/mock-index/has-data'); + expect(json_decode($lastRequest->getBody()->getContents(), true))->toBe(null); + }); +});