camusdb 0.5.0 → 0.7.0

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.
Files changed (104) hide show
  1. package/README.md +207 -5
  2. package/dist/client.d.ts +42 -37
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +117 -166
  5. package/dist/client.js.map +1 -1
  6. package/dist/config.d.ts +22 -0
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +19 -0
  9. package/dist/config.js.map +1 -1
  10. package/dist/endpoint-pool.d.ts +8 -0
  11. package/dist/endpoint-pool.d.ts.map +1 -1
  12. package/dist/endpoint-pool.js +25 -0
  13. package/dist/endpoint-pool.js.map +1 -1
  14. package/dist/index.d.ts +6 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +4 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/json.d.ts +4 -3
  19. package/dist/json.d.ts.map +1 -1
  20. package/dist/json.js +10 -4
  21. package/dist/json.js.map +1 -1
  22. package/dist/node-stats.d.ts +113 -0
  23. package/dist/node-stats.d.ts.map +1 -0
  24. package/dist/node-stats.js +90 -0
  25. package/dist/node-stats.js.map +1 -0
  26. package/dist/options.d.ts +10 -0
  27. package/dist/options.d.ts.map +1 -1
  28. package/dist/options.js +1 -0
  29. package/dist/options.js.map +1 -1
  30. package/dist/pipeline.d.ts +126 -0
  31. package/dist/pipeline.d.ts.map +1 -0
  32. package/dist/pipeline.js +363 -0
  33. package/dist/pipeline.js.map +1 -0
  34. package/dist/prepared/auto-prepare.d.ts +51 -0
  35. package/dist/prepared/auto-prepare.d.ts.map +1 -0
  36. package/dist/prepared/auto-prepare.js +150 -0
  37. package/dist/prepared/auto-prepare.js.map +1 -0
  38. package/dist/prepared/policy.d.ts +7 -0
  39. package/dist/prepared/policy.d.ts.map +1 -1
  40. package/dist/prepared/policy.js +16 -0
  41. package/dist/prepared/policy.js.map +1 -1
  42. package/dist/query-stream.d.ts +4 -1
  43. package/dist/query-stream.d.ts.map +1 -1
  44. package/dist/query-stream.js +13 -2
  45. package/dist/query-stream.js.map +1 -1
  46. package/dist/retry.d.ts +8 -0
  47. package/dist/retry.d.ts.map +1 -1
  48. package/dist/retry.js +12 -1
  49. package/dist/retry.js.map +1 -1
  50. package/dist/statements.d.ts.map +1 -1
  51. package/dist/statements.js +37 -4
  52. package/dist/statements.js.map +1 -1
  53. package/dist/telemetry.d.ts +199 -0
  54. package/dist/telemetry.d.ts.map +1 -0
  55. package/dist/telemetry.js +422 -0
  56. package/dist/telemetry.js.map +1 -0
  57. package/dist/transaction.d.ts +60 -5
  58. package/dist/transaction.d.ts.map +1 -1
  59. package/dist/transaction.js +124 -24
  60. package/dist/transaction.js.map +1 -1
  61. package/dist/transport/authenticating-transport.d.ts +9 -1
  62. package/dist/transport/authenticating-transport.d.ts.map +1 -1
  63. package/dist/transport/authenticating-transport.js +13 -0
  64. package/dist/transport/authenticating-transport.js.map +1 -1
  65. package/dist/transport/grpc/batch-frames.d.ts +23 -5
  66. package/dist/transport/grpc/batch-frames.d.ts.map +1 -1
  67. package/dist/transport/grpc/batch-frames.js +29 -8
  68. package/dist/transport/grpc/batch-frames.js.map +1 -1
  69. package/dist/transport/grpc/batcher.d.ts +69 -5
  70. package/dist/transport/grpc/batcher.d.ts.map +1 -1
  71. package/dist/transport/grpc/batcher.js +217 -10
  72. package/dist/transport/grpc/batcher.js.map +1 -1
  73. package/dist/transport/grpc/grpc-transport.d.ts +35 -1
  74. package/dist/transport/grpc/grpc-transport.d.ts.map +1 -1
  75. package/dist/transport/grpc/grpc-transport.js +193 -7
  76. package/dist/transport/grpc/grpc-transport.js.map +1 -1
  77. package/dist/transport/grpc/messages.d.ts +15 -0
  78. package/dist/transport/grpc/messages.d.ts.map +1 -1
  79. package/dist/transport/grpc/messages.js +9 -0
  80. package/dist/transport/grpc/messages.js.map +1 -1
  81. package/dist/transport/ndjson-row-source.d.ts +2 -0
  82. package/dist/transport/ndjson-row-source.d.ts.map +1 -1
  83. package/dist/transport/ndjson-row-source.js +7 -4
  84. package/dist/transport/ndjson-row-source.js.map +1 -1
  85. package/dist/transport/rest-decode.d.ts +14 -4
  86. package/dist/transport/rest-decode.d.ts.map +1 -1
  87. package/dist/transport/rest-decode.js +56 -17
  88. package/dist/transport/rest-decode.js.map +1 -1
  89. package/dist/transport/rest-transport.d.ts +9 -1
  90. package/dist/transport/rest-transport.d.ts.map +1 -1
  91. package/dist/transport/rest-transport.js +24 -0
  92. package/dist/transport/rest-transport.js.map +1 -1
  93. package/dist/transport/sequential-pipeline.d.ts +21 -0
  94. package/dist/transport/sequential-pipeline.d.ts.map +1 -0
  95. package/dist/transport/sequential-pipeline.js +119 -0
  96. package/dist/transport/sequential-pipeline.js.map +1 -0
  97. package/dist/transport/transport.d.ts +94 -0
  98. package/dist/transport/transport.d.ts.map +1 -1
  99. package/dist/transport/transport.js +10 -0
  100. package/dist/transport/transport.js.map +1 -1
  101. package/dist/values/encode.js +13 -5
  102. package/dist/values/encode.js.map +1 -1
  103. package/package.json +10 -4
  104. package/proto/camus_sql.proto +114 -0
