@@ -9,6 +9,7 @@ built on top of [ReactPHP](https://reactphp.org/).
9
9
* [ Usage] ( #usage )
10
10
* [ Factory] ( #factory )
11
11
* [ open()] ( #open )
12
+ * [ openLazy()] ( #openlazy )
12
13
* [ DatabaseInterface] ( #databaseinterface )
13
14
* [ exec()] ( #exec )
14
15
* [ query()] ( #query )
@@ -31,24 +32,18 @@ existing SQLite database file (or automatically create it on first run) and then
31
32
$loop = React\EventLoop\Factory::create();
32
33
$factory = new Clue\React\SQLite\Factory($loop);
33
34
35
+ $db = $factory->openLazy('users.db');
36
+ $db->exec('CREATE TABLE IF NOT EXISTS foo (id INTEGER PRIMARY KEY AUTOINCREMENT, bar STRING)');
37
+
34
38
$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;
49
42
}
50
43
);
51
44
45
+ $db->quit();
46
+
52
47
$loop->run();
53
48
```
54
49
@@ -101,6 +96,75 @@ $factory->open('users.db', SQLITE3_OPEN_READONLY)->then(function (DatabaseInterf
101
96
});
102
97
```
103
98
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
+
104
168
### DatabaseInterface
105
169
106
170
The ` DatabaseInterface ` represents a connection that is responsible for
@@ -149,7 +213,7 @@ method instead.
149
213
150
214
#### query()
151
215
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
153
217
perform an async query.
154
218
155
219
0 commit comments