Skip to content

Commit 3dfc6c5

Browse files
committed
Merge pull request #63 from corley/feature/query-manager
Support for custom query manager
2 parents dd30958 + a056cc2 commit 3dfc6c5

File tree

13 files changed

+443
-73
lines changed

13 files changed

+443
-73
lines changed

README.md

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -183,16 +183,6 @@ array(1) {
183183
}
184184
```
185185

186-
## Database operations
187-
188-
You can create, list or destroy databases using dedicated methods
189-
190-
```php
191-
$client->getDatabases(); // list all databases
192-
$client->createDatabase("my-name"); // create a new database with name "my.name"
193-
$client->deleteDatabase("my-name"); // delete an existing database with name "my.name"
194-
```
195-
196186
## Global tags and retention policy
197187

198188
You can set a set of default tags, that the SDK will add to your metrics:
@@ -300,6 +290,75 @@ $connectionParams = array(
300290
$conn = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config);
301291
```
302292

293+
## Database operations and custom queries
294+
295+
The class `InfluxDB\Client` does not support any database operation by itself.
296+
That means that you don't have any helper function for create new databases, or
297+
list actual databases and so on.
298+
Thanks to `InfluxDB\Manager` you can use a preset of queries and create your own
299+
personal queries that will run against the Influxdb instance.
300+
301+
### Create the manager
302+
303+
The `Manager` instance is very simple, you have to create it with a client
304+
instance.
305+
306+
```php
307+
$manager = new Manager($client); // InfluxDB\Client instance
308+
```
309+
310+
### Attach new queries
311+
312+
The manager allows to attach new queries via an helper method `addQuery`.
313+
314+
```php
315+
$manager->addQuery("getExceptionsInMinutes", function($minutes) {
316+
return "SELECT * FROM app_exceptions WHERE time > now() - {$minutes}m";
317+
});
318+
319+
$manager->getExceptionsInMinutes(10); // The callable name
320+
```
321+
322+
As you can see you have to label your anonymous function and reuse it via the
323+
manager.
324+
325+
In order to collect and reuse custom queries you can define query objects:
326+
327+
```php
328+
class GetExceptionsInMinutes
329+
{
330+
public function __invoke($minutes)
331+
{
332+
return "SELECT * FROM app_exceptions WHERE time > now() - {$minutes}m";
333+
}
334+
335+
public function __toString()
336+
{
337+
return "getExceptionsInMinutes";
338+
}
339+
}
340+
341+
$manager->addQuery(new GetExceptionsInMinutes());
342+
343+
$manger->getExceptionsInMinutes(10); //Use the query
344+
```
345+
346+
As you can see valid query command should be `callable` via the `__invoke`
347+
method and should be also serializable as strings via `__toString` method
348+
349+
### Existing queries
350+
351+
This project comes out with a preset of valid queries:
352+
353+
* Create new database `InfluxDB\Query\CreateDatabase`
354+
* Drop existing databases `InfluxDB\Query\DeleteDatabase`
355+
* List existing databases `InfluxDB\Query\GetDatabases`
356+
357+
```php
358+
$manager->addQuery(new CreateDatabase());
359+
$manager->addQuery(new DeleteDatabase());
360+
$manager->addQuery(new GetDatabases());
361+
```
303362

304363
## FAQ
305364

src/Client.php

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,4 @@ public function query($query)
4545
{
4646
return $this->getReader()->query($query);
4747
}
48-
49-
public function getDatabases()
50-
{
51-
@trigger_error('The '.__METHOD__.' method is deprecated since version 0.8.1 and will be removed in 0.9.', E_USER_DEPRECATED);
52-
return $this->query("show databases");
53-
}
54-
55-
public function createDatabase($name)
56-
{
57-
@trigger_error('The '.__METHOD__.' method is deprecated since version 0.8.1 and will be removed in 0.9.', E_USER_DEPRECATED);
58-
return $this->query("create database \"{$name}\"");
59-
}
60-
61-
public function deleteDatabase($name)
62-
{
63-
@trigger_error('The '.__METHOD__.' method is deprecated since version 0.8.1 and will be removed in 0.9.', E_USER_DEPRECATED);
64-
return $this->query("drop database \"{$name}\"");
65-
}
6648
}