package/README.md CHANGED
@@ -12,6 +12,9 @@ The gRPC transport needs two more packages. Install them only if you use it:
12
12
  npm install @grpc/grpc-js @grpc/proto-loader
13
13
  ```
14
14
 
15
+ Traces and metrics need `@opentelemetry/api`. Install it only if you collect them. See
16
+ [OpenTelemetry](#opentelemetry).
17
+
15
18
  **Requirements**: Node.js 20.19 or later, or 22.12 or later. The package ships as ECMAScript
16
19
  modules with TypeScript declarations.
17
20
 
@@ -36,8 +39,10 @@ modules with TypeScript declarations.
36
39
  - [Databases and branches](#databases-and-branches)
37
40
  - [The query result cache](#the-query-result-cache)
38
41
  - [Backups](#backups)
42
+ - [Node stats](#node-stats)
39
43
  - [Errors](#errors)
40
44
  - [Cancellation and deadlines](#cancellation-and-deadlines)
45
+ - [OpenTelemetry](#opentelemetry)
41
46
  - [What a client shares](#what-a-client-shares)
42
47
  - [Security notes](#security-notes)
43
48
  - [Development](#development)
@@ -119,6 +124,7 @@ const b = CamusClient.fromConnectionString('Endpoint=http://localhost:8082;Datab
119
124
  | `coalescingDelayMs` | `CoalescingDelay` | No | gRPC only: milliseconds. Default `0`, which is off. |
120
125
  | `requestFrames` | `RequestFrames` | No | gRPC only: pack the operations that wait together into one stream message. Default `true`. |
121
126
  | `streamDrainTimeoutMs` | `StreamDrainTimeout` | No | gRPC only: milliseconds a rotated-out stream stays open for its transactions. Default `300000`. |
127
+ | `httpVersion` | `HttpVersion` | No | The highest HTTP version for REST calls. Only `1.1` (the default) is accepted. See the note below. |
122
128
  | `backupEndpoint` | `BackupEndpoint` | No | The HTTP endpoint for the backup admin API. Required with `grpc`. |
123
129
  | `backupTimeoutSeconds` | `BackupTimeout` | No | The backup request timeout in seconds. Default `300`. |
124
130
  | `allowInsecureCredentials` | `AllowInsecureCredentials` | No | Waives the refusal to send credentials to a remote plaintext endpoint. |
@@ -127,6 +133,13 @@ const b = CamusClient.fromConnectionString('Endpoint=http://localhost:8082;Datab
127
133
  | `routingMaxHintAgeMs` | `RoutingMaxHintAge` | No | The ceiling on how long a learned route is reused. Default `5000`. |
128
134
  | `defaultTransactionOptions` | `IsolationLevel`, `TransactionMode`, `Locking` | No | Concurrency defaults for every transaction and autocommit statement. |
129
135
  | `int64` | `Int64` | No | `auto` (the default), `number`, or `bigint`. See [Types](#types). |
136
+ | `traceQueryText` | `TraceQueryText` | No | Put the SQL text on the driver's spans as `db.query.text`. Default `false`. See [OpenTelemetry](#opentelemetry). |
137
+
138
+ **`HttpVersion`.** The .NET driver reads `HttpVersion=1.1|2|3` and can send REST calls over HTTP/2
139
+ or HTTP/3. Node's `fetch` sends HTTP/1.1 only. So this driver accepts `1.1`, and it refuses `2` and
140
+ `3` (also `2.0` and `3.0`) with a `CamusError` when the client is built. Remove the key, or set it
141
+ to `1.1`, in a connection string that you share with a .NET service. Any other value reads as `1.1`,
142
+ as in .NET. The key does not apply to `protocol: 'grpc'`, which always uses HTTP/2.
130
143
 
131
144
  ### How a connection string is parsed
132
145
 
@@ -223,15 +236,15 @@ change what the statement means.
223
236
  | --- | --- |
224
237
  | `null`, `undefined` | `Null` |
225
238
  | `boolean` | `Bool` |
226
- | `number` that is an integer | `Integer64` |
227
- | `number` that is not | `Float64` |
239
+ | `number` that is an integer, other than `-0` | `Integer64` |
240
+ | `number` that is not, and `-0` | `Float64` |
228
241
  | `bigint` | `Integer64` |
229
242
  | `string` | `String` |
230
243
  | `Date` | `DateTime` |
231
244
  | `Uint8Array`, `Buffer`, `ArrayBuffer` | `Bytes` |
232
245
  | `Float32Array` | `Bytes`, packed as a vector |
233
246
  | `CamusObjectId` | `Id` |
234
- | an array | `Array`, with the element type read from the first element that is not null. When that element is a whole `number` and another `number` element is not whole, the element type is `Float64`. |
247
+ | an array | `Array`, with the element type read from the first element that is not null. When that element is a whole `number` and another `number` element is not whole or is `-0`, the element type is `Float64`. |
235
248
 
236
249
  A UUID-shaped string is **not** read as a `uuid`. A 36-character string that happens to look like
237
250
  one would otherwise change type silently.
@@ -297,6 +310,15 @@ against an `OID` column. `camus.array(uuids, ColumnType.Id)` therefore sends a `
297
310
  | `Numeric` | `string`, the exact decimal text — see [NUMERIC](#numeric) |
298
311
  | `Array` | an array of the values above |
299
312
 
313
+ A `Float32` value is the single-precision number the server stored, on both transports. A negative
314
+ zero keeps its sign in both directions.
315
+
316
+ An array element reads as its element type on both transports. Over REST the driver reads that type
317
+ from the `elementType` field of the result's `columns`. An older server does not send the field. A
318
+ `Date`, `DateTime`, or `Bytes` element then reads as its wire value: the tick count as a number or
319
+ a `bigint`, and the bytes as base64 text. A `Float64` array whose numbers are all whole reads them
320
+ as integers. Use gRPC, or a newer server, when you read such arrays.
321
+
300
322
  ### 64-bit integers
301
323
 
302
324
  CamusDB is a 64-bit database, and a JavaScript number stops being able to name every integer above
@@ -564,8 +586,8 @@ A server from 0.13.2 on has sequences. A sequence stores `int64` values only, ha
564
586
  increment, and never cycles. The server refuses `CYCLE` with `CADB0533`, because a counter that
565
587
  wraps would issue again the values that committed rows already hold.
566
588
 
567
- `CREATE SEQUENCE`, `ALTER SEQUENCE`, and `DROP SEQUENCE` go to the DDL route. Two helpers compose
568
- the create and the drop statements:
589
+ `CREATE SEQUENCE`, `ALTER SEQUENCE`, `DROP SEQUENCE`, and `COMMENT ON SEQUENCE` go to the DDL
590
+ route. Two helpers compose the create and the drop statements:
569
591
 
570
592
  ```ts
571
593
  import { createSequenceStatement, dropSequenceStatement, nextValueExpression } from 'camusdb';
@@ -684,6 +706,10 @@ await client.transaction(work, {
684
706
  - **`locking`** — `Pessimistic` (the default) takes locks up front. `Optimistic` stages the writes
685
707
  and detects a conflict only at commit; a losing transaction fails its commit and must be retried.
686
708
  It does not protect against phantoms.
709
+ - **`deferBegin`** — `true` sends `BEGIN` with the first statement, and not from
710
+ `beginTransaction`. When that first statement is a pipeline send, `BEGIN` travels inside the same
711
+ exchange. With learned routing on, `BEGIN` is deferred already. The transaction identity reads as
712
+ zero until the first statement, and a failure to begin comes from that statement.
687
713
 
688
714
  Every knob is optional. A knob left unset falls back to the client's `defaultTransactionOptions`,
689
715
  then to the connection-string defaults, then to the server default.
@@ -697,6 +723,63 @@ dead, so the driver re-issues the **same** commit on the **same** handle, backin
697
723
  times. It never replays the work from the start, because that could apply an already-durable commit
698
724
  a second time. This is handled inside the driver; you do not write it.
699
725
 
726
+ ### Pipelined transactions
727
+
728
+ A transaction that awaits each statement pays one round trip for each statement: six for a bank
729
+ transfer (`BEGIN`, two reads, two writes, `COMMIT`). At high concurrency, those round trips set the
730
+ latency, and the statements do not. A pipeline sends the statements whose inputs are known as one
731
+ stream message, and it settles the promise of each statement from its own answer.
732
+
733
+ ```ts
734
+ const txn = await client.beginTransaction({
735
+ locking: CamusLocking.Optimistic,
736
+ deferBegin: true, // BEGIN travels inside the first send
737
+ });
738
+
739
+ const pipeline = txn.pipeline();
740
+
741
+ // Exchange 1: [BEGIN, SELECT a, SELECT b]
742
+ const readA = pipeline.query<{ balance: number }>('SELECT balance FROM accounts WHERE id = @id', { id: a });
743
+ const readB = pipeline.query<{ balance: number }>('SELECT balance FROM accounts WHERE id = @id', { id: b });
744
+ await pipeline.send();
745
+
746
+ const fromBalance = (await readA).rows[0]!.balance;
747
+ const toBalance = (await readB).rows[0]!.balance;
748
+
749
+ // Exchange 2: [UPDATE a, UPDATE b, COMMIT]. The commit happens only if both updates succeed.
750
+ pipeline.execute('UPDATE accounts SET balance = @v WHERE id = @id', { v: fromBalance - amount, id: a });
751
+ pipeline.execute('UPDATE accounts SET balance = @v WHERE id = @id', { v: toBalance + amount, id: b });
752
+ await pipeline.commit();
753
+
754
+ console.log(`${pipeline.exchanges} round trips`); // 2 over gRPC
755
+ ```
756
+
757
+ - **Results.** `query` returns the promise of a `QueryResult`, and `execute` returns the promise of
758
+ an `ExecuteResult`, as the client methods do. A write with `RETURNING` in `query` gives its rows
759
+ and `affectedRows`. `send` and `commit` also reject with the first failure, so a caller that awaits
760
+ only the send still learns of it. A queued promise that nobody awaits is never reported as an
761
+ unhandled rejection.
762
+ - **Failure.** The statements after a failed one in the same exchange still get an answer. The
763
+ transaction has ended, so they fail too, and `commit` rejects with the first failure and does not
764
+ commit. The server rolled the transaction back, so `rollback` is then a harmless call. To retry,
765
+ run the whole transaction again from `BEGIN`, as for any failed statement.
766
+ - **Commit.** After a successful `pipeline.commit()`, the transaction is committed. A later
767
+ `txn.rollback()` does nothing, and a later `txn.commit()` throws. Inside `client.transaction`, the
768
+ helper sees the pipeline commit and does not commit a second time.
769
+ - **Order.** The queued statements run in queue order, after every statement of the transaction
770
+ sent before them. A pipeline can be sent more than once on one transaction, and an ordinary
771
+ statement can run between two sends. One send at a time for each pipeline.
772
+ - **Exchanges.** `pipeline.exchanges` gives the round trips used. Over gRPC, to a server that
773
+ announces frame contract version 2 or higher, it is one for each send. Over REST, with
774
+ `requestFrames: false`, or against an older server, the driver runs the same statements one
775
+ exchange per step, with the same results, and the count shows it. The driver never sends an
776
+ older server something that it could misread.
777
+ - **Routing.** With learned routing on, a pipelined statement asks for routing advice, and the
778
+ driver learns the route from its reply, as for a lone statement. So the next deferred transaction
779
+ begins on the node that the advice names.
780
+ - **What cannot be queued.** DDL, which does not run inside the transaction, and `TRUNCATE`. These
781
+ throw a `CamusError` at queue time, and the pipeline stays usable.
782
+
700
783
  ---
701
784
 
702
785
  ## Retries
@@ -836,6 +919,10 @@ frame, and the fixed cost of a message is paid once instead of six times. A fram
836
919
  more statements. A lone statement stays a plain single message, and a server that does not announce
837
920
  frames never receives one. Set `requestFrames` to `false` to turn frames off.
838
921
 
922
+ A whole transaction can travel as one frame too: a pipeline puts the `BEGIN`, the statements, and a
923
+ conditional commit in one stream message. That needs a server that announces frame contract version
924
+ 2. See [Pipelined transactions](#pipelined-transactions).
925
+
839
926
  A stream carries its bearer token once, in the metadata it opens with, and gRPC gives no way to
840
927
  change it later. The token provider renews the token every few minutes, so a long-lived stream
841
928
  outlives the token it presented. Whether a server tolerates that is the server's decision. The
@@ -1057,6 +1144,39 @@ HTTP endpoint; the driver refuses to guess rather than send HTTP at a gRPC port.
1057
1144
 
1058
1145
  ---
1059
1146
 
1147
+ ## Node stats
1148
+
1149
+ `client.nodeStats()` returns the disk, CPU, and memory of one node. It works over REST
1150
+ (`GET /v1/admin/stats`) and gRPC (`GetNodeStats`).
1151
+
1152
+ ```ts
1153
+ const stats = await client.nodeStats(); // the next endpoint in the rotation
1154
+ const data = stats.dataVolume!; // the volume that holds data_dir
1155
+
1156
+ console.log(`${data.availableBytes} bytes free of ${data.totalBytes}`);
1157
+ console.log(`writes refused (below min_free_disk_bytes): ${data.belowWatermark}`);
1158
+
1159
+ for (const endpoint of client.endpoints) {
1160
+ const node = await client.nodeStats(endpoint); // one call for each node of a cluster
1161
+ console.log(`${node.address}: ${node.cpu.processCpuPercent}% CPU, ${node.memory.hostAvailableBytes} bytes free`);
1162
+ }
1163
+ ```
1164
+
1165
+ - **Each node answers for itself.** `address` names the configured endpoint that answered.
1166
+ `nodeStats(endpoint)` accepts only an endpoint from `client.endpoints`, so the client's credentials
1167
+ never go to another address. Any other endpoint throws a `TypeError`.
1168
+ - **`-1` means unknown.** A value that the node could not read is `-1`, and `errors` names the field
1169
+ and the reason. One failed probe never fails the call. A value that an older server does not send
1170
+ is `-1` too.
1171
+ - **`belowWatermark` is the answer of the write gate.** While it is `true`, writes on that node fail
1172
+ with `CADB0536`.
1173
+ - **`MONITOR`, not superuser.** With authentication on, the account needs the superuser attribute or
1174
+ the `MONITOR` privilege: `GRANT MONITOR ON *.* TO monitoring;`. Other accounts get `CADB0517`.
1175
+ - **Cheap enough to poll.** The server answers from caches and a background sampler, so one call
1176
+ each minute from several monitors costs nothing measurable.
1177
+
1178
+ ---
1179
+
1060
1180
  ## Errors
1061
1181
 
1062
1182
  Every database-level failure is a `CamusError` carrying the server's `CADBxxxx` code.
@@ -1108,6 +1228,88 @@ not marked unreachable.
1108
1228
 
1109
1229
  ---
1110
1230
 
1231
+ ## OpenTelemetry
1232
+
1233
+ The driver reports traces and metrics through `@opentelemetry/api`, which is an optional peer
1234
+ dependency. Install it, and register an OpenTelemetry SDK as usual. The driver needs no plugin and
1235
+ no extra setting:
1236
+
1237
+ ```shell
1238
+ npm install @opentelemetry/api @opentelemetry/sdk-node
1239
+ ```
1240
+
1241
+ ```ts
1242
+ import { NodeSDK } from '@opentelemetry/sdk-node';
1243
+
1244
+ new NodeSDK({ /* exporters */ }).start();
1245
+
1246
+ // Every client reports from now on, under the instrumentation scope 'camusdb' (CAMUS_TELEMETRY_NAME).
1247
+ ```
1248
+
1249
+ Without the package, the driver reports nothing and loads nothing for telemetry. The driver loads
1250
+ the package with `require` on the first operation, so the first operation is reported too. Register
1251
+ the SDK before the first database call.
1252
+
1253
+ **Spans.** The driver records one client span for each of these operations:
1254
+
1255
+ - A statement: `query` (and so `queryOne`, `scalar`, and `nextSequenceValue`), `queryStream`,
1256
+ `execute`, `executeDdl`, `evictCache`, and `evictAllCache`.
1257
+ - A typed insert (`insert`).
1258
+ - `BEGIN`, `COMMIT`, and `ROLLBACK`. One `COMMIT` span covers all the retries of an unresolved
1259
+ commit (`CADB0509`), with one `camusdb.retry` event for each retry.
1260
+ - A pipeline exchange, as one `BATCH` span with `db.operation.batch.size` and
1261
+ `camusdb.pipeline.commit`.
1262
+
1263
+ The span name is `{operation} {target}`, for example `SELECT shop`. The target is the table for a
1264
+ typed insert, and the database for all other operations. The span has these attributes from the
1265
+ [OpenTelemetry database conventions](https://opentelemetry.io/docs/specs/semconv/database/):
1266
+
1267
+ | Attribute | Value |
1268
+ | --- | --- |
1269
+ | `db.system.name` | `camusdb` |
1270
+ | `db.namespace` | The database of the client. |
1271
+ | `db.operation.name` | The first keyword of the SQL text, if it is a known verb (`SELECT`, `INSERT`, `UPDATE`, `DELETE`, `CREATE`, `ALTER`, `DROP`, `TRUNCATE`, and others), or `BEGIN`, `COMMIT`, `ROLLBACK`, `BATCH`. |
1272
+ | `db.collection.name` | The table of a typed insert. |
1273
+ | `server.address`, `server.port` | The endpoint that received the operation, after routing. |
1274
+ | `db.query.text` | The SQL text. Only with `traceQueryText: true`. |
1275
+ | `error.type`, `db.response.status_code` | The `CADBxxxx` code of a failed operation, or the error name when there is no code. |
1276
+ | `camusdb.transport` | `rest` or `grpc`. |
1277
+
1278
+ The span is a child of the active span. While the operation runs, the driver span is the active
1279
+ span, so the HTTP or gRPC spans of the transport are its children. This needs a context manager,
1280
+ which `NodeSDK` registers.
1281
+
1282
+ **Duration metric.** The driver records the `db.client.operation.duration` histogram, in seconds,
1283
+ for the same operations. Its attributes are `db.system.name`, `db.namespace`, `db.operation.name`,
1284
+ `server.address`, `server.port`, `error.type`, and `db.response.status_code`. The SQL text is never
1285
+ an attribute.
1286
+
1287
+ **Driver metrics.** The same meter also has these metrics:
1288
+
1289
+ | Metric | Type | Attributes | What it counts |
1290
+ | --- | --- | --- | --- |
1291
+ | `camusdb.client.operation.retries` | Counter | `camusdb.retry.kind`, `error.type`, and `db.namespace` and `db.operation.name` when known | Each time the driver sends an operation again. The kinds are `finalize` (a `COMMIT` or `ROLLBACK` after `CADB0509`), `autocommit` (`withRetry`), `transaction` (`client.transaction` from `BEGIN`), `token_renewal` (a call sent again with a new token after `CADB0516`), and `create_database`. When a driver span is active, the retry is also a `camusdb.retry` event on it. |
1292
+ | `camusdb.client.endpoint.quarantines` | Counter | `server.address`, `server.port` | Each time an endpoint fails at the transport level and the driver sets it aside for 30 seconds. |
1293
+ | `camusdb.client.endpoint.quarantined` | Gauge | `server.address`, `server.port` | `1` while the endpoint is set aside, `0` while it takes traffic. |
1294
+ | `camusdb.client.prepared_statement.lookups` | Counter | `db.namespace`, `camusdb.prepared_statement.result` | Each execution of a preparable statement: `hit` (already prepared), `registered` (prepared by this execution), or `miss` (sent as SQL text). |
1295
+ | `camusdb.client.prepared_statement.registrations` | Counter | `db.namespace`, `camusdb.prepared_statement.result`, `error.type` | Each request to prepare a statement that got an answer: `success`, `refused` (the statement runs as SQL text from then on), or `unsupported` (the server has no prepared statements, so automatic preparation stops). |
1296
+ | `camusdb.client.prepared_statement.evictions` | Counter | `db.namespace` | Each prepared statement released to make room for one used more recently. See `maxAutoPrepare`. |
1297
+ | `camusdb.client.prepared_statement.count` | UpDownCounter | `db.namespace` | The statements kept prepared now. |
1298
+
1299
+ If `count` stays at `maxAutoPrepare` and `evictions` keeps growing, `maxAutoPrepare` is too small
1300
+ for the workload.
1301
+
1302
+ - **The SQL text is opt-in.** SQL text with literal values can contain sensitive data, so set
1303
+ `traceQueryText: true` (or `TraceQueryText=true`) to record it. The driver never records
1304
+ parameter values.
1305
+ - **A stream ends its span at the last row.** For `queryStream`, the span ends when the iteration
1306
+ reaches the last row, when a read fails, or when the stream is closed.
1307
+ - **A provider registered later.** The metrics API has no proxy provider, so the driver makes its
1308
+ instruments again when the global meter provider changes. Spans go through the proxy tracer of the
1309
+ API, so a tracer provider registered later gets them too.
1310
+
1311
+ ---
1312
+
1111
1313
  ## What a client shares
1112
1314
 
1113
1315
  A client holds no socket of its own. Four kinds of state are shared process-wide, keyed by what
package/dist/client.d.ts CHANGED
@@ -7,6 +7,7 @@
7
7
  import { CamusBackupClient } from './backup.js';
8
8
  import type { CamusCacheMetadata } from './cache.js';
9
9
  import type { CamusClientOptions, CamusProtocol, ResolvedConfig } from './config.js';
10
+ import type { CamusNodeStats } from './node-stats.js';
10
11
  import type { CamusTransactionOptions } from './options.js';
11
12
  import { CamusQueryStream } from './query-stream.js';
12
13
  import type { CamusColumn } from './result-set.js';
@@ -171,6 +172,7 @@ export declare class CamusClient implements AsyncDisposable {
171
172
  * a large result, such as an `INSERT … SELECT … RETURNING` or an `UPDATE` of many rows.
172
173
  */
173
174
  query<T = Record<string, unknown>>(sql: string, parameters?: Parameters, options?: AutocommitStatementOptions): Promise<QueryResult<T>>;
175
+ private runQuery;
174
176
  /**
175
177
  * Runs a `SELECT` and reads its first row, or `undefined` when it returned none. It accepts an
176
178
  * `INSERT`, `UPDATE`, or `DELETE` with `RETURNING` as `query` does.
@@ -220,6 +222,7 @@ export declare class CamusClient implements AsyncDisposable {
220
222
  * for it. The stream reports no written-row count, so count the rows as you read them.
221
223
  */
222
224
  queryStream<T = Record<string, unknown>>(sql: string, parameters?: Parameters, options?: AutocommitStatementOptions): Promise<CamusQueryStream<T>>;
225
+ private openQueryStream;
223
226
  /**
224
227
  * Runs an `INSERT`, `UPDATE`, or `DELETE` and reports how many rows it changed.
225
228
  *
@@ -246,6 +249,7 @@ export declare class CamusClient implements AsyncDisposable {
246
249
  * deliver, and the driver refuses it before the round trip.
247
250
  */
248
251
  executeDdl(sql: string, options?: AutocommitStatementOptions): Promise<boolean>;
252
+ private runDdl;
249
253
  /**
250
254
  * Inserts one row through the server's typed row-level route, naming a table and a column-to-value
251
255
  * map instead of composing SQL.
@@ -258,6 +262,38 @@ export declare class CamusClient implements AsyncDisposable {
258
262
  * health, and error translation. Use it to avoid building statement text for a hot write path.
259
263
  */
260
264
  insert(table: string, values: Parameters, options?: StatementOptions): Promise<number>;
265
+ /** The endpoints that this client is configured with, in configuration order. */
266
+ get endpoints(): readonly string[];
267
+ /**
268
+ * The disk, CPU, and memory of one node. See `CamusNodeStats` for every field.
269
+ *
270
+ * ```ts
271
+ * const stats = await client.nodeStats();
272
+ * const data = stats.dataVolume!;
273
+ *
274
+ * console.log(`${data.availableBytes} bytes free of ${data.totalBytes}`);
275
+ *
276
+ * for (const endpoint of client.endpoints) {
277
+ * const node = await client.nodeStats(endpoint);
278
+ * console.log(`${node.address}: ${node.cpu.processCpuPercent}% CPU`);
279
+ * }
280
+ * ```
281
+ *
282
+ * Without `endpoint`, it asks the next node in the rotation. Each node answers only for itself.
283
+ * An `endpoint` must be one of `endpoints`, so the client's credentials go only to the addresses
284
+ * it was configured with.
285
+ *
286
+ * It is server-level, not scoped to this client's database, and it works over REST
287
+ * (`GET /v1/admin/stats`) and gRPC (`GetNodeStats`). With authentication on, the account needs
288
+ * the superuser attribute or the `MONITOR` privilege (`GRANT MONITOR ON *.* TO <user>`). Any
289
+ * other account gets `CADB0517`.
290
+ *
291
+ * @throws {TypeError} when `endpoint` is not one of `endpoints`.
292
+ */
293
+ nodeStats(endpoint?: string, options?: {
294
+ signal?: AbortSignal;
295
+ timeoutSeconds?: number;
296
+ }): Promise<CamusNodeStats>;
261
297
  /** Reports whether the server answers. */
262
298
  ping(options?: {
263
299
  signal?: AbortSignal;
@@ -280,6 +316,9 @@ export declare class CamusClient implements AsyncDisposable {
280
316
  *
281
317
  * With `await using`, a transaction that is left without a commit is rolled back as the block
282
318
  * unwinds.
319
+ *
320
+ * With `deferBegin`, or with learned routing on, `BEGIN` is not sent here. The first statement,
321
+ * or the first `CamusPipeline` send, sends it.
283
322
  */
284
323
  beginTransaction(options?: CamusTransactionOptions, signal?: AbortSignal): Promise<CamusTransaction>;
285
324
  /**
@@ -299,6 +338,9 @@ export declare class CamusClient implements AsyncDisposable {
299
338
  * an exponential back-off. So the function must be safe to run more than once — it must not send
300
339
  * an email, charge a card, or mutate state outside the database on a path that could repeat.
301
340
  *
341
+ * The work can commit the transaction itself with `CamusPipeline.commit`. The transaction is
342
+ * then not committed a second time.
343
+ *
302
344
  * A commit that reports an unresolved outcome is **not** retried this way. That case is resolved
303
345
  * inside `CamusTransaction`, by re-issuing the same commit on the same handle, because replaying
304
346
  * the work could apply an already-durable commit twice.
@@ -467,43 +509,6 @@ export declare class CamusClient implements AsyncDisposable {
467
509
  */
468
510
  private route;
469
511
  private buildRequest;
470
- /**
471
- * Whether this execution should name a prepared statement instead of carrying its SQL,
472
- * registering it first when this is the execution that tips it over the threshold.
473
- *
474
- * The registration is awaited rather than started in the background, because the whole point is
475
- * that this execution and the ones after it are cheap. Firing it off and running inline anyway
476
- * would leave a busy statement racing its own warm-up. It costs one extra round trip, once per
477
- * statement per endpoint.
478
- *
479
- * The caller passes the endpoint it already resolved. A REST handle is node-local and the pool
480
- * rotates, so registering against a freshly drawn endpoint would routinely prepare on one node
481
- * and execute on another — correct, because the transport re-registers where it lands, but a
482
- * wasted round trip every single time.
483
- */
484
- private shouldPrepare;
485
- /**
486
- * Registers a statement and records what happened, reporting whether it may now run prepared.
487
- *
488
- * A registration failure never reaches the caller: preparing is an optimization, and the
489
- * statement runs inline exactly as it would have if the driver had not tried. What the failure
490
- * does decide is whether to ask again. A refusal specific to this statement stops asking for that
491
- * statement; anything that says the node has no prepared-statement support at all stops asking
492
- * for every statement, because one round trip per distinct SQL to relearn that is worse than not
493
- * trying. A failure that never reached a verdict — a timeout, an unreachable node — drops the
494
- * entry instead, so one network blip does not cost this statement its registration for the life
495
- * of the process.
496
- */
497
- private register;
498
- /**
499
- * Releases a statement the policy evicted, so the server stops holding a handle this client has
500
- * stopped using.
501
- *
502
- * It is best effort and off the caller's path: it is bookkeeping, not part of the statement being
503
- * run. It takes the endpoint the caller already resolved rather than drawing a new one, which
504
- * would rotate the pool as a side effect of housekeeping.
505
- */
506
- private release;
507
512
  /**
508
513
  * The effective options for a transaction or an autocommit statement: the caller's explicit knobs
509
514
  * win, then this client's defaults, then the server default for any knob still unset.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}