@mark1russell7/harness 0.11.4 → 0.11.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/schema.d.ts
CHANGED
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
// - ready: the reply to the first query: the connection is idle in the pool (idle, inflight), or
|
|
17
17
|
// the stream starts (stream).
|
|
18
18
|
// - sent, ack, fail: each query by its sequence number, with its error.
|
|
19
|
-
// - data, error: the end of the query in flight, as the TCP client of the harness tells it.
|
|
19
|
+
// - data, error: the end of the query in flight, as the TCP client of the harness tells it. In idle
|
|
20
|
+
// mode, the close of the socket of the first connection is an error line too: the pool closed it.
|
|
20
21
|
// - done, deadline: the end of the client.
|
|
21
22
|
//
|
|
22
23
|
// The modes are those of the pg client. idle sends one query, closes its connection (the
|
|
@@ -60,6 +61,7 @@ public final class ClientHikari {
|
|
|
60
61
|
private static volatile boolean stopped = false;
|
|
61
62
|
private static volatile HikariDataSource pool;
|
|
62
63
|
private static volatile String connected;
|
|
64
|
+
private static volatile Socket observed;
|
|
63
65
|
private static String host;
|
|
64
66
|
private static String port;
|
|
65
67
|
private static String query;
|
|
@@ -216,8 +218,8 @@ public final class ClientHikari {
|
|
|
216
218
|
|
|
217
219
|
// ---- each connection that the client borrows: its socket, read from pgjdbc
|
|
218
220
|
|
|
219
|
-
/** This function gives the
|
|
220
|
-
private static
|
|
221
|
+
/** This function gives the socket of a connection, from the PGStream of pgjdbc, or null. */
|
|
222
|
+
private static Socket socketOf(Connection connection) {
|
|
221
223
|
try {
|
|
222
224
|
PgConnection pg = connection.unwrap(PgConnection.class);
|
|
223
225
|
Object executor = pg.getQueryExecutor();
|
|
@@ -231,23 +233,50 @@ public final class ClientHikari {
|
|
|
231
233
|
}
|
|
232
234
|
if (field == null) return null;
|
|
233
235
|
field.setAccessible(true);
|
|
234
|
-
|
|
235
|
-
return socket.getLocalAddress().getHostAddress() + ":" + socket.getLocalPort();
|
|
236
|
+
return ((PGStream) field.get(executor)).getSocket();
|
|
236
237
|
} catch (Exception error) {
|
|
237
238
|
return null;
|
|
238
239
|
}
|
|
239
240
|
}
|
|
240
241
|
|
|
241
242
|
private static void seen(Connection connection) {
|
|
242
|
-
|
|
243
|
-
if (
|
|
243
|
+
Socket socket = socketOf(connection);
|
|
244
|
+
if (socket == null) return;
|
|
245
|
+
String local = socket.getLocalAddress().getHostAddress() + ":" + socket.getLocalPort();
|
|
246
|
+
if (!SEEN.add(local)) return;
|
|
244
247
|
emit("socket", "\"role\":\"pool\",\"local\":" + q(local));
|
|
245
248
|
if (connected == null) {
|
|
246
249
|
connected = local;
|
|
250
|
+
observed = socket;
|
|
247
251
|
emit("connected", "\"local\":" + q(local));
|
|
248
252
|
}
|
|
249
253
|
}
|
|
250
254
|
|
|
255
|
+
/**
|
|
256
|
+
* This function watches the socket of the first connection in idle mode, each 2 ms. The pool
|
|
257
|
+
* closes it when a check finds it dead: pgjdbc closes the socket after a read timeout or an I/O
|
|
258
|
+
* error. That close is the detection of an idle cell, thus it writes an error line.
|
|
259
|
+
*/
|
|
260
|
+
private static void watchIdle() {
|
|
261
|
+
Socket socket = observed;
|
|
262
|
+
if (socket == null) return;
|
|
263
|
+
Thread watcher = new Thread(() -> {
|
|
264
|
+
while (!stopped) {
|
|
265
|
+
if (socket.isClosed()) {
|
|
266
|
+
emit("error", "\"errno\":\"CLOSED\",\"local\":" + q(connected));
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
Thread.sleep(2);
|
|
271
|
+
} catch (InterruptedException stop) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}, "idle-watcher");
|
|
276
|
+
watcher.setDaemon(true);
|
|
277
|
+
watcher.start();
|
|
278
|
+
}
|
|
279
|
+
|
|
251
280
|
// ---- the counts of the pool, each 5 ms: a line for each change
|
|
252
281
|
|
|
253
282
|
private static void watchPool() {
|
|
@@ -413,6 +442,7 @@ public final class ClientHikari {
|
|
|
413
442
|
}
|
|
414
443
|
// the connection went back to the pool at the end of the query: it is idle there
|
|
415
444
|
emit("ready", "\"reply\":\"ack\"");
|
|
445
|
+
if (mode.equals("idle")) watchIdle();
|
|
416
446
|
if (mode.equals("inflight")) {
|
|
417
447
|
while (!Files.exists(go)) Thread.sleep(2);
|
|
418
448
|
Throwable error = operate(2);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@mark1russell7/harness",
|
|
4
|
-
"version": "0.11.
|
|
4
|
+
"version": "0.11.5",
|
|
5
5
|
"description": "A fault-injection harness for connection timers: a cell runs a client against a stock target in Docker, through a topology of routers and proxies, a replicated group under Sentinels or a replica set, injects a fault, measures the kernel's own records and judges a prediction. HTTP clients of Go, Node and undici race the keep-alive of a Node server, and the MongoDB driver meets the faults of a replica set. The WebSocket client of @procedures/client drops a silent connection on its own heartbeat, and the harness times that detection and the reconnect from the program's lines and the kernel's stamps.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"fault-injection",
|