src/Manager.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
namespace InfluxDB;
3+
4+
use InvalidArgumentException;
5+
use RuntimeException;
6+
use InfluxDB\Client;
7+
8+
class Manager
9+
{
10+
private $client;
11+
private $queries;
12+
13+
public function __construct(Client $client)
14+
{
15+
$this->client = $client;
16+
$this->queries = [];
17+
}
18+
19+
public function addQuery($name, callable $query = null)
20+
{
21+
if ($query === null) {
22+
list($name, $query) = $this->fromObjectToNameCallableList($name);
23+
}
24+
25+
$this->queries[$name] = $query;
26+
}
27+
28+
private function fromObjectToNameCallableList($name)
29+
{
30+
if (is_object($name) && is_callable($name)) {
31+
if (method_exists($name, "__toString")) {
32+
return [(string)$name, $name];
33+
}
34+
}
35+
36+
throw new InvalidArgumentException("Your command should implements '__toString' method and should be a callable thing");
37+
}
38+
39+
public function __call($name, $args)
40+
{
41+
if (method_exists($this->client, $name)) {
42+
return call_user_func_array([$this->client, $name], $args);
43+
}
44+
45+
if (array_key_exists($name, $this->queries)) {
46+
$query = call_user_func_array($this->queries[$name], $args);
47+
return $this->client->query($query);
48+
}
49+
50+
throw new RuntimeException("The method you are using is not allowed: '{$name}', do you have to add it with 'addQuery'");
51+
}
52+
}

src/Query/CreateDatabase.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
namespace InfluxDB\Query;
3+
4+
class CreateDatabase
5+
{
6+
public function __invoke($name)
7+
{
8+
return "CREATE DATABASE \"" . addslashes($name) . "\"";
9+
}
10+
11+
public function __toString()
12+
{
13+
return "createDatabase";
14+
}
15+
}

src/Query/DeleteDatabase.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
namespace InfluxDB\Query;
3+
4+
class DeleteDatabase
5+
{
6+
public function __invoke($name)
7+
{
8+
return "DROP DATABASE \"" . addslashes($name) . "\"";
9+
}
10+
11+
public function __toString()
12+
{
13+
return "deleteDatabase";
14+
}
15+
}
16+

src/Query/GetDatabases.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
namespace InfluxDB\Query;
3+
4+
class GetDatabases
5+
{
6+
public function __invoke()
7+
{
8+
return "show databases";
9+
}
10+
11+
public function __toString()
12+
{
13+
return "getDatabases";
14+
}
15+
}
16+
17+

tests/integration/ClientTest.php

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -70,49 +70,6 @@ public function testDirectMessagesMarkPublicSignature()
7070
$this->assertValueExistsInSerie("tcp.test", "tt", "mem", 2);
7171
}
7272

