@@ -9,6 +9,7 @@ built on top of [ReactPHP](https://reactphp.org/).
99* [ Usage] ( #usage )
1010 * [ Factory] ( #factory )
1111 * [ open()] ( #open )
12+ * [ openLazy()] ( #openlazy )
1213 * [ DatabaseInterface] ( #databaseinterface )
1314 * [ exec()] ( #exec )
1415 * [ query()] ( #query )
@@ -31,24 +32,18 @@ existing SQLite database file (or automatically create it on first run) and then
3132$loop = React\EventLoop\Factory::create();
3233$factory = new Clue\React\SQLite\Factory($loop);
3334
35+ $db = $factory->openLazy('users.db');
36+ $db->exec('CREATE TABLE IF NOT EXISTS foo (id INTEGER PRIMARY KEY AUTOINCREMENT, bar STRING)');
37+
3438$name = 'Alice';
35- $factory->open('users.db')->then(
36- function (Clue\React\SQLite\DatabaseInterface $db) use ($name) {
37- $db->exec('CREATE TABLE IF NOT EXISTS foo (id INTEGER PRIMARY KEY AUTOINCREMENT, bar STRING)');
38-
39- $db->query('INSERT INTO foo (bar) VALUES (?)', array($name))->then(
40- function (Clue\React\SQLite\Result $result) use ($name) {
41- echo 'New ID for ' . $name . ': ' . $result->insertId . PHP_EOL;
42- }
43- );
44-
45- $db->quit();
46- },
47- function (Exception $e) {
48- echo 'Error: ' . $e->getMessage() . PHP_EOL;
39+ $db->query('INSERT INTO foo (bar) VALUES (?)', [$name])->then(
40+ function (Clue\React\SQLite\Result $result) use ($name) {
41+ echo 'New ID for ' . $name . ': ' . $result->insertId . PHP_EOL;
4942 }
5043);
5144
45+ $db->quit();
46+
5247$loop->run();
5348```
5449
@@ -101,6 +96,75 @@ $factory->open('users.db', SQLITE3_OPEN_READONLY)->then(function (DatabaseInterf
10196});
10297```
10398
99+ #### openLazy()
100+
101+ The ` openLazy(string $filename, int $flags = null, array $options = []): DatabaseInterface ` method can be used to
102+ open a new database connection for the given SQLite database file.
103+
104+ ``` php
105+ $db = $factory->openLazy('users.db');
106+
107+ $db->query('INSERT INTO users (name) VALUES ("test")');
108+ $db->quit();
109+ ```
110+
111+ This method immediately returns a "virtual" connection implementing the
112+ [ ` DatabaseInterface ` ] ( #databaseinterface ) that can be used to
113+ interface with your SQLite database. Internally, it lazily creates the
114+ underlying database process only on demand once the first request is
115+ invoked on this instance and will queue all outstanding requests until
116+ the underlying database is ready. Additionally, it will only keep this
117+ underlying database in an "idle" state for 60s by default and will
118+ automatically end the underlying database when it is no longer needed.
119+
120+ From a consumer side this means that you can start sending queries to the
121+ database right away while the underlying database process may still be
122+ outstanding. Because creating this underlying process may take some
123+ time, it will enqueue all oustanding commands and will ensure that all
124+ commands will be executed in correct order once the database is ready.
125+ In other words, this "virtual" database behaves just like a "real"
126+ database as described in the ` DatabaseInterface ` and frees you from
127+ having to deal with its async resolution.
128+
129+ If the underlying database process fails, it will reject all
130+ outstanding commands and will return to the initial "idle" state. This
131+ means that you can keep sending additional commands at a later time which
132+ will again try to open a new underlying database. Note that this may
133+ require special care if you're using transactions that are kept open for
134+ longer than the idle period.
135+
136+ Note that creating the underlying database will be deferred until the
137+ first request is invoked. Accordingly, any eventual connection issues
138+ will be detected once this instance is first used. You can use the
139+ ` quit() ` method to ensure that the "virtual" connection will be soft-closed
140+ and no further commands can be enqueued. Similarly, calling ` quit() ` on
141+ this instance when not currently connected will succeed immediately and
142+ will not have to wait for an actual underlying connection.
143+
144+ Depending on your particular use case, you may prefer this method or the
145+ underlying ` open() ` method which resolves with a promise. For many
146+ simple use cases it may be easier to create a lazy connection.
147+
148+ The optional ` $flags ` parameter is used to determine how to open the
149+ SQLite database. By default, open uses ` SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE ` .
150+
151+ ``` php
152+ $db = $factory->openLazy('users.db', SQLITE3_OPEN_READONLY);
153+ ```
154+
155+ By default, this method will keep "idle" connection open for 60s and will
156+ then end the underlying connection. The next request after an "idle"
157+ connection ended will automatically create a new underlying connection.
158+ This ensure you always get a "fresh" connection and as such should not be
159+ confused with a "keepalive" or "heartbeat" mechanism, as this will not
160+ actively try to probe the connection. You can explicitly pass a custom
161+ idle timeout value in seconds (or use a negative number to not apply a
162+ timeout) like this:
163+
164+ ``` php
165+ $db = $factory->openLazy('users.db', null, ['idle' => 0.1]);
166+ ```
167+
104168### DatabaseInterface
105169
106170The ` DatabaseInterface ` represents a connection that is responsible for
@@ -149,7 +213,7 @@ method instead.
149213
150214#### query()
151215
152- The ` query(string $query, array $params = array() ): PromiseInterface<Result> ` method can be used to
216+ The ` query(string $query, array $params = [] ): PromiseInterface<Result> ` method can be used to
153217perform an async query.
154218
155219
0 commit comments