@push.rocks/smartmongo 3.0.0 → 4.0.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.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/tsmdb/engine/IndexEngine.d.ts +23 -3
- package/dist_ts/tsmdb/engine/IndexEngine.js +357 -55
- package/dist_ts/tsmdb/engine/QueryPlanner.d.ts +64 -0
- package/dist_ts/tsmdb/engine/QueryPlanner.js +308 -0
- package/dist_ts/tsmdb/engine/SessionEngine.d.ts +117 -0
- package/dist_ts/tsmdb/engine/SessionEngine.js +232 -0
- package/dist_ts/tsmdb/index.d.ts +7 -0
- package/dist_ts/tsmdb/index.js +6 -1
- package/dist_ts/tsmdb/server/CommandRouter.d.ts +36 -0
- package/dist_ts/tsmdb/server/CommandRouter.js +91 -1
- package/dist_ts/tsmdb/server/TsmdbServer.js +3 -1
- package/dist_ts/tsmdb/server/handlers/AdminHandler.js +106 -6
- package/dist_ts/tsmdb/server/handlers/DeleteHandler.js +15 -3
- package/dist_ts/tsmdb/server/handlers/FindHandler.js +44 -14
- package/dist_ts/tsmdb/server/handlers/InsertHandler.js +4 -1
- package/dist_ts/tsmdb/server/handlers/UpdateHandler.js +31 -5
- package/dist_ts/tsmdb/storage/FileStorageAdapter.d.ts +25 -1
- package/dist_ts/tsmdb/storage/FileStorageAdapter.js +75 -6
- package/dist_ts/tsmdb/storage/IStorageAdapter.d.ts +5 -0
- package/dist_ts/tsmdb/storage/MemoryStorageAdapter.d.ts +1 -0
- package/dist_ts/tsmdb/storage/MemoryStorageAdapter.js +12 -1
- package/dist_ts/tsmdb/storage/WAL.d.ts +117 -0
- package/dist_ts/tsmdb/storage/WAL.js +286 -0
- package/dist_ts/tsmdb/utils/checksum.d.ts +30 -0
- package/dist_ts/tsmdb/utils/checksum.js +77 -0
- package/dist_ts/tsmdb/utils/index.d.ts +1 -0
- package/dist_ts/tsmdb/utils/index.js +2 -0
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/tsmdb/engine/IndexEngine.ts +375 -56
- package/ts/tsmdb/engine/QueryPlanner.ts +393 -0
- package/ts/tsmdb/engine/SessionEngine.ts +292 -0
- package/ts/tsmdb/index.ts +9 -0
- package/ts/tsmdb/server/CommandRouter.ts +109 -0
- package/ts/tsmdb/server/TsmdbServer.ts +3 -0
- package/ts/tsmdb/server/handlers/AdminHandler.ts +110 -5
- package/ts/tsmdb/server/handlers/DeleteHandler.ts +17 -2
- package/ts/tsmdb/server/handlers/FindHandler.ts +42 -13
- package/ts/tsmdb/server/handlers/InsertHandler.ts +6 -0
- package/ts/tsmdb/server/handlers/UpdateHandler.ts +33 -4
- package/ts/tsmdb/storage/FileStorageAdapter.ts +88 -5
- package/ts/tsmdb/storage/IStorageAdapter.ts +6 -0
- package/ts/tsmdb/storage/MemoryStorageAdapter.ts +12 -0
- package/ts/tsmdb/storage/WAL.ts +375 -0
- package/ts/tsmdb/utils/checksum.ts +88 -0
- package/ts/tsmdb/utils/index.ts +1 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import * as plugins from '../tsmdb.plugins.js';
|
|
2
|
+
/**
|
|
3
|
+
* Session engine for managing client sessions
|
|
4
|
+
* - Tracks session lifecycle (create, touch, end)
|
|
5
|
+
* - Links sessions to transactions
|
|
6
|
+
* - Auto-aborts transactions on session expiry
|
|
7
|
+
*/
|
|
8
|
+
export class SessionEngine {
|
|
9
|
+
sessions = new Map();
|
|
10
|
+
sessionTimeoutMs;
|
|
11
|
+
cleanupInterval;
|
|
12
|
+
transactionEngine;
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.sessionTimeoutMs = options?.sessionTimeoutMs ?? 30 * 60 * 1000; // 30 minutes default
|
|
15
|
+
const cleanupIntervalMs = options?.cleanupIntervalMs ?? 60 * 1000; // 1 minute default
|
|
16
|
+
// Start cleanup interval
|
|
17
|
+
this.cleanupInterval = setInterval(() => {
|
|
18
|
+
this.cleanupExpiredSessions();
|
|
19
|
+
}, cleanupIntervalMs);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Set the transaction engine to use for auto-abort
|
|
23
|
+
*/
|
|
24
|
+
setTransactionEngine(engine) {
|
|
25
|
+
this.transactionEngine = engine;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Start a new session
|
|
29
|
+
*/
|
|
30
|
+
startSession(sessionId, metadata) {
|
|
31
|
+
const id = sessionId ?? new plugins.bson.UUID().toHexString();
|
|
32
|
+
const now = Date.now();
|
|
33
|
+
const session = {
|
|
34
|
+
id,
|
|
35
|
+
createdAt: now,
|
|
36
|
+
lastActivityAt: now,
|
|
37
|
+
inTransaction: false,
|
|
38
|
+
metadata,
|
|
39
|
+
};
|
|
40
|
+
this.sessions.set(id, session);
|
|
41
|
+
return session;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get a session by ID
|
|
45
|
+
*/
|
|
46
|
+
getSession(sessionId) {
|
|
47
|
+
const session = this.sessions.get(sessionId);
|
|
48
|
+
if (session && this.isSessionExpired(session)) {
|
|
49
|
+
// Session expired, clean it up
|
|
50
|
+
this.endSession(sessionId);
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
return session;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Touch a session to update last activity time
|
|
57
|
+
*/
|
|
58
|
+
touchSession(sessionId) {
|
|
59
|
+
const session = this.sessions.get(sessionId);
|
|
60
|
+
if (!session)
|
|
61
|
+
return false;
|
|
62
|
+
if (this.isSessionExpired(session)) {
|
|
63
|
+
this.endSession(sessionId);
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
session.lastActivityAt = Date.now();
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* End a session explicitly
|
|
71
|
+
* This will also abort any active transaction
|
|
72
|
+
*/
|
|
73
|
+
async endSession(sessionId) {
|
|
74
|
+
const session = this.sessions.get(sessionId);
|
|
75
|
+
if (!session)
|
|
76
|
+
return false;
|
|
77
|
+
// If session has an active transaction, abort it
|
|
78
|
+
if (session.inTransaction && session.txnId && this.transactionEngine) {
|
|
79
|
+
try {
|
|
80
|
+
await this.transactionEngine.abortTransaction(session.txnId);
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
// Ignore abort errors during cleanup
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
this.sessions.delete(sessionId);
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Start a transaction in a session
|
|
91
|
+
*/
|
|
92
|
+
startTransaction(sessionId, txnId, txnNumber) {
|
|
93
|
+
const session = this.sessions.get(sessionId);
|
|
94
|
+
if (!session)
|
|
95
|
+
return false;
|
|
96
|
+
if (this.isSessionExpired(session)) {
|
|
97
|
+
this.endSession(sessionId);
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
session.txnId = txnId;
|
|
101
|
+
session.txnNumber = txnNumber;
|
|
102
|
+
session.inTransaction = true;
|
|
103
|
+
session.lastActivityAt = Date.now();
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* End a transaction in a session (commit or abort)
|
|
108
|
+
*/
|
|
109
|
+
endTransaction(sessionId) {
|
|
110
|
+
const session = this.sessions.get(sessionId);
|
|
111
|
+
if (!session)
|
|
112
|
+
return false;
|
|
113
|
+
session.txnId = undefined;
|
|
114
|
+
session.txnNumber = undefined;
|
|
115
|
+
session.inTransaction = false;
|
|
116
|
+
session.lastActivityAt = Date.now();
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get transaction ID for a session
|
|
121
|
+
*/
|
|
122
|
+
getTransactionId(sessionId) {
|
|
123
|
+
const session = this.sessions.get(sessionId);
|
|
124
|
+
return session?.txnId;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Check if session is in a transaction
|
|
128
|
+
*/
|
|
129
|
+
isInTransaction(sessionId) {
|
|
130
|
+
const session = this.sessions.get(sessionId);
|
|
131
|
+
return session?.inTransaction ?? false;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check if a session is expired
|
|
135
|
+
*/
|
|
136
|
+
isSessionExpired(session) {
|
|
137
|
+
return Date.now() - session.lastActivityAt > this.sessionTimeoutMs;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Cleanup expired sessions
|
|
141
|
+
* This is called periodically by the cleanup interval
|
|
142
|
+
*/
|
|
143
|
+
async cleanupExpiredSessions() {
|
|
144
|
+
const expiredSessions = [];
|
|
145
|
+
for (const [id, session] of this.sessions) {
|
|
146
|
+
if (this.isSessionExpired(session)) {
|
|
147
|
+
expiredSessions.push(id);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// End all expired sessions (this will also abort their transactions)
|
|
151
|
+
for (const sessionId of expiredSessions) {
|
|
152
|
+
await this.endSession(sessionId);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get all active sessions
|
|
157
|
+
*/
|
|
158
|
+
listSessions() {
|
|
159
|
+
const activeSessions = [];
|
|
160
|
+
for (const session of this.sessions.values()) {
|
|
161
|
+
if (!this.isSessionExpired(session)) {
|
|
162
|
+
activeSessions.push(session);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return activeSessions;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Get session count
|
|
169
|
+
*/
|
|
170
|
+
getSessionCount() {
|
|
171
|
+
return this.sessions.size;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get sessions with active transactions
|
|
175
|
+
*/
|
|
176
|
+
getSessionsWithTransactions() {
|
|
177
|
+
return this.listSessions().filter(s => s.inTransaction);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Refresh session timeout
|
|
181
|
+
*/
|
|
182
|
+
refreshSession(sessionId) {
|
|
183
|
+
return this.touchSession(sessionId);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Close the session engine and cleanup
|
|
187
|
+
*/
|
|
188
|
+
close() {
|
|
189
|
+
if (this.cleanupInterval) {
|
|
190
|
+
clearInterval(this.cleanupInterval);
|
|
191
|
+
this.cleanupInterval = undefined;
|
|
192
|
+
}
|
|
193
|
+
// Clear all sessions
|
|
194
|
+
this.sessions.clear();
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get or create a session for a given session ID
|
|
198
|
+
* Useful for handling MongoDB driver session requests
|
|
199
|
+
*/
|
|
200
|
+
getOrCreateSession(sessionId) {
|
|
201
|
+
let session = this.getSession(sessionId);
|
|
202
|
+
if (!session) {
|
|
203
|
+
session = this.startSession(sessionId);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
this.touchSession(sessionId);
|
|
207
|
+
}
|
|
208
|
+
return session;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Extract session ID from MongoDB lsid (logical session ID)
|
|
212
|
+
*/
|
|
213
|
+
static extractSessionId(lsid) {
|
|
214
|
+
if (!lsid)
|
|
215
|
+
return undefined;
|
|
216
|
+
// MongoDB session ID format: { id: UUID }
|
|
217
|
+
if (lsid.id) {
|
|
218
|
+
if (lsid.id instanceof plugins.bson.UUID) {
|
|
219
|
+
return lsid.id.toHexString();
|
|
220
|
+
}
|
|
221
|
+
if (typeof lsid.id === 'string') {
|
|
222
|
+
return lsid.id;
|
|
223
|
+
}
|
|
224
|
+
if (lsid.id.$binary?.base64) {
|
|
225
|
+
// Binary UUID format
|
|
226
|
+
return Buffer.from(lsid.id.$binary.base64, 'base64').toString('hex');
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2Vzc2lvbkVuZ2luZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL3RzbWRiL2VuZ2luZS9TZXNzaW9uRW5naW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFpQy9DOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7SUFDaEIsUUFBUSxHQUEwQixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQzVDLGdCQUFnQixDQUFTO0lBQ3pCLGVBQWUsQ0FBa0M7SUFDakQsaUJBQWlCLENBQXFCO0lBRTlDLFlBQVksT0FBK0I7UUFDekMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLE9BQU8sRUFBRSxnQkFBZ0IsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDLHFCQUFxQjtRQUMxRixNQUFNLGlCQUFpQixHQUFHLE9BQU8sRUFBRSxpQkFBaUIsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsbUJBQW1CO1FBRXRGLHlCQUF5QjtRQUN6QixJQUFJLENBQUMsZUFBZSxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUU7WUFDdEMsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7UUFDaEMsQ0FBQyxFQUFFLGlCQUFpQixDQUFDLENBQUM7SUFDeEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsb0JBQW9CLENBQUMsTUFBeUI7UUFDNUMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLE1BQU0sQ0FBQztJQUNsQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxZQUFZLENBQUMsU0FBa0IsRUFBRSxRQUE4QjtRQUM3RCxNQUFNLEVBQUUsR0FBRyxTQUFTLElBQUksSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzlELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUV2QixNQUFNLE9BQU8sR0FBYTtZ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
|
package/dist_ts/tsmdb/index.d.ts
CHANGED
|
@@ -7,13 +7,20 @@ export type { IStorageAdapter } from './storage/IStorageAdapter.js';
|
|
|
7
7
|
export { MemoryStorageAdapter } from './storage/MemoryStorageAdapter.js';
|
|
8
8
|
export { FileStorageAdapter } from './storage/FileStorageAdapter.js';
|
|
9
9
|
export { OpLog } from './storage/OpLog.js';
|
|
10
|
+
export { WAL } from './storage/WAL.js';
|
|
11
|
+
export type { IWalEntry, TWalOperation } from './storage/WAL.js';
|
|
10
12
|
export { QueryEngine } from './engine/QueryEngine.js';
|
|
11
13
|
export { UpdateEngine } from './engine/UpdateEngine.js';
|
|
12
14
|
export { AggregationEngine } from './engine/AggregationEngine.js';
|
|
13
15
|
export { IndexEngine } from './engine/IndexEngine.js';
|
|
14
16
|
export { TransactionEngine } from './engine/TransactionEngine.js';
|
|
17
|
+
export { QueryPlanner } from './engine/QueryPlanner.js';
|
|
18
|
+
export type { IQueryPlan, TQueryPlanType } from './engine/QueryPlanner.js';
|
|
19
|
+
export { SessionEngine } from './engine/SessionEngine.js';
|
|
20
|
+
export type { ISession, ISessionEngineOptions } from './engine/SessionEngine.js';
|
|
15
21
|
export { TsmdbServer } from './server/TsmdbServer.js';
|
|
16
22
|
export type { ITsmdbServerOptions } from './server/TsmdbServer.js';
|
|
17
23
|
export { WireProtocol } from './server/WireProtocol.js';
|
|
18
24
|
export { CommandRouter } from './server/CommandRouter.js';
|
|
19
25
|
export type { ICommandHandler, IHandlerContext, ICursorState } from './server/CommandRouter.js';
|
|
26
|
+
export * from './utils/checksum.js';
|
package/dist_ts/tsmdb/index.js
CHANGED
|
@@ -12,15 +12,20 @@ export * from './errors/TsmdbErrors.js';
|
|
|
12
12
|
export { MemoryStorageAdapter } from './storage/MemoryStorageAdapter.js';
|
|
13
13
|
export { FileStorageAdapter } from './storage/FileStorageAdapter.js';
|
|
14
14
|
export { OpLog } from './storage/OpLog.js';
|
|
15
|
+
export { WAL } from './storage/WAL.js';
|
|
15
16
|
// Export engines
|
|
16
17
|
export { QueryEngine } from './engine/QueryEngine.js';
|
|
17
18
|
export { UpdateEngine } from './engine/UpdateEngine.js';
|
|
18
19
|
export { AggregationEngine } from './engine/AggregationEngine.js';
|
|
19
20
|
export { IndexEngine } from './engine/IndexEngine.js';
|
|
20
21
|
export { TransactionEngine } from './engine/TransactionEngine.js';
|
|
22
|
+
export { QueryPlanner } from './engine/QueryPlanner.js';
|
|
23
|
+
export { SessionEngine } from './engine/SessionEngine.js';
|
|
21
24
|
// Export server (the main entry point for using TsmDB)
|
|
22
25
|
export { TsmdbServer } from './server/TsmdbServer.js';
|
|
23
26
|
// Export wire protocol utilities (for advanced usage)
|
|
24
27
|
export { WireProtocol } from './server/WireProtocol.js';
|
|
25
28
|
export { CommandRouter } from './server/CommandRouter.js';
|
|
26
|
-
|
|
29
|
+
// Export utilities
|
|
30
|
+
export * from './utils/checksum.js';
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy90c21kYi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxRUFBcUU7QUFDckUsNERBQTREO0FBRTVELHFDQUFxQztBQUNyQyxPQUFPLEtBQUssT0FBTyxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztBQUVuQixvQ0FBb0M7QUFDcEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRTNFLG1CQUFtQjtBQUNuQixjQUFjLHVCQUF1QixDQUFDO0FBRXRDLGdCQUFnQjtBQUNoQixjQUFjLHlCQUF5QixDQUFDO0FBSXhDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMzQyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFHdkMsaUJBQWlCO0FBQ2pCLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3RELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUV4RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFHMUQsdURBQXVEO0FBQ3ZELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUd0RCxzREFBc0Q7QUFDdEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUcxRCxtQkFBbUI7QUFDbkIsY0FBYyxxQkFBcUIsQ0FBQyJ9
|
|
@@ -2,6 +2,9 @@ import * as plugins from '../tsmdb.plugins.js';
|
|
|
2
2
|
import type { IStorageAdapter } from '../storage/IStorageAdapter.js';
|
|
3
3
|
import type { IParsedCommand } from './WireProtocol.js';
|
|
4
4
|
import type { TsmdbServer } from './TsmdbServer.js';
|
|
5
|
+
import { IndexEngine } from '../engine/IndexEngine.js';
|
|
6
|
+
import { TransactionEngine } from '../engine/TransactionEngine.js';
|
|
7
|
+
import { SessionEngine } from '../engine/SessionEngine.js';
|
|
5
8
|
/**
|
|
6
9
|
* Handler context passed to command handlers
|
|
7
10
|
*/
|
|
@@ -11,6 +14,16 @@ export interface IHandlerContext {
|
|
|
11
14
|
database: string;
|
|
12
15
|
command: plugins.bson.Document;
|
|
13
16
|
documentSequences?: Map<string, plugins.bson.Document[]>;
|
|
17
|
+
/** Get or create an IndexEngine for a collection */
|
|
18
|
+
getIndexEngine: (collName: string) => IndexEngine;
|
|
19
|
+
/** Transaction engine instance */
|
|
20
|
+
transactionEngine: TransactionEngine;
|
|
21
|
+
/** Current transaction ID (if in a transaction) */
|
|
22
|
+
txnId?: string;
|
|
23
|
+
/** Session ID (from lsid) */
|
|
24
|
+
sessionId?: string;
|
|
25
|
+
/** Session engine instance */
|
|
26
|
+
sessionEngine: SessionEngine;
|
|
14
27
|
}
|
|
15
28
|
/**
|
|
16
29
|
* Command handler interface
|
|
@@ -27,7 +40,18 @@ export declare class CommandRouter {
|
|
|
27
40
|
private handlers;
|
|
28
41
|
private cursors;
|
|
29
42
|
private cursorIdCounter;
|
|
43
|
+
private indexEngines;
|
|
44
|
+
private transactionEngine;
|
|
45
|
+
private sessionEngine;
|
|
30
46
|
constructor(storage: IStorageAdapter, server: TsmdbServer);
|
|
47
|
+
/**
|
|
48
|
+
* Get or create an IndexEngine for a database.collection
|
|
49
|
+
*/
|
|
50
|
+
getIndexEngine(dbName: string, collName: string): IndexEngine;
|
|
51
|
+
/**
|
|
52
|
+
* Clear index engine cache for a collection (used when collection is dropped)
|
|
53
|
+
*/
|
|
54
|
+
clearIndexEngineCache(dbName: string, collName?: string): void;
|
|
31
55
|
/**
|
|
32
56
|
* Register all command handlers
|
|
33
57
|
*/
|
|
@@ -36,6 +60,18 @@ export declare class CommandRouter {
|
|
|
36
60
|
* Route a command to its handler
|
|
37
61
|
*/
|
|
38
62
|
route(parsedCommand: IParsedCommand): Promise<plugins.bson.Document>;
|
|
63
|
+
/**
|
|
64
|
+
* Close the command router and cleanup resources
|
|
65
|
+
*/
|
|
66
|
+
close(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Get session engine (for administrative purposes)
|
|
69
|
+
*/
|
|
70
|
+
getSessionEngine(): SessionEngine;
|
|
71
|
+
/**
|
|
72
|
+
* Get transaction engine (for administrative purposes)
|
|
73
|
+
*/
|
|
74
|
+
getTransactionEngine(): TransactionEngine;
|
|
39
75
|
}
|
|
40
76
|
/**
|
|
41
77
|
* Cursor state for multi-batch queries
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import * as plugins from '../tsmdb.plugins.js';
|
|
2
|
+
import { IndexEngine } from '../engine/IndexEngine.js';
|
|
3
|
+
import { TransactionEngine } from '../engine/TransactionEngine.js';
|
|
4
|
+
import { SessionEngine } from '../engine/SessionEngine.js';
|
|
2
5
|
// Import handlers
|
|
3
6
|
import { HelloHandler } from './handlers/HelloHandler.js';
|
|
4
7
|
import { InsertHandler } from './handlers/InsertHandler.js';
|
|
@@ -18,11 +21,49 @@ export class CommandRouter {
|
|
|
18
21
|
// Cursor state for getMore operations
|
|
19
22
|
cursors = new Map();
|
|
20
23
|
cursorIdCounter = BigInt(1);
|
|
24
|
+
// Index engine cache: db.collection -> IndexEngine
|
|
25
|
+
indexEngines = new Map();
|
|
26
|
+
// Transaction engine (shared across all handlers)
|
|
27
|
+
transactionEngine;
|
|
28
|
+
// Session engine (shared across all handlers)
|
|
29
|
+
sessionEngine;
|
|
21
30
|
constructor(storage, server) {
|
|
22
31
|
this.storage = storage;
|
|
23
32
|
this.server = server;
|
|
33
|
+
this.transactionEngine = new TransactionEngine(storage);
|
|
34
|
+
this.sessionEngine = new SessionEngine();
|
|
35
|
+
// Link session engine to transaction engine for auto-abort on session expiry
|
|
36
|
+
this.sessionEngine.setTransactionEngine(this.transactionEngine);
|
|
24
37
|
this.registerHandlers();
|
|
25
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Get or create an IndexEngine for a database.collection
|
|
41
|
+
*/
|
|
42
|
+
getIndexEngine(dbName, collName) {
|
|
43
|
+
const key = `${dbName}.${collName}`;
|
|
44
|
+
let engine = this.indexEngines.get(key);
|
|
45
|
+
if (!engine) {
|
|
46
|
+
engine = new IndexEngine(dbName, collName, this.storage);
|
|
47
|
+
this.indexEngines.set(key, engine);
|
|
48
|
+
}
|
|
49
|
+
return engine;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Clear index engine cache for a collection (used when collection is dropped)
|
|
53
|
+
*/
|
|
54
|
+
clearIndexEngineCache(dbName, collName) {
|
|
55
|
+
if (collName) {
|
|
56
|
+
this.indexEngines.delete(`${dbName}.${collName}`);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// Clear all engines for the database
|
|
60
|
+
for (const key of this.indexEngines.keys()) {
|
|
61
|
+
if (key.startsWith(`${dbName}.`)) {
|
|
62
|
+
this.indexEngines.delete(key);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
26
67
|
/**
|
|
27
68
|
* Register all command handlers
|
|
28
69
|
*/
|
|
@@ -87,6 +128,27 @@ export class CommandRouter {
|
|
|
87
128
|
*/
|
|
88
129
|
async route(parsedCommand) {
|
|
89
130
|
const { commandName, command, database, documentSequences } = parsedCommand;
|
|
131
|
+
// Extract session ID from lsid using SessionEngine helper
|
|
132
|
+
let sessionId = SessionEngine.extractSessionId(command.lsid);
|
|
133
|
+
let txnId;
|
|
134
|
+
// If we have a session ID, register/touch the session
|
|
135
|
+
if (sessionId) {
|
|
136
|
+
this.sessionEngine.getOrCreateSession(sessionId);
|
|
137
|
+
}
|
|
138
|
+
// Check if this starts a new transaction
|
|
139
|
+
if (command.startTransaction && sessionId) {
|
|
140
|
+
txnId = this.transactionEngine.startTransaction(sessionId);
|
|
141
|
+
this.sessionEngine.startTransaction(sessionId, txnId, command.txnNumber);
|
|
142
|
+
}
|
|
143
|
+
else if (sessionId && this.sessionEngine.isInTransaction(sessionId)) {
|
|
144
|
+
// Continue existing transaction
|
|
145
|
+
txnId = this.sessionEngine.getTransactionId(sessionId);
|
|
146
|
+
// Verify transaction is still active
|
|
147
|
+
if (txnId && !this.transactionEngine.isActive(txnId)) {
|
|
148
|
+
this.sessionEngine.endTransaction(sessionId);
|
|
149
|
+
txnId = undefined;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
90
152
|
// Create handler context
|
|
91
153
|
const context = {
|
|
92
154
|
storage: this.storage,
|
|
@@ -94,6 +156,11 @@ export class CommandRouter {
|
|
|
94
156
|
database,
|
|
95
157
|
command,
|
|
96
158
|
documentSequences,
|
|
159
|
+
getIndexEngine: (collName) => this.getIndexEngine(database, collName),
|
|
160
|
+
transactionEngine: this.transactionEngine,
|
|
161
|
+
sessionEngine: this.sessionEngine,
|
|
162
|
+
txnId,
|
|
163
|
+
sessionId,
|
|
97
164
|
};
|
|
98
165
|
// Find handler
|
|
99
166
|
const handler = this.handlers.get(commandName);
|
|
@@ -128,5 +195,28 @@ export class CommandRouter {
|
|
|
128
195
|
};
|
|
129
196
|
}
|
|
130
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* Close the command router and cleanup resources
|
|
200
|
+
*/
|
|
201
|
+
close() {
|
|
202
|
+
// Close session engine (stops cleanup interval, clears sessions)
|
|
203
|
+
this.sessionEngine.close();
|
|
204
|
+
// Clear cursors
|
|
205
|
+
this.cursors.clear();
|
|
206
|
+
// Clear index engine cache
|
|
207
|
+
this.indexEngines.clear();
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get session engine (for administrative purposes)
|
|
211
|
+
*/
|
|
212
|
+
getSessionEngine() {
|
|
213
|
+
return this.sessionEngine;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Get transaction engine (for administrative purposes)
|
|
217
|
+
*/
|
|
218
|
+
getTransactionEngine() {
|
|
219
|
+
return this.transactionEngine;
|
|
220
|
+
}
|
|
131
221
|
}
|
|
132
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
222
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tbWFuZFJvdXRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL3RzbWRiL3NlcnZlci9Db21tYW5kUm91dGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFJL0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUUzRCxrQkFBa0I7QUFDbEIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzFELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzVELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDMUQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBOEIxRDs7R0FFRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBQ2hCLE9BQU8sQ0FBa0I7SUFDekIsTUFBTSxDQUFjO0lBQ3BCLFFBQVEsR0FBaUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUUzRCxzQ0FBc0M7SUFDOUIsT0FBTyxHQUE4QixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQy9DLGVBQWUsR0FBVyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFNUMsbURBQW1EO0lBQzNDLFlBQVksR0FBNkIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUUzRCxrREFBa0Q7SUFDMUMsaUJBQWlCLENBQW9CO0lBRTdDLDhDQUE4QztJQUN0QyxhQUFhLENBQWdCO0lBRXJDLFlBQVksT0FBd0IsRUFBRSxNQUFtQjtRQUN2RCxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN4RCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksYUFBYSxFQUFFLENBQUM7UUFDekMsNkVBQTZFO1FBQzdFLElBQUksQ0FBQyxhQUFhLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDaEUsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsY0FBYyxDQUFDLE1BQWMsRUFBRSxRQUFnQjtRQUM3QyxNQUFNLEdBQUcsR0FBRyxHQUFHLE1BQU0sSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUNwQyxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixNQUFNLEdBQUcsSUFBSSxXQUFXLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDekQsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3JDLENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxxQkFBcUIsQ0FBQyxNQUFjLEVBQUUsUUFBaUI7UUFDckQsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsTUFBTSxJQUFJLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDcEQsQ0FBQzthQUFNLENBQUM7WUFDTixxQ0FBcUM7WUFDckMsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7Z0JBQzNDLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDakMsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ2hDLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNLLGdCQUFnQjtRQUN0Qiw2Q0FBNkM7UUFDN0MsTUFBTSxZQUFZLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUN4QyxNQUFNLFdBQVcsR0FBRyxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDO1FBQ2hGLE1BQU0sYUFBYSxHQUFHLElBQUksYUFBYSxFQUFFLENBQUM7UUFDMUMsTUFBTSxhQUFhLEdBQUcsSUFBSSxhQUFhLEVBQUUsQ0FBQztRQUMxQyxNQUFNLGFBQWEsR0FBRyxJQUFJLGFBQWEsRUFBRSxDQUFDO1FBQzFDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDO1FBQzFGLE1BQU0sWUFBWSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDeEMsTUFBTSxZQUFZLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUV4QyxxQkFBcUI7UUFDckIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUM1QyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFFNUMsZ0JBQWdCO1FBQ2hCLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsQ0FBQztRQUN2QyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxhQUFhLENBQUMsQ0FBQztRQUMzQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxlQUFlLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQzFDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUU5QyxjQUFjO1FBQ2QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ3hDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUUzQyxtQkFBbUI7UUFDbkIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsZUFBZSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQ2pELElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUMvQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFFL0MsNEJBQTRCO1FBQzVCLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxZQUFZLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxlQUFlLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDbkQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQ3hDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUNoRCxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDMUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUM3QyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDOUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzFDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUM1QyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDNUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzdDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUNoRCxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDL0MsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDcEQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDckQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzdDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUMzQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDN0MsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLGtCQUFrQixFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxLQUFLLENBQUMsYUFBNkI7UUFDdkMsTUFBTSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLEdBQUcsYUFBYSxDQUFDO1FBRTVFLDBEQUEwRDtRQUMxRCxJQUFJLFNBQVMsR0FBRyxhQUFhLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdELElBQUksS0FBeUIsQ0FBQztRQUU5QixzREFBc0Q7UUFDdEQsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNkLElBQUksQ0FBQyxhQUFhLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDbkQsQ0FBQztRQUVELHlDQUF5QztRQUN6QyxJQUFJLE9BQU8sQ0FBQyxnQkFBZ0IsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUMxQyxLQUFLLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQzNELElBQUksQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLEtBQUssRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDM0UsQ0FBQzthQUFNLElBQUksU0FBUyxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDdEUsZ0NBQWdDO1lBQ2hDLEtBQUssR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3ZELHFDQUFxQztZQUNyQyxJQUFJLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDckQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQzdDLEtBQUssR0FBRyxTQUFTLENBQUM7WUFDcEIsQ0FBQztRQUNILENBQUM7UUFFRCx5QkFBeUI7UUFDekIsTUFBTSxPQUFPLEdBQW9CO1lBQy9CLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztZQUNyQixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDbkIsUUFBUTtZQUNSLE9BQU87WUFDUCxpQkFBaUI7WUFDakIsY0FBYyxFQUFFLENBQUMsUUFBZ0IsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDO1lBQzdFLGlCQUFpQixFQUFFLElBQUksQ0FBQyxpQkFBaUI7WUFDekMsYUFBYSxFQUFFLElBQUksQ0FBQyxhQUFhO1lBQ2pDLEtBQUs7WUFDTCxTQUFTO1NBQ1YsQ0FBQztRQUVGLGVBQWU7UUFDZixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUUvQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixrQkFBa0I7WUFDbEIsT0FBTztnQkFDTCxFQUFFLEVBQUUsQ0FBQztnQkFDTCxNQUFNLEVBQUUscUJBQXFCLFdBQVcsR0FBRztnQkFDM0MsSUFBSSxFQUFFLEVBQUU7Z0JBQ1IsUUFBUSxFQUFFLGlCQUFpQjthQUM1QixDQUFDO1FBQ0osQ0FBQztRQUVELElBQUksQ0FBQztZQUNILE9BQU8sTUFBTSxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZDLENBQUM7UUFBQyxPQUFPLEtBQVUsRUFBRSxDQUFDO1lBQ3BCLDJCQUEyQjtZQUMzQixJQUFJLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDZixPQUFPO29CQUNMLEVBQUUsRUFBRSxDQUFDO29CQUNMLE1BQU0sRUFBRSxLQUFLLENBQUMsT0FBTztvQkFDckIsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO29CQUNoQixRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVEsSUFBSSxjQUFjO2lCQUMzQyxDQUFDO1lBQ0osQ0FBQztZQUVELGdCQUFnQjtZQUNoQixPQUFPO2dCQUNMLEVBQUUsRUFBRSxDQUFDO2dCQUNMLE1BQU0sRUFBRSxLQUFLLENBQUMsT0FBTyxJQUFJLGdCQUFnQjtnQkFDekMsSUFBSSxFQUFFLENBQUM7Z0JBQ1AsUUFBUSxFQUFFLGVBQWU7YUFDMUIsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLO1FBQ0gsaUVBQWlFO1FBQ2pFLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDM0IsZ0JBQWdCO1FBQ2hCLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDckIsMkJBQTJCO1FBQzNCLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsZ0JBQWdCO1FBQ2QsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDO0lBQzVCLENBQUM7SUFFRDs7T0FFRztJQUNILG9CQUFvQjtRQUNsQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztJQUNoQyxDQUFDO0NBQ0YifQ==
|
|
@@ -111,6 +111,8 @@ export class TsmdbServer {
|
|
|
111
111
|
conn.socket.destroy();
|
|
112
112
|
}
|
|
113
113
|
this.connections.clear();
|
|
114
|
+
// Close command router (cleans up session engine, cursors, etc.)
|
|
115
|
+
this.commandRouter.close();
|
|
114
116
|
// Close storage
|
|
115
117
|
await this.storage.close();
|
|
116
118
|
return new Promise((resolve) => {
|
|
@@ -224,4 +226,4 @@ export class TsmdbServer {
|
|
|
224
226
|
return this.options.host;
|
|
225
227
|
}
|
|
226
228
|
}
|
|
227
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
229
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHNtZGJTZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90c21kYi9zZXJ2ZXIvVHNtZGJTZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEdBQUcsTUFBTSxLQUFLLENBQUM7QUFDM0IsT0FBTyxLQUFLLE9BQU8sTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzNELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNuRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUMxRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQWdDdEU7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gsTUFBTSxPQUFPLFdBQVc7SUFDZCxPQUFPLENBQWdDO0lBQ3ZDLE1BQU0sR0FBc0IsSUFBSSxDQUFDO0lBQ2pDLE9BQU8sQ0FBa0I7SUFDekIsYUFBYSxDQUFnQjtJQUM3QixXQUFXLEdBQWtDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDdkQsbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO0lBQ3hCLFNBQVMsR0FBRyxLQUFLLENBQUM7SUFDbEIsU0FBUyxHQUFTLElBQUksSUFBSSxFQUFFLENBQUM7SUFFckMsWUFBWSxVQUErQixFQUFFO1FBQzNDLElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDYixJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksSUFBSSxLQUFLO1lBQzNCLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxJQUFJLFdBQVc7WUFDakMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPLElBQUksUUFBUTtZQUNwQyxXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVcsSUFBSSxRQUFRO1lBQzVDLFdBQVcsRUFBRSxPQUFPLENBQUMsV0FBVyxJQUFJLEVBQUU7WUFDdEMs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
|