73-
public function testListActiveDatabases()
74-
{
75-
$options = new Options();
76-
$guzzleHttp = new GuzzleHttpClient();
77-
$writer = new Writer($guzzleHttp, $options);
78-
$reader = new Reader($guzzleHttp, $options);
79-
$client = new Client($reader, $writer);
80-
81-
$databases = $client->getDatabases();
82-
83-
$this->assertCount(2, $databases["results"][0]["series"][0]["values"]);
84-
}
85-
86-
public function testCreateANewDatabase()
87-
{
88-
$options = new Options();
89-
$guzzleHttp = new GuzzleHttpClient();
90-
$writer = new Writer($guzzleHttp, $options);
91-
$reader = new Reader($guzzleHttp, $options);
92-
$client = new Client($reader, $writer);
93-
94-
$client->createDatabase("walter");
95-
96-
$databases = $client->getDatabases();
97-
98-
$this->assertCount(3, $databases["results"][0]["series"][0]["values"]);
99-
}
100-
101-
public function testDropExistingDatabase()
102-
{
103-
$options = new Options();
104-
$guzzleHttp = new GuzzleHttpClient();
105-
$writer = new Writer($guzzleHttp, $options);
106-
$reader = new Reader($guzzleHttp, $options);
107-
$client = new Client($reader, $writer);
108-
109-
$client->createDatabase("walter");
110-
$this->assertDatabasesCount(3);
111-
112-
$client->deleteDatabase("walter");
113-
$this->assertDatabasesCount(2);
114-
}
115-
11673
/**
11774
* Test that we handle socket problems correctly in the UDP
11875
* adapter, and that they don't inturrupt the user's application.

tests/integration/Framework/TestCase.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33

44
use GuzzleHttp\Client as GuzzleHttpClient;
55
use InfluxDB\Client;
6+
use InfluxDB\Manager;
67
use InfluxDB\Adapter\Http\Options as HttpOptions;
78
use InfluxDB\Adapter\Http\Writer;
89
use InfluxDB\Adapter\Http\Reader;
10+
use InfluxDB\Query\CreateDatabase;
11+
use InfluxDB\Query\DeleteDatabase;
12+
use InfluxDB\Query\GetDatabases;
913

1014
class TestCase extends \PHPUnit_Framework_TestCase
1115
{
@@ -19,7 +23,11 @@ public function setUp()
1923
$writer = new Writer($guzzleHttp, $options);
2024
$reader = new Reader($guzzleHttp, $options);
2125

22-
$client = $this->client = new Client($reader, $writer);
26+
$client = $this->client = new Manager(new Client($reader, $writer));
27+
28+
$client->addQuery(new CreateDatabase());
29+
$client->addQuery(new DeleteDatabase());
30+
$client->addQuery(new GetDatabases());
2331

2432
$this->dropAll();
2533
}
@@ -78,7 +86,12 @@ public function assertSerieExists($database, $serieName)
7886
public function assertDatabasesCount($count)
7987
{
8088
$databases = $this->client->getDatabases();
81-
$this->assertCount($count, $databases["results"][0]["series"][0]["values"]);
89+
$databaseList = [];
90+
if (array_key_exists("values", $databases["results"][0]["series"][0])) {
91+
$databaseList = $databases["results"][0]["series"][0]["values"];
92+
}
93+
94+
$this->assertCount($count, $databaseList);
8295
}
8396

8497
public function getOptions()

tests/integration/ManagerTest.php

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
namespace InfluxDB\Integration;
3+
4+
use InfluxDB\Adapter\Http\Options;
5+
use InfluxDB\Adapter\Http\Writer;
6+
use InfluxDB\Adapter\Http\Reader;
7+
use InfluxDB\Client;
8+
use InfluxDB\Query\CreateDatabase;
9+
use InfluxDB\Query\DeleteDatabase;
10+
use InfluxDB\Query\GetDatabases;
11+
use GuzzleHttp\Client as GuzzleHttpClient;
12+
use InfluxDB\Manager;
13+
use InfluxDB\Integration\Framework\TestCase;
14+
15+
class ManagerTest extends TestCase
16+
{
17+
public function testCreateANewDatabase()
18+
{
19+
$options = new Options();
20+
$guzzleHttp = new GuzzleHttpClient();
21+
$writer = new Writer($guzzleHttp, $options);
22+
$reader = new Reader($guzzleHttp, $options);
23+
$client = new Client($reader, $writer);
24+
$manager = new Manager($client);
25+
26+
$manager->addQuery(new CreateDatabase());
27+
$manager->addQuery(new DeleteDatabase());
28+
$manager->addQuery(new GetDatabases());
29+
30+
$manager->createDatabase("one");
31+
$manager->createDatabase("two");
32+
$manager->createDatabase("walter");
33+
34+
$databases = $manager->getDatabases();
35+
36+
$this->assertCount(3, $databases["results"][0]["series"][0]["values"]);
37+
}
38+
39+
public function testDropExistingDatabase()
40+
{
41+
$options = new Options();
42+
$guzzleHttp = new GuzzleHttpClient();
43+
$writer = new Writer($guzzleHttp, $options);
44+
$reader = new Reader($guzzleHttp, $options);
45+
$client = new Client($reader, $writer);
46+
$manager = new Manager($client);
47+
48+
$manager->addQuery(new CreateDatabase());
49+
$manager->addQuery(new DeleteDatabase());
50+
$manager->addQuery(new GetDatabases());
51+
52+
$manager->createDatabase("walter");
53+
$this->assertDatabasesCount(1);
54+
55+
$manager->deleteDatabase("walter");
56+
$this->assertDatabasesCount(0);
57+
}
58+
59+
public function testListActiveDatabases()
60+
{
61+
$options = new Options();
62+
$guzzleHttp = new GuzzleHttpClient();
63+
$writer = new Writer($guzzleHttp, $options);
64+
$reader = new Reader($guzzleHttp, $options);
65+
$client = new Client($reader, $writer);
66+
$manager = new Manager($client);
67+
68+
$manager->addQuery(new CreateDatabase());
69+
$manager->addQuery(new DeleteDatabase());
70+
$manager->addQuery(new GetDatabases());
71+
72+
$manager->createDatabase("one");
73+
$manager->createDatabase("two");
74+
75+
$databases = $manager->getDatabases();
76+
77+
$this->assertCount(2, $databases["results"][0]["series"][0]["values"]);
78+
}
79+
}

0 commit comments

Comments
 (0)