@ragestudio/scylla-odm 0.22.2 → 0.22.4
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/batch/index.d.ts +3 -3
- package/batch/index.d.ts.map +1 -1
- package/client.d.ts +6 -5
- package/client.d.ts.map +1 -1
- package/client.js +11 -12
- package/client.js.map +1 -1
- package/cql_gen/create_table.d.ts +1 -1
- package/cql_gen/create_table.d.ts.map +1 -1
- package/document/index.d.ts +3 -3
- package/document/index.d.ts.map +1 -1
- package/driver/LICENSE.txt +177 -0
- package/driver/NOTICE.txt +67 -0
- package/driver/auth/index.d.ts +37 -0
- package/driver/auth/index.js +37 -0
- package/driver/auth/no-auth-provider.js +73 -0
- package/driver/auth/plain-text-auth-provider.js +81 -0
- package/driver/auth/provider.js +77 -0
- package/driver/client-options.js +442 -0
- package/driver/client.js +1267 -0
- package/driver/concurrent/index.d.ts +49 -0
- package/driver/concurrent/index.js +366 -0
- package/driver/connection.js +1034 -0
- package/driver/control-connection.js +1282 -0
- package/driver/encoder.js +2316 -0
- package/driver/errors.js +223 -0
- package/driver/execution-options.js +612 -0
- package/driver/execution-profile.js +274 -0
- package/driver/host-connection-pool.js +587 -0
- package/driver/host.js +699 -0
- package/driver/index.d.ts +387 -0
- package/driver/index.js +81 -0
- package/driver/mapping/cache.js +214 -0
- package/driver/mapping/doc-info-adapter.js +171 -0
- package/driver/mapping/index.d.ts +219 -0
- package/driver/mapping/index.js +57 -0
- package/driver/mapping/mapper.js +225 -0
- package/driver/mapping/mapping-handler.js +641 -0
- package/driver/mapping/model-batch-item.js +215 -0
- package/driver/mapping/model-batch-mapper.js +141 -0
- package/driver/mapping/model-mapper.js +315 -0
- package/driver/mapping/model-mapping-info.js +225 -0
- package/driver/mapping/object-selector.js +417 -0
- package/driver/mapping/q.js +156 -0
- package/driver/mapping/query-generator.js +556 -0
- package/driver/mapping/result-mapper.js +123 -0
- package/driver/mapping/result.js +139 -0
- package/driver/mapping/table-mappings.js +133 -0
- package/driver/mapping/tree.js +160 -0
- package/driver/metadata/aggregate.js +79 -0
- package/driver/metadata/client-state.js +119 -0
- package/driver/metadata/data-collection.js +182 -0
- package/driver/metadata/event-debouncer.js +174 -0
- package/driver/metadata/index.d.ts +276 -0
- package/driver/metadata/index.js +1156 -0
- package/driver/metadata/materialized-view.js +49 -0
- package/driver/metadata/schema-function.js +98 -0
- package/driver/metadata/schema-index.js +166 -0
- package/driver/metadata/schema-parser.js +1399 -0
- package/driver/metadata/table-metadata.js +77 -0
- package/driver/operation-state.js +206 -0
- package/driver/policies/address-resolution.js +145 -0
- package/driver/policies/index.d.ts +241 -0
- package/driver/policies/index.js +110 -0
- package/driver/policies/load-balancing.js +970 -0
- package/driver/policies/reconnection.js +166 -0
- package/driver/policies/retry.js +326 -0
- package/driver/policies/speculative-execution.js +150 -0
- package/driver/policies/timestamp-generation.js +176 -0
- package/driver/prepare-handler.js +347 -0
- package/driver/promise-utils.js +191 -0
- package/driver/readers.js +624 -0
- package/driver/request-execution.js +644 -0
- package/driver/request-handler.js +332 -0
- package/driver/requests.js +618 -0
- package/driver/stream-id-stack.js +209 -0
- package/driver/streams.js +745 -0
- package/driver/token.js +325 -0
- package/driver/tokenizer.js +631 -0
- package/driver/types/big-decimal.js +282 -0
- package/driver/types/duration.js +576 -0
- package/driver/types/index.d.ts +486 -0
- package/driver/types/index.js +733 -0
- package/driver/types/inet-address.js +262 -0
- package/driver/types/integer.js +818 -0
- package/driver/types/local-date.js +280 -0
- package/driver/types/local-time.js +299 -0
- package/driver/types/mutable-long.js +385 -0
- package/driver/types/protocol-version.js +391 -0
- package/driver/types/result-set.js +287 -0
- package/driver/types/result-stream.js +164 -0
- package/driver/types/row.js +85 -0
- package/driver/types/time-uuid.js +414 -0
- package/driver/types/tuple.js +103 -0
- package/driver/types/uuid.js +160 -0
- package/driver/types/vector.js +130 -0
- package/driver/types/version-number.js +153 -0
- package/driver/utils.js +1485 -0
- package/driver/writers.js +350 -0
- package/global.d.ts +1 -1
- package/global.d.ts.map +1 -1
- package/index.d.ts +6 -6
- package/index.d.ts.map +1 -1
- package/index.js +6 -6
- package/index.js.map +1 -1
- package/migrate/index.d.ts +1 -1
- package/migrate/index.d.ts.map +1 -1
- package/migrate/index.js +1 -1
- package/migrate/index.js.map +1 -1
- package/model/index.d.ts +6 -6
- package/model/index.d.ts.map +1 -1
- package/model/index.js +10 -10
- package/model/index.js.map +1 -1
- package/operations/countAll.d.ts +1 -1
- package/operations/countAll.d.ts.map +1 -1
- package/operations/delete.d.ts +3 -4
- package/operations/delete.d.ts.map +1 -1
- package/operations/delete.js +1 -1
- package/operations/delete.js.map +1 -1
- package/operations/find.d.ts +2 -2
- package/operations/find.d.ts.map +1 -1
- package/operations/find.js +1 -1
- package/operations/find.js.map +1 -1
- package/operations/findOne.d.ts +2 -2
- package/operations/findOne.d.ts.map +1 -1
- package/operations/findOne.js +1 -1
- package/operations/findOne.js.map +1 -1
- package/operations/insert.d.ts +3 -3
- package/operations/insert.d.ts.map +1 -1
- package/operations/insert.js +2 -2
- package/operations/insert.js.map +1 -1
- package/operations/sync.d.ts +1 -1
- package/operations/sync.d.ts.map +1 -1
- package/operations/sync.js +1 -1
- package/operations/sync.js.map +1 -1
- package/operations/tableExists.d.ts +1 -1
- package/operations/tableExists.d.ts.map +1 -1
- package/operations/update.d.ts +3 -3
- package/operations/update.d.ts.map +1 -1
- package/operations/update.js +2 -2
- package/operations/update.js.map +1 -1
- package/package.json +4 -12
- package/schema/index.d.ts +1 -1
- package/schema/index.d.ts.map +1 -1
- package/types.d.ts +4 -4
- package/types.d.ts.map +1 -1
- package/utils/queryParser.d.ts +1 -1
- package/utils/queryParser.d.ts.map +1 -1
- package/utils/queryParser.js +1 -1
- package/utils/queryParser.js.map +1 -1
- package/utils/typeChecker.d.ts +1 -1
- package/utils/typeChecker.d.ts.map +1 -1
- package/utils/typeChecker.js +1 -1
- package/utils/typeChecker.js.map +1 -1
package/driver/host.js
ADDED
|
@@ -0,0 +1,699 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed to the Apache Software Foundation (ASF) under one
|
|
3
|
+
* or more contributor license agreements. See the NOTICE file
|
|
4
|
+
* distributed with this work for additional information
|
|
5
|
+
* regarding copyright ownership. The ASF licenses this file
|
|
6
|
+
* to you under the Apache License, Version 2.0 (the
|
|
7
|
+
* "License"); you may not use this file except in compliance
|
|
8
|
+
* with the License. You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import events from "events"
|
|
20
|
+
|
|
21
|
+
import utils from "./utils.js"
|
|
22
|
+
import types from "./types/index.js"
|
|
23
|
+
import HostConnectionPool from "./host-connection-pool.js"
|
|
24
|
+
import PrepareHandler from "./prepare-handler.js"
|
|
25
|
+
import promiseUtils from "./promise-utils.js"
|
|
26
|
+
|
|
27
|
+
const healthResponseCountInterval = 200
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Represents a Cassandra node.
|
|
31
|
+
* @extends EventEmitter
|
|
32
|
+
*/
|
|
33
|
+
class Host extends events.EventEmitter {
|
|
34
|
+
/**
|
|
35
|
+
* Creates a new Host instance.
|
|
36
|
+
*/
|
|
37
|
+
constructor(address, protocolVersion, options, metadata) {
|
|
38
|
+
super()
|
|
39
|
+
/**
|
|
40
|
+
* Gets ip address and port number of the node separated by `:`.
|
|
41
|
+
* @type {String}
|
|
42
|
+
*/
|
|
43
|
+
this.address = address
|
|
44
|
+
this.setDownAt = 0
|
|
45
|
+
this.log = utils.log
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Gets the timestamp of the moment when the Host was marked as UP.
|
|
49
|
+
* @type {Number|null}
|
|
50
|
+
* @ignore
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
53
|
+
this.isUpSince = null
|
|
54
|
+
Object.defineProperty(this, "options", {
|
|
55
|
+
value: options,
|
|
56
|
+
enumerable: false,
|
|
57
|
+
writable: false,
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The host pool.
|
|
62
|
+
* @internal
|
|
63
|
+
* @ignore
|
|
64
|
+
* @type {HostConnectionPool}
|
|
65
|
+
*/
|
|
66
|
+
Object.defineProperty(this, "pool", {
|
|
67
|
+
value: new HostConnectionPool(this, protocolVersion),
|
|
68
|
+
enumerable: false,
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
this.pool.on("open", (err) =>
|
|
72
|
+
promiseUtils.toBackground(this._onNewConnectionOpen(err)),
|
|
73
|
+
)
|
|
74
|
+
this.pool.on("remove", () => this._checkPoolState())
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Gets string containing the Cassandra version.
|
|
78
|
+
* @type {String}
|
|
79
|
+
*/
|
|
80
|
+
this.cassandraVersion = null
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Gets data center name of the node.
|
|
84
|
+
* @type {String}
|
|
85
|
+
*/
|
|
86
|
+
this.datacenter = null
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Gets rack name of the node.
|
|
90
|
+
* @type {String}
|
|
91
|
+
*/
|
|
92
|
+
this.rack = null
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Gets the tokens assigned to the node.
|
|
96
|
+
* @type {Array}
|
|
97
|
+
*/
|
|
98
|
+
this.tokens = null
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Gets the id of the host.
|
|
102
|
+
* <p>This identifier is used by the server for internal communication / gossip.</p>
|
|
103
|
+
* @type {Uuid}
|
|
104
|
+
*/
|
|
105
|
+
this.hostId = null
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Gets string containing the DSE version or null if not set.
|
|
109
|
+
* @type {String}
|
|
110
|
+
*/
|
|
111
|
+
this.dseVersion = null
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Gets the DSE Workloads the host is running.
|
|
115
|
+
* <p>
|
|
116
|
+
* This is based on the "workload" or "workloads" columns in {@code system.local} and {@code system.peers}.
|
|
117
|
+
* <p/>
|
|
118
|
+
* <p>
|
|
119
|
+
* Workload labels may vary depending on the DSE version in use;e.g. DSE 5.1 may report two distinct workloads:
|
|
120
|
+
* <code>Search</code> and <code>Analytics</code>, while DSE 5.0 would report a single
|
|
121
|
+
* <code>SearchAnalytics</code> workload instead. The driver simply returns the workload labels as reported by
|
|
122
|
+
* DSE, without any form of pre-processing.
|
|
123
|
+
* <p/>
|
|
124
|
+
* <p>When the information is unavailable, this property returns an empty array.</p>
|
|
125
|
+
* @type {Array<string>}
|
|
126
|
+
*/
|
|
127
|
+
this.workloads = utils.emptyArray
|
|
128
|
+
|
|
129
|
+
// the distance as last set using the load balancing policy
|
|
130
|
+
this._distance = types.distance.ignored
|
|
131
|
+
this._healthResponseCounter = 0
|
|
132
|
+
|
|
133
|
+
// Make some of the private instance variables not enumerable to prevent from showing when inspecting
|
|
134
|
+
Object.defineProperty(this, "_metadata", {
|
|
135
|
+
value: metadata,
|
|
136
|
+
enumerable: false,
|
|
137
|
+
})
|
|
138
|
+
Object.defineProperty(this, "_healthResponseCountTimer", {
|
|
139
|
+
value: null,
|
|
140
|
+
enumerable: false,
|
|
141
|
+
writable: true,
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
this.reconnectionSchedule =
|
|
145
|
+
this.options.policies.reconnection.newSchedule()
|
|
146
|
+
this.reconnectionDelay = 0
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Marks this host as not available for query coordination, when the host was previously marked as UP, otherwise its
|
|
151
|
+
* a no-op.
|
|
152
|
+
* @internal
|
|
153
|
+
* @ignore
|
|
154
|
+
*/
|
|
155
|
+
setDown() {
|
|
156
|
+
// Multiple events signaling that a host is failing could cause multiple calls to this method
|
|
157
|
+
if (this.setDownAt !== 0) {
|
|
158
|
+
// the host is already marked as Down
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
if (this.pool.isClosing()) {
|
|
162
|
+
// the pool is being closed/shutdown, don't mind
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
this.setDownAt = Date.now()
|
|
166
|
+
if (this.pool.coreConnectionsLength > 0) {
|
|
167
|
+
// According to the distance, there should be connections open to it => issue a warning
|
|
168
|
+
this.log(
|
|
169
|
+
"warning",
|
|
170
|
+
`Host ${this.address} considered as DOWN. Reconnection delay ${this.reconnectionDelay}ms.`,
|
|
171
|
+
)
|
|
172
|
+
} else {
|
|
173
|
+
this.log("info", `Host ${this.address} considered as DOWN.`)
|
|
174
|
+
}
|
|
175
|
+
this.emit("down")
|
|
176
|
+
this._checkPoolState()
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Marks this host as available for querying.
|
|
181
|
+
* @param {Boolean} [clearReconnection]
|
|
182
|
+
* @internal
|
|
183
|
+
* @ignore
|
|
184
|
+
*/
|
|
185
|
+
setUp(clearReconnection) {
|
|
186
|
+
if (!this.setDownAt) {
|
|
187
|
+
//The host is already marked as UP
|
|
188
|
+
return
|
|
189
|
+
}
|
|
190
|
+
this.log("info", `Setting host ${this.address} as UP`)
|
|
191
|
+
this.setDownAt = 0
|
|
192
|
+
this.isUpSince = Date.now()
|
|
193
|
+
//if it was unhealthy and now it is not, lets reset the reconnection schedule.
|
|
194
|
+
this.reconnectionSchedule =
|
|
195
|
+
this.options.policies.reconnection.newSchedule()
|
|
196
|
+
if (clearReconnection) {
|
|
197
|
+
this.pool.clearNewConnectionAttempt()
|
|
198
|
+
}
|
|
199
|
+
this.emit("up")
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Resets the reconnectionSchedule and tries to issue a reconnection immediately.
|
|
204
|
+
* @internal
|
|
205
|
+
* @ignore
|
|
206
|
+
*/
|
|
207
|
+
checkIsUp() {
|
|
208
|
+
if (this.isUp()) {
|
|
209
|
+
return
|
|
210
|
+
}
|
|
211
|
+
this.reconnectionSchedule =
|
|
212
|
+
this.options.policies.reconnection.newSchedule()
|
|
213
|
+
this.reconnectionDelay = 0
|
|
214
|
+
this.pool.attemptNewConnectionImmediate()
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* @param {Boolean} [waitForPending] When true, it waits for in-flight operations to be finish before closing the
|
|
219
|
+
* connections.
|
|
220
|
+
* @returns {Promise<void>}
|
|
221
|
+
* @internal
|
|
222
|
+
* @ignore
|
|
223
|
+
*/
|
|
224
|
+
shutdown(waitForPending) {
|
|
225
|
+
if (this._healthResponseCountTimer) {
|
|
226
|
+
clearInterval(this._healthResponseCountTimer)
|
|
227
|
+
}
|
|
228
|
+
if (waitForPending) {
|
|
229
|
+
this.pool.drainAndShutdown()
|
|
230
|
+
// Gracefully draining and shutting down the pool is being done in the background
|
|
231
|
+
return Promise.resolve()
|
|
232
|
+
}
|
|
233
|
+
return this.pool.shutdown()
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Determines if the node is UP now (seen as UP by the driver).
|
|
238
|
+
* @returns {boolean}
|
|
239
|
+
*/
|
|
240
|
+
isUp() {
|
|
241
|
+
return !this.setDownAt
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Determines if the host can be considered as UP.
|
|
246
|
+
* Deprecated: Use {@link Host#isUp()} instead.
|
|
247
|
+
* @returns {boolean}
|
|
248
|
+
*/
|
|
249
|
+
canBeConsideredAsUp() {
|
|
250
|
+
const self = this
|
|
251
|
+
function hasTimePassed() {
|
|
252
|
+
return (
|
|
253
|
+
new Date().getTime() - self.setDownAt >= self.reconnectionDelay
|
|
254
|
+
)
|
|
255
|
+
}
|
|
256
|
+
return !this.setDownAt || hasTimePassed()
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Sets the distance of the host relative to the client using the load balancing policy.
|
|
261
|
+
* @param {Number} distance
|
|
262
|
+
* @internal
|
|
263
|
+
* @ignore
|
|
264
|
+
*/
|
|
265
|
+
setDistance(distance) {
|
|
266
|
+
const previousDistance = this._distance
|
|
267
|
+
this._distance = distance || types.distance.local
|
|
268
|
+
if (this.options.pooling.coreConnectionsPerHost) {
|
|
269
|
+
this.pool.coreConnectionsLength =
|
|
270
|
+
this.options.pooling.coreConnectionsPerHost[this._distance] || 0
|
|
271
|
+
} else {
|
|
272
|
+
this.pool.coreConnectionsLength = 1
|
|
273
|
+
}
|
|
274
|
+
if (this._distance === previousDistance) {
|
|
275
|
+
return this._distance
|
|
276
|
+
}
|
|
277
|
+
if (this._healthResponseCountTimer) {
|
|
278
|
+
clearInterval(this._healthResponseCountTimer)
|
|
279
|
+
}
|
|
280
|
+
if (this._distance === types.distance.ignored) {
|
|
281
|
+
// this host was local/remote and now must be ignored
|
|
282
|
+
this.emit("ignore")
|
|
283
|
+
this.pool.drainAndShutdown()
|
|
284
|
+
} else {
|
|
285
|
+
if (!this.isUp()) {
|
|
286
|
+
this.checkIsUp()
|
|
287
|
+
}
|
|
288
|
+
// Reset the health check timer
|
|
289
|
+
this._healthResponseCountTimer = setInterval(() => {
|
|
290
|
+
this._healthResponseCounter =
|
|
291
|
+
this.pool.getAndResetResponseCounter()
|
|
292
|
+
}, healthResponseCountInterval)
|
|
293
|
+
}
|
|
294
|
+
return this._distance
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Changes the protocol version of a given host
|
|
299
|
+
* @param {Number} value
|
|
300
|
+
* @internal
|
|
301
|
+
* @ignore
|
|
302
|
+
*/
|
|
303
|
+
setProtocolVersion(value) {
|
|
304
|
+
this.pool.protocolVersion = value
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Gets the least busy connection from the pool.
|
|
309
|
+
* @param {Connection} [previousConnection] When provided, the pool should attempt to obtain a different connection.
|
|
310
|
+
* @returns {Connection!}
|
|
311
|
+
* @throws {Error}
|
|
312
|
+
* @throws {BusyConnectionError}
|
|
313
|
+
* @internal
|
|
314
|
+
* @ignore
|
|
315
|
+
*/
|
|
316
|
+
borrowConnection(previousConnection) {
|
|
317
|
+
return this.pool.borrowConnection(previousConnection)
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Creates all the connection in the pool.
|
|
322
|
+
* @param {string} keyspace
|
|
323
|
+
* @internal
|
|
324
|
+
* @ignore
|
|
325
|
+
*/
|
|
326
|
+
warmupPool(keyspace) {
|
|
327
|
+
return this.pool.warmup(keyspace)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Starts creating the pool in the background.
|
|
332
|
+
* @internal
|
|
333
|
+
* @ignore
|
|
334
|
+
*/
|
|
335
|
+
initializePool() {
|
|
336
|
+
this.pool.increaseSize()
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Gets any connection that is already opened or null if not found.
|
|
340
|
+
* @returns {Connection}
|
|
341
|
+
* @internal
|
|
342
|
+
* @ignore
|
|
343
|
+
*/
|
|
344
|
+
getActiveConnection() {
|
|
345
|
+
if (!this.isUp() || !this.pool.connections.length) {
|
|
346
|
+
return null
|
|
347
|
+
}
|
|
348
|
+
return this.pool.connections[0]
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Internal method to get the amount of responses dequeued in the last interval (between 200ms and 400ms) on all
|
|
353
|
+
* connections to the host.
|
|
354
|
+
* @returns {Number}
|
|
355
|
+
* @internal
|
|
356
|
+
* @ignore
|
|
357
|
+
*/
|
|
358
|
+
getResponseCount() {
|
|
359
|
+
// Last interval plus the current count
|
|
360
|
+
return this._healthResponseCounter + this.pool.responseCounter
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Checks the health of a connection in the pool
|
|
365
|
+
* @param {Connection} connection
|
|
366
|
+
* @internal
|
|
367
|
+
* @ignore
|
|
368
|
+
*/
|
|
369
|
+
checkHealth(connection) {
|
|
370
|
+
if (
|
|
371
|
+
connection.timedOutOperations <=
|
|
372
|
+
this.options.socketOptions.defunctReadTimeoutThreshold
|
|
373
|
+
) {
|
|
374
|
+
return
|
|
375
|
+
}
|
|
376
|
+
this.removeFromPool(connection)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* @param {Connection} connection
|
|
381
|
+
* @internal
|
|
382
|
+
* @ignore
|
|
383
|
+
*/
|
|
384
|
+
removeFromPool(connection) {
|
|
385
|
+
this.pool.remove(connection)
|
|
386
|
+
this._checkPoolState()
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Internal method that gets the amount of in-flight requests on all connections to the host.
|
|
391
|
+
* @internal
|
|
392
|
+
* @ignore
|
|
393
|
+
*/
|
|
394
|
+
getInFlight() {
|
|
395
|
+
return this.pool.getInFlight()
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Validates that the internal state of the connection pool.
|
|
400
|
+
* If the pool size is smaller than expected, schedule a new connection attempt.
|
|
401
|
+
* If the amount of connections is 0 for not ignored hosts, the host must be down.
|
|
402
|
+
* @private
|
|
403
|
+
*/
|
|
404
|
+
_checkPoolState() {
|
|
405
|
+
if (this.pool.isClosing()) {
|
|
406
|
+
return
|
|
407
|
+
}
|
|
408
|
+
if (this.pool.connections.length < this.pool.coreConnectionsLength) {
|
|
409
|
+
// the pool needs to grow / reconnect
|
|
410
|
+
if (!this.pool.hasScheduledNewConnection()) {
|
|
411
|
+
this.reconnectionDelay = this.reconnectionSchedule.next().value
|
|
412
|
+
this.pool.scheduleNewConnectionAttempt(this.reconnectionDelay)
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
const shouldHaveConnections =
|
|
416
|
+
this._distance !== types.distance.ignored &&
|
|
417
|
+
this.pool.coreConnectionsLength > 0
|
|
418
|
+
if (shouldHaveConnections && this.pool.connections.length === 0) {
|
|
419
|
+
// Mark as DOWN, if its UP
|
|
420
|
+
this.setDown()
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Executed after an scheduled new connection attempt finished
|
|
426
|
+
* @private
|
|
427
|
+
*/
|
|
428
|
+
async _onNewConnectionOpen(err) {
|
|
429
|
+
if (err) {
|
|
430
|
+
this._checkPoolState()
|
|
431
|
+
return
|
|
432
|
+
}
|
|
433
|
+
if (!this.isUp() && this.options.rePrepareOnUp) {
|
|
434
|
+
this.log(
|
|
435
|
+
"info",
|
|
436
|
+
`Re-preparing all queries on host ${this.address} before setting it as UP`,
|
|
437
|
+
)
|
|
438
|
+
const allPrepared = this._metadata.getAllPrepared()
|
|
439
|
+
try {
|
|
440
|
+
await PrepareHandler.prepareAllQueries(this, allPrepared)
|
|
441
|
+
} catch (err) {
|
|
442
|
+
this.log(
|
|
443
|
+
"warning",
|
|
444
|
+
`Failed re-preparing on host ${this.address}: ${err}`,
|
|
445
|
+
err,
|
|
446
|
+
)
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
this.setUp()
|
|
450
|
+
this.pool.increaseSize()
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Returns an array containing the Cassandra Version as an Array of Numbers having the major version in the first
|
|
455
|
+
* position.
|
|
456
|
+
* @returns {Array.<Number>}
|
|
457
|
+
*/
|
|
458
|
+
getCassandraVersion() {
|
|
459
|
+
if (!this.cassandraVersion) {
|
|
460
|
+
return utils.emptyArray
|
|
461
|
+
}
|
|
462
|
+
return this.cassandraVersion
|
|
463
|
+
.split("-")[0]
|
|
464
|
+
.split(".")
|
|
465
|
+
.map((x) => parseInt(x, 10))
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Gets the DSE version of the host as an Array, containing the major version in the first position.
|
|
470
|
+
* In case the cluster is not a DSE cluster, it returns an empty Array.
|
|
471
|
+
* @returns {Array}
|
|
472
|
+
*/
|
|
473
|
+
getDseVersion() {
|
|
474
|
+
if (!this.dseVersion) {
|
|
475
|
+
return utils.emptyArray
|
|
476
|
+
}
|
|
477
|
+
return this.dseVersion
|
|
478
|
+
.split("-")[0]
|
|
479
|
+
.split(".")
|
|
480
|
+
.map((x) => parseInt(x, 10))
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Represents an associative-array of {@link Host hosts} that can be iterated.
|
|
486
|
+
* It creates an internal copy when adding or removing, making it safe to iterate using the values()
|
|
487
|
+
* method within async operations.
|
|
488
|
+
* @extends events.EventEmitter
|
|
489
|
+
* @constructor
|
|
490
|
+
*/
|
|
491
|
+
class HostMap extends events.EventEmitter {
|
|
492
|
+
constructor() {
|
|
493
|
+
super()
|
|
494
|
+
|
|
495
|
+
this._items = new Map()
|
|
496
|
+
this._values = null
|
|
497
|
+
|
|
498
|
+
Object.defineProperty(this, "length", {
|
|
499
|
+
get: () => this.values().length,
|
|
500
|
+
enumerable: true,
|
|
501
|
+
})
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Emitted when a host is added to the map
|
|
505
|
+
* @event HostMap#add
|
|
506
|
+
*/
|
|
507
|
+
/**
|
|
508
|
+
* Emitted when a host is removed from the map
|
|
509
|
+
* @event HostMap#remove
|
|
510
|
+
*/
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Executes a provided function once per map element.
|
|
515
|
+
* @param callback
|
|
516
|
+
*/
|
|
517
|
+
forEach(callback) {
|
|
518
|
+
const items = this._items
|
|
519
|
+
for (const [key, value] of items) {
|
|
520
|
+
callback(value, key)
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Gets a {@link Host host} by key or undefined if not found.
|
|
526
|
+
* @param {String} key
|
|
527
|
+
* @returns {Host}
|
|
528
|
+
*/
|
|
529
|
+
get(key) {
|
|
530
|
+
return this._items.get(key)
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Returns an array of host addresses.
|
|
535
|
+
* @returns {Array.<String>}
|
|
536
|
+
*/
|
|
537
|
+
keys() {
|
|
538
|
+
return Array.from(this._items.keys())
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Removes an item from the map.
|
|
543
|
+
* @param {String} key The key of the host
|
|
544
|
+
* @fires HostMap#remove
|
|
545
|
+
*/
|
|
546
|
+
remove(key) {
|
|
547
|
+
const value = this._items.get(key)
|
|
548
|
+
if (value === undefined) {
|
|
549
|
+
return
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// Clear cache
|
|
553
|
+
this._values = null
|
|
554
|
+
|
|
555
|
+
// Copy the values
|
|
556
|
+
const copy = new Map(this._items)
|
|
557
|
+
copy.delete(key)
|
|
558
|
+
|
|
559
|
+
this._items = copy
|
|
560
|
+
this.emit("remove", value)
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Removes multiple hosts from the map.
|
|
565
|
+
* @param {Array.<String>} keys
|
|
566
|
+
* @fires HostMap#remove
|
|
567
|
+
*/
|
|
568
|
+
removeMultiple(keys) {
|
|
569
|
+
// Clear value cache
|
|
570
|
+
this._values = null
|
|
571
|
+
|
|
572
|
+
// Copy the values
|
|
573
|
+
const copy = new Map(this._items)
|
|
574
|
+
const removedHosts = []
|
|
575
|
+
|
|
576
|
+
for (const key of keys) {
|
|
577
|
+
const h = copy.get(key)
|
|
578
|
+
|
|
579
|
+
if (!h) {
|
|
580
|
+
continue
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
removedHosts.push(h)
|
|
584
|
+
copy.delete(key)
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
this._items = copy
|
|
588
|
+
removedHosts.forEach((h) => this.emit("remove", h))
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Adds a new item to the map.
|
|
593
|
+
* @param {String} key The key of the host
|
|
594
|
+
* @param {Host} value The host to be added
|
|
595
|
+
* @fires HostMap#remove
|
|
596
|
+
* @fires HostMap#add
|
|
597
|
+
*/
|
|
598
|
+
set(key, value) {
|
|
599
|
+
// Clear values cache
|
|
600
|
+
this._values = null
|
|
601
|
+
|
|
602
|
+
const originalValue = this._items.get(key)
|
|
603
|
+
if (originalValue) {
|
|
604
|
+
//The internal structure does not change
|
|
605
|
+
this._items.set(key, value)
|
|
606
|
+
//emit a remove followed by a add
|
|
607
|
+
this.emit("remove", originalValue)
|
|
608
|
+
this.emit("add", value)
|
|
609
|
+
return
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Copy the values
|
|
613
|
+
const copy = new Map(this._items)
|
|
614
|
+
copy.set(key, value)
|
|
615
|
+
this._items = copy
|
|
616
|
+
this.emit("add", value)
|
|
617
|
+
return value
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Returns a shallow copy of a portion of the items into a new array object.
|
|
622
|
+
* Backward-compatibility.
|
|
623
|
+
* @param {Number} [begin]
|
|
624
|
+
* @param {Number} [end]
|
|
625
|
+
* @returns {Array}
|
|
626
|
+
* @ignore
|
|
627
|
+
*/
|
|
628
|
+
slice(begin, end) {
|
|
629
|
+
if (!begin && !end) {
|
|
630
|
+
// Avoid making a copy of the copy
|
|
631
|
+
return this.values()
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
return this.values().slice(begin || 0, end)
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Deprecated: Use set() instead.
|
|
639
|
+
* @ignore
|
|
640
|
+
* @deprecated
|
|
641
|
+
*/
|
|
642
|
+
push(k, v) {
|
|
643
|
+
this.set(k, v)
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Returns a shallow copy of the values of the map.
|
|
648
|
+
* @returns {Array.<Host>}
|
|
649
|
+
*/
|
|
650
|
+
values() {
|
|
651
|
+
if (!this._values) {
|
|
652
|
+
// Cache the values
|
|
653
|
+
this._values = Object.freeze(Array.from(this._items.values()))
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
return this._values
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Removes all items from the map.
|
|
661
|
+
* @returns {Array.<Host>} The previous items
|
|
662
|
+
*/
|
|
663
|
+
clear() {
|
|
664
|
+
const previousItems = this.values()
|
|
665
|
+
|
|
666
|
+
// Clear cache
|
|
667
|
+
this._values = null
|
|
668
|
+
|
|
669
|
+
// Clear items
|
|
670
|
+
this._items = new Map()
|
|
671
|
+
|
|
672
|
+
// Emit events
|
|
673
|
+
previousItems.forEach((h) => this.emit("remove", h))
|
|
674
|
+
|
|
675
|
+
return previousItems
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
inspect() {
|
|
679
|
+
return this._items
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
toJSON() {
|
|
683
|
+
// Node 10 and below don't support Object.fromEntries()
|
|
684
|
+
if (Object.fromEntries) {
|
|
685
|
+
return Object.fromEntries(this._items)
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
const obj = {}
|
|
689
|
+
for (const [key, value] of this._items) {
|
|
690
|
+
obj[key] = value
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return obj
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
export { Host, HostMap }
|
|
698
|
+
|
|
699
|
+
export default { Host, HostMap }
|