@push.rocks/smartdb 1.0.1 → 2.1.1

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 (126) hide show
  1. package/.smartconfig.json +18 -4
  2. package/dist_rust/rustdb_linux_amd64 +0 -0
  3. package/dist_rust/rustdb_linux_arm64 +0 -0
  4. package/dist_ts/00_commitinfo_data.js +3 -3
  5. package/dist_ts/index.d.ts +1 -0
  6. package/dist_ts/ts_local/classes.localsmartdb.d.ts +5 -5
  7. package/dist_ts/ts_local/classes.localsmartdb.js +7 -9
  8. package/dist_ts/ts_local/plugins.d.ts +1 -2
  9. package/dist_ts/ts_local/plugins.js +3 -3
  10. package/dist_ts/ts_smartdb/index.d.ts +2 -24
  11. package/dist_ts/ts_smartdb/index.js +4 -29
  12. package/dist_ts/ts_smartdb/plugins.d.ts +2 -10
  13. package/dist_ts/ts_smartdb/plugins.js +3 -13
  14. package/dist_ts/ts_smartdb/rust-db-bridge.d.ts +122 -0
  15. package/dist_ts/ts_smartdb/rust-db-bridge.js +113 -0
  16. package/dist_ts/ts_smartdb/server/SmartdbServer.d.ts +39 -37
  17. package/dist_ts/ts_smartdb/server/SmartdbServer.js +87 -206
  18. package/dist_ts/ts_smartdb/server/index.d.ts +0 -4
  19. package/dist_ts/ts_smartdb/server/index.js +1 -5
  20. package/dist_ts_debugserver/bundled.d.ts +4 -0
  21. package/dist_ts_debugserver/bundled.js +12 -0
  22. package/dist_ts_debugserver/classes.debugserver.d.ts +36 -0
  23. package/dist_ts_debugserver/classes.debugserver.js +95 -0
  24. package/dist_ts_debugserver/index.d.ts +2 -0
  25. package/dist_ts_debugserver/index.js +2 -0
  26. package/dist_ts_debugserver/plugins.d.ts +2 -0
  27. package/dist_ts_debugserver/plugins.js +3 -0
  28. package/dist_ts_debugui/index.d.ts +2 -0
  29. package/dist_ts_debugui/index.js +2 -0
  30. package/dist_ts_debugui/plugins.d.ts +1 -0
  31. package/dist_ts_debugui/plugins.js +2 -0
  32. package/dist_ts_debugui/smartdb-debugui.d.ts +62 -0
  33. package/dist_ts_debugui/smartdb-debugui.js +1132 -0
  34. package/license +3 -1
  35. package/package.json +14 -13
  36. package/readme.md +209 -177
  37. package/ts/00_commitinfo_data.ts +2 -2
  38. package/ts/index.ts +11 -0
  39. package/ts/ts_local/classes.localsmartdb.ts +5 -6
  40. package/ts/ts_local/plugins.ts +1 -3
  41. package/ts/ts_smartdb/index.ts +14 -41
  42. package/ts/ts_smartdb/plugins.ts +2 -15
  43. package/ts/ts_smartdb/rust-db-bridge.ts +262 -0
  44. package/ts/ts_smartdb/server/SmartdbServer.ts +115 -246
  45. package/ts/ts_smartdb/server/index.ts +0 -7
  46. package/dist_ts/ts_smartdb/engine/AggregationEngine.d.ts +0 -66
  47. package/dist_ts/ts_smartdb/engine/AggregationEngine.js +0 -189
  48. package/dist_ts/ts_smartdb/engine/IndexEngine.d.ts +0 -97
  49. package/dist_ts/ts_smartdb/engine/IndexEngine.js +0 -678
  50. package/dist_ts/ts_smartdb/engine/QueryEngine.d.ts +0 -54
  51. package/dist_ts/ts_smartdb/engine/QueryEngine.js +0 -271
  52. package/dist_ts/ts_smartdb/engine/QueryPlanner.d.ts +0 -64
  53. package/dist_ts/ts_smartdb/engine/QueryPlanner.js +0 -308
  54. package/dist_ts/ts_smartdb/engine/SessionEngine.d.ts +0 -117
  55. package/dist_ts/ts_smartdb/engine/SessionEngine.js +0 -232
  56. package/dist_ts/ts_smartdb/engine/TransactionEngine.d.ts +0 -85
  57. package/dist_ts/ts_smartdb/engine/TransactionEngine.js +0 -287
  58. package/dist_ts/ts_smartdb/engine/UpdateEngine.d.ts +0 -47
  59. package/dist_ts/ts_smartdb/engine/UpdateEngine.js +0 -461
  60. package/dist_ts/ts_smartdb/errors/SmartdbErrors.d.ts +0 -100
  61. package/dist_ts/ts_smartdb/errors/SmartdbErrors.js +0 -155
  62. package/dist_ts/ts_smartdb/server/CommandRouter.d.ts +0 -87
  63. package/dist_ts/ts_smartdb/server/CommandRouter.js +0 -222
  64. package/dist_ts/ts_smartdb/server/WireProtocol.d.ts +0 -117
  65. package/dist_ts/ts_smartdb/server/WireProtocol.js +0 -298
  66. package/dist_ts/ts_smartdb/server/handlers/AdminHandler.d.ts +0 -100
  67. package/dist_ts/ts_smartdb/server/handlers/AdminHandler.js +0 -668
  68. package/dist_ts/ts_smartdb/server/handlers/AggregateHandler.d.ts +0 -31
  69. package/dist_ts/ts_smartdb/server/handlers/AggregateHandler.js +0 -277
  70. package/dist_ts/ts_smartdb/server/handlers/DeleteHandler.d.ts +0 -8
  71. package/dist_ts/ts_smartdb/server/handlers/DeleteHandler.js +0 -95
  72. package/dist_ts/ts_smartdb/server/handlers/FindHandler.d.ts +0 -31
  73. package/dist_ts/ts_smartdb/server/handlers/FindHandler.js +0 -291
  74. package/dist_ts/ts_smartdb/server/handlers/HelloHandler.d.ts +0 -11
  75. package/dist_ts/ts_smartdb/server/handlers/HelloHandler.js +0 -62
  76. package/dist_ts/ts_smartdb/server/handlers/IndexHandler.d.ts +0 -20
  77. package/dist_ts/ts_smartdb/server/handlers/IndexHandler.js +0 -183
  78. package/dist_ts/ts_smartdb/server/handlers/InsertHandler.d.ts +0 -8
  79. package/dist_ts/ts_smartdb/server/handlers/InsertHandler.js +0 -79
  80. package/dist_ts/ts_smartdb/server/handlers/UpdateHandler.d.ts +0 -24
  81. package/dist_ts/ts_smartdb/server/handlers/UpdateHandler.js +0 -296
  82. package/dist_ts/ts_smartdb/server/handlers/index.d.ts +0 -8
  83. package/dist_ts/ts_smartdb/server/handlers/index.js +0 -10
  84. package/dist_ts/ts_smartdb/storage/FileStorageAdapter.d.ts +0 -85
  85. package/dist_ts/ts_smartdb/storage/FileStorageAdapter.js +0 -465
  86. package/dist_ts/ts_smartdb/storage/IStorageAdapter.d.ts +0 -145
  87. package/dist_ts/ts_smartdb/storage/IStorageAdapter.js +0 -2
  88. package/dist_ts/ts_smartdb/storage/MemoryStorageAdapter.d.ts +0 -67
  89. package/dist_ts/ts_smartdb/storage/MemoryStorageAdapter.js +0 -378
  90. package/dist_ts/ts_smartdb/storage/OpLog.d.ts +0 -93
  91. package/dist_ts/ts_smartdb/storage/OpLog.js +0 -221
  92. package/dist_ts/ts_smartdb/storage/WAL.d.ts +0 -117
  93. package/dist_ts/ts_smartdb/storage/WAL.js +0 -286
  94. package/dist_ts/ts_smartdb/types/interfaces.d.ts +0 -363
  95. package/dist_ts/ts_smartdb/types/interfaces.js +0 -2
  96. package/dist_ts/ts_smartdb/utils/checksum.d.ts +0 -30
  97. package/dist_ts/ts_smartdb/utils/checksum.js +0 -77
  98. package/dist_ts/ts_smartdb/utils/index.d.ts +0 -1
  99. package/dist_ts/ts_smartdb/utils/index.js +0 -2
  100. package/ts/ts_smartdb/engine/AggregationEngine.ts +0 -283
  101. package/ts/ts_smartdb/engine/IndexEngine.ts +0 -798
  102. package/ts/ts_smartdb/engine/QueryEngine.ts +0 -301
  103. package/ts/ts_smartdb/engine/QueryPlanner.ts +0 -393
  104. package/ts/ts_smartdb/engine/SessionEngine.ts +0 -292
  105. package/ts/ts_smartdb/engine/TransactionEngine.ts +0 -351
  106. package/ts/ts_smartdb/engine/UpdateEngine.ts +0 -506
  107. package/ts/ts_smartdb/errors/SmartdbErrors.ts +0 -181
  108. package/ts/ts_smartdb/server/CommandRouter.ts +0 -289
  109. package/ts/ts_smartdb/server/WireProtocol.ts +0 -416
  110. package/ts/ts_smartdb/server/handlers/AdminHandler.ts +0 -719
  111. package/ts/ts_smartdb/server/handlers/AggregateHandler.ts +0 -342
  112. package/ts/ts_smartdb/server/handlers/DeleteHandler.ts +0 -115
  113. package/ts/ts_smartdb/server/handlers/FindHandler.ts +0 -330
  114. package/ts/ts_smartdb/server/handlers/HelloHandler.ts +0 -78
  115. package/ts/ts_smartdb/server/handlers/IndexHandler.ts +0 -207
  116. package/ts/ts_smartdb/server/handlers/InsertHandler.ts +0 -97
  117. package/ts/ts_smartdb/server/handlers/UpdateHandler.ts +0 -344
  118. package/ts/ts_smartdb/server/handlers/index.ts +0 -10
  119. package/ts/ts_smartdb/storage/FileStorageAdapter.ts +0 -562
  120. package/ts/ts_smartdb/storage/IStorageAdapter.ts +0 -208
  121. package/ts/ts_smartdb/storage/MemoryStorageAdapter.ts +0 -455
  122. package/ts/ts_smartdb/storage/OpLog.ts +0 -282
  123. package/ts/ts_smartdb/storage/WAL.ts +0 -375
  124. package/ts/ts_smartdb/types/interfaces.ts +0 -433
  125. package/ts/ts_smartdb/utils/checksum.ts +0 -88
  126. package/ts/ts_smartdb/utils/index.ts +0 -1
@@ -1,221 +0,0 @@
1
- import * as plugins from '../plugins.js';
2
- /**
3
- * Operation Log for tracking all mutations
4
- * Used primarily for change stream support
5
- */
6
- export class OpLog {
7
- storage;
8
- counter = 0;
9
- listeners = [];
10
- constructor(storage) {
11
- this.storage = storage;
12
- }
13
- /**
14
- * Generate a new timestamp for oplog entries
15
- */
16
- generateTimestamp() {
17
- this.counter++;
18
- return new plugins.bson.Timestamp({ t: Math.floor(Date.now() / 1000), i: this.counter });
19
- }
20
- /**
21
- * Generate a resume token from a timestamp
22
- */
23
- generateResumeToken(ts) {
24
- // Create a resume token similar to MongoDB's format
25
- // It's a base64-encoded BSON document containing the timestamp
26
- const tokenData = {
27
- _data: Buffer.from(JSON.stringify({
28
- ts: { t: ts.high, i: ts.low },
29
- version: 1,
30
- })).toString('base64'),
31
- };
32
- return tokenData;
33
- }
34
- /**
35
- * Parse a resume token to get the timestamp
36
- */
37
- parseResumeToken(token) {
38
- try {
39
- const data = JSON.parse(Buffer.from(token._data, 'base64').toString('utf-8'));
40
- return new plugins.bson.Timestamp({ t: data.ts.t, i: data.ts.i });
41
- }
42
- catch {
43
- throw new Error('Invalid resume token');
44
- }
45
- }
46
- /**
47
- * Record an insert operation
48
- */
49
- async recordInsert(dbName, collName, document, txnInfo) {
50
- const entry = {
51
- ts: this.generateTimestamp(),
52
- op: 'i',
53
- ns: `${dbName}.${collName}`,
54
- o: document,
55
- ...txnInfo,
56
- };
57
- await this.storage.appendOpLog(entry);
58
- this.notifyListeners(entry);
59
- return entry;
60
- }
61
- /**
62
- * Record an update operation
63
- */
64
- async recordUpdate(dbName, collName, filter, update, txnInfo) {
65
- const entry = {
66
- ts: this.generateTimestamp(),
67
- op: 'u',
68
- ns: `${dbName}.${collName}`,
69
- o: update,
70
- o2: filter,
71
- ...txnInfo,
72
- };
73
- await this.storage.appendOpLog(entry);
74
- this.notifyListeners(entry);
75
- return entry;
76
- }
77
- /**
78
- * Record a delete operation
79
- */
80
- async recordDelete(dbName, collName, filter, txnInfo) {
81
- const entry = {
82
- ts: this.generateTimestamp(),
83
- op: 'd',
84
- ns: `${dbName}.${collName}`,
85
- o: filter,
86
- ...txnInfo,
87
- };
88
- await this.storage.appendOpLog(entry);
89
- this.notifyListeners(entry);
90
- return entry;
91
- }
92
- /**
93
- * Record a command (drop, rename, etc.)
94
- */
95
- async recordCommand(dbName, command) {
96
- const entry = {
97
- ts: this.generateTimestamp(),
98
- op: 'c',
99
- ns: `${dbName}.$cmd`,
100
- o: command,
101
- };
102
- await this.storage.appendOpLog(entry);
103
- this.notifyListeners(entry);
104
- return entry;
105
- }
106
- /**
107
- * Get oplog entries after a timestamp
108
- */
109
- async getEntriesAfter(ts, limit) {
110
- return this.storage.getOpLogAfter(ts, limit);
111
- }
112
- /**
113
- * Get the latest timestamp
114
- */
115
- async getLatestTimestamp() {
116
- return this.storage.getLatestOpLogTimestamp();
117
- }
118
- /**
119
- * Subscribe to oplog changes (for change streams)
120
- */
121
- subscribe(listener) {
122
- this.listeners.push(listener);
123
- return () => {
124
- const idx = this.listeners.indexOf(listener);
125
- if (idx >= 0) {
126
- this.listeners.splice(idx, 1);
127
- }
128
- };
129
- }
130
- /**
131
- * Notify all listeners of a new entry
132
- */
133
- notifyListeners(entry) {
134
- for (const listener of this.listeners) {
135
- try {
136
- listener(entry);
137
- }
138
- catch (error) {
139
- console.error('Error in oplog listener:', error);
140
- }
141
- }
142
- }
143
- /**
144
- * Convert an oplog entry to a change stream document
145
- */
146
- opLogEntryToChangeEvent(entry, fullDocument, fullDocumentBeforeChange) {
147
- const [db, coll] = entry.ns.split('.');
148
- const resumeToken = this.generateResumeToken(entry.ts);
149
- const baseEvent = {
150
- _id: resumeToken,
151
- ns: { db, coll: coll === '$cmd' ? undefined : coll },
152
- clusterTime: entry.ts,
153
- };
154
- switch (entry.op) {
155
- case 'i':
156
- return {
157
- ...baseEvent,
158
- operationType: 'insert',
159
- fullDocument: fullDocument || entry.o,
160
- documentKey: entry.o._id ? { _id: entry.o._id } : undefined,
161
- };
162
- case 'u':
163
- const updateEvent = {
164
- ...baseEvent,
165
- operationType: 'update',
166
- documentKey: entry.o2?._id ? { _id: entry.o2._id } : undefined,
167
- };
168
- if (fullDocument) {
169
- updateEvent.fullDocument = fullDocument;
170
- }
171
- if (fullDocumentBeforeChange) {
172
- updateEvent.fullDocumentBeforeChange = fullDocumentBeforeChange;
173
- }
174
- // Parse update description
175
- if (entry.o.$set || entry.o.$unset) {
176
- updateEvent.updateDescription = {
177
- updatedFields: entry.o.$set || {},
178
- removedFields: entry.o.$unset ? Object.keys(entry.o.$unset) : [],
179
- };
180
- }
181
- return updateEvent;
182
- case 'd':
183
- return {
184
- ...baseEvent,
185
- operationType: 'delete',
186
- documentKey: entry.o._id ? { _id: entry.o._id } : undefined,
187
- fullDocumentBeforeChange,
188
- };
189
- case 'c':
190
- if (entry.o.drop) {
191
- return {
192
- ...baseEvent,
193
- operationType: 'drop',
194
- ns: { db, coll: entry.o.drop },
195
- };
196
- }
197
- if (entry.o.dropDatabase) {
198
- return {
199
- ...baseEvent,
200
- operationType: 'dropDatabase',
201
- };
202
- }
203
- if (entry.o.renameCollection) {
204
- return {
205
- ...baseEvent,
206
- operationType: 'rename',
207
- };
208
- }
209
- return {
210
- ...baseEvent,
211
- operationType: 'invalidate',
212
- };
213
- default:
214
- return {
215
- ...baseEvent,
216
- operationType: 'invalidate',
217
- };
218
- }
219
- }
220
- }
221
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3BMb2cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90c19zbWFydGRiL3N0b3JhZ2UvT3BMb2cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFJekM7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLEtBQUs7SUFDUixPQUFPLENBQWtCO0lBQ3pCLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFDWixTQUFTLEdBQXdDLEVBQUUsQ0FBQztJQUU1RCxZQUFZLE9BQXdCO1FBQ2xDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQ3pCLENBQUM7SUFFRDs7T0FFRztJQUNILGlCQUFpQjtRQUNmLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNmLE9BQU8sSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDM0YsQ0FBQztJQUVEOztPQUVHO0lBQ0gsbUJBQW1CLENBQUMsRUFBMEI7UUFDNUMsb0RBQW9EO1FBQ3BELCtEQUErRDtRQUMvRCxNQUFNLFNBQVMsR0FBRztZQUNoQixLQUFLLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUNoQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsRUFBRTtnQkFDN0IsT0FBTyxFQUFFLENBQUM7YUFDWCxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDO1NBQ3ZCLENBQUM7UUFDRixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxnQkFBZ0IsQ0FBQyxL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
@@ -1,117 +0,0 @@
1
- import type { IStoredDocument } from '../types/interfaces.js';
2
- /**
3
- * WAL entry operation types
4
- */
5
- export type TWalOperation = 'insert' | 'update' | 'delete' | 'checkpoint' | 'begin' | 'commit' | 'abort';
6
- /**
7
- * WAL entry structure
8
- */
9
- export interface IWalEntry {
10
- /** Log Sequence Number - monotonically increasing */
11
- lsn: number;
12
- /** Timestamp of the operation */
13
- timestamp: number;
14
- /** Operation type */
15
- operation: TWalOperation;
16
- /** Database name */
17
- dbName: string;
18
- /** Collection name */
19
- collName: string;
20
- /** Document ID (hex string) */
21
- documentId: string;
22
- /** Document data (BSON serialized, base64 encoded) */
23
- data?: string;
24
- /** Previous document data for updates (for rollback) */
25
- previousData?: string;
26
- /** Transaction ID if part of a transaction */
27
- txnId?: string;
28
- /** CRC32 checksum of the entry (excluding this field) */
29
- checksum: number;
30
- }
31
- /**
32
- * Write-Ahead Log (WAL) for durability and crash recovery
33
- *
34
- * The WAL ensures durability by writing operations to a log file before
35
- * they are applied to the main storage. On crash recovery, uncommitted
36
- * operations can be replayed to restore the database to a consistent state.
37
- */
38
- export declare class WAL {
39
- private walPath;
40
- private currentLsn;
41
- private lastCheckpointLsn;
42
- private entries;
43
- private isInitialized;
44
- private fs;
45
- private uncommittedTxns;
46
- private checkpointInterval;
47
- constructor(walPath: string, options?: {
48
- checkpointInterval?: number;
49
- });
50
- /**
51
- * Initialize the WAL, loading existing entries and recovering if needed
52
- */
53
- initialize(): Promise<{
54
- recoveredEntries: IWalEntry[];
55
- }>;
56
- /**
57
- * Log an insert operation
58
- */
59
- logInsert(dbName: string, collName: string, doc: IStoredDocument, txnId?: string): Promise<number>;
60
- /**
61
- * Log an update operation
62
- */
63
- logUpdate(dbName: string, collName: string, oldDoc: IStoredDocument, newDoc: IStoredDocument, txnId?: string): Promise<number>;
64
- /**
65
- * Log a delete operation
66
- */
67
- logDelete(dbName: string, collName: string, doc: IStoredDocument, txnId?: string): Promise<number>;
68
- /**
69
- * Log transaction begin
70
- */
71
- logBeginTransaction(txnId: string): Promise<number>;
72
- /**
73
- * Log transaction commit
74
- */
75
- logCommitTransaction(txnId: string): Promise<number>;
76
- /**
77
- * Log transaction abort
78
- */
79
- logAbortTransaction(txnId: string): Promise<number>;
80
- /**
81
- * Get entries to roll back for an aborted transaction
82
- */
83
- getTransactionEntries(txnId: string): IWalEntry[];
84
- /**
85
- * Create a checkpoint - marks a consistent point in the log
86
- */
87
- checkpoint(): Promise<number>;
88
- /**
89
- * Truncate the WAL file, removing entries before the last checkpoint
90
- */
91
- private truncate;
92
- /**
93
- * Get current LSN
94
- */
95
- getCurrentLsn(): number;
96
- /**
97
- * Get entries after a specific LSN (for recovery)
98
- */
99
- getEntriesAfter(lsn: number): IWalEntry[];
100
- /**
101
- * Close the WAL
102
- */
103
- close(): Promise<void>;
104
- private appendEntry;
105
- private serializeDocument;
106
- private deserializeDocument;
107
- private calculateChecksum;
108
- private verifyChecksum;
109
- /**
110
- * Recover document from WAL entry
111
- */
112
- recoverDocument(entry: IWalEntry): IStoredDocument | null;
113
- /**
114
- * Recover previous document state from WAL entry (for rollback)
115
- */
116
- recoverPreviousDocument(entry: IWalEntry): IStoredDocument | null;
117
- }
@@ -1,286 +0,0 @@
1
- import * as plugins from '../plugins.js';
2
- /**
3
- * Write-Ahead Log (WAL) for durability and crash recovery
4
- *
5
- * The WAL ensures durability by writing operations to a log file before
6
- * they are applied to the main storage. On crash recovery, uncommitted
7
- * operations can be replayed to restore the database to a consistent state.
8
- */
9
- export class WAL {
10
- walPath;
11
- currentLsn = 0;
12
- lastCheckpointLsn = 0;
13
- entries = [];
14
- isInitialized = false;
15
- fs = new plugins.smartfs.SmartFs(new plugins.smartfs.SmartFsProviderNode());
16
- // In-memory uncommitted entries per transaction
17
- uncommittedTxns = new Map();
18
- // Checkpoint interval (number of entries between checkpoints)
19
- checkpointInterval = 1000;
20
- constructor(walPath, options) {
21
- this.walPath = walPath;
22
- if (options?.checkpointInterval) {
23
- this.checkpointInterval = options.checkpointInterval;
24
- }
25
- }
26
- /**
27
- * Initialize the WAL, loading existing entries and recovering if needed
28
- */
29
- async initialize() {
30
- if (this.isInitialized) {
31
- return { recoveredEntries: [] };
32
- }
33
- // Ensure WAL directory exists
34
- const walDir = this.walPath.substring(0, this.walPath.lastIndexOf('/'));
35
- if (walDir) {
36
- await this.fs.directory(walDir).recursive().create();
37
- }
38
- // Try to load existing WAL
39
- const exists = await this.fs.file(this.walPath).exists();
40
- if (exists) {
41
- const content = await this.fs.file(this.walPath).encoding('utf8').read();
42
- const lines = content.split('\n').filter(line => line.trim());
43
- for (const line of lines) {
44
- try {
45
- const entry = JSON.parse(line);
46
- // Verify checksum
47
- if (this.verifyChecksum(entry)) {
48
- this.entries.push(entry);
49
- if (entry.lsn > this.currentLsn) {
50
- this.currentLsn = entry.lsn;
51
- }
52
- if (entry.operation === 'checkpoint') {
53
- this.lastCheckpointLsn = entry.lsn;
54
- }
55
- }
56
- }
57
- catch {
58
- // Skip corrupted entries
59
- console.warn('Skipping corrupted WAL entry');
60
- }
61
- }
62
- }
63
- this.isInitialized = true;
64
- // Return entries after last checkpoint that need recovery
65
- const recoveredEntries = this.entries.filter(e => e.lsn > this.lastCheckpointLsn &&
66
- (e.operation === 'insert' || e.operation === 'update' || e.operation === 'delete'));
67
- return { recoveredEntries };
68
- }
69
- /**
70
- * Log an insert operation
71
- */
72
- async logInsert(dbName, collName, doc, txnId) {
73
- return this.appendEntry({
74
- operation: 'insert',
75
- dbName,
76
- collName,
77
- documentId: doc._id.toHexString(),
78
- data: this.serializeDocument(doc),
79
- txnId,
80
- });
81
- }
82
- /**
83
- * Log an update operation
84
- */
85
- async logUpdate(dbName, collName, oldDoc, newDoc, txnId) {
86
- return this.appendEntry({
87
- operation: 'update',
88
- dbName,
89
- collName,
90
- documentId: oldDoc._id.toHexString(),
91
- data: this.serializeDocument(newDoc),
92
- previousData: this.serializeDocument(oldDoc),
93
- txnId,
94
- });
95
- }
96
- /**
97
- * Log a delete operation
98
- */
99
- async logDelete(dbName, collName, doc, txnId) {
100
- return this.appendEntry({
101
- operation: 'delete',
102
- dbName,
103
- collName,
104
- documentId: doc._id.toHexString(),
105
- previousData: this.serializeDocument(doc),
106
- txnId,
107
- });
108
- }
109
- /**
110
- * Log transaction begin
111
- */
112
- async logBeginTransaction(txnId) {
113
- this.uncommittedTxns.set(txnId, []);
114
- return this.appendEntry({
115
- operation: 'begin',
116
- dbName: '',
117
- collName: '',
118
- documentId: '',
119
- txnId,
120
- });
121
- }
122
- /**
123
- * Log transaction commit
124
- */
125
- async logCommitTransaction(txnId) {
126
- this.uncommittedTxns.delete(txnId);
127
- return this.appendEntry({
128
- operation: 'commit',
129
- dbName: '',
130
- collName: '',
131
- documentId: '',
132
- txnId,
133
- });
134
- }
135
- /**
136
- * Log transaction abort
137
- */
138
- async logAbortTransaction(txnId) {
139
- this.uncommittedTxns.delete(txnId);
140
- return this.appendEntry({
141
- operation: 'abort',
142
- dbName: '',
143
- collName: '',
144
- documentId: '',
145
- txnId,
146
- });
147
- }
148
- /**
149
- * Get entries to roll back for an aborted transaction
150
- */
151
- getTransactionEntries(txnId) {
152
- return this.entries.filter(e => e.txnId === txnId);
153
- }
154
- /**
155
- * Create a checkpoint - marks a consistent point in the log
156
- */
157
- async checkpoint() {
158
- const lsn = await this.appendEntry({
159
- operation: 'checkpoint',
160
- dbName: '',
161
- collName: '',
162
- documentId: '',
163
- });
164
- this.lastCheckpointLsn = lsn;
165
- // Truncate old entries (keep only entries after checkpoint)
166
- await this.truncate();
167
- return lsn;
168
- }
169
- /**
170
- * Truncate the WAL file, removing entries before the last checkpoint
171
- */
172
- async truncate() {
173
- // Keep entries after last checkpoint
174
- const newEntries = this.entries.filter(e => e.lsn >= this.lastCheckpointLsn);
175
- this.entries = newEntries;
176
- // Rewrite the WAL file
177
- const lines = this.entries.map(e => JSON.stringify(e)).join('\n');
178
- await this.fs.file(this.walPath).encoding('utf8').write(lines);
179
- }
180
- /**
181
- * Get current LSN
182
- */
183
- getCurrentLsn() {
184
- return this.currentLsn;
185
- }
186
- /**
187
- * Get entries after a specific LSN (for recovery)
188
- */
189
- getEntriesAfter(lsn) {
190
- return this.entries.filter(e => e.lsn > lsn);
191
- }
192
- /**
193
- * Close the WAL
194
- */
195
- async close() {
196
- if (this.isInitialized) {
197
- // Final checkpoint before close
198
- await this.checkpoint();
199
- }
200
- this.isInitialized = false;
201
- }
202
- // ============================================================================
203
- // Private Methods
204
- // ============================================================================
205
- async appendEntry(partial) {
206
- await this.initialize();
207
- this.currentLsn++;
208
- const entry = {
209
- ...partial,
210
- lsn: this.currentLsn,
211
- timestamp: Date.now(),
212
- checksum: 0, // Will be calculated
213
- };
214
- // Calculate checksum
215
- entry.checksum = this.calculateChecksum(entry);
216
- // Track in transaction if applicable
217
- if (partial.txnId && this.uncommittedTxns.has(partial.txnId)) {
218
- this.uncommittedTxns.get(partial.txnId).push(entry);
219
- }
220
- // Add to in-memory log
221
- this.entries.push(entry);
222
- // Append to file (append mode for durability)
223
- await this.fs.file(this.walPath).encoding('utf8').append(JSON.stringify(entry) + '\n');
224
- // Check if we need a checkpoint
225
- if (this.entries.length - this.lastCheckpointLsn >= this.checkpointInterval) {
226
- await this.checkpoint();
227
- }
228
- return entry.lsn;
229
- }
230
- serializeDocument(doc) {
231
- // Serialize document to BSON and encode as base64
232
- const bsonData = plugins.bson.serialize(doc);
233
- return Buffer.from(bsonData).toString('base64');
234
- }
235
- deserializeDocument(data) {
236
- // Decode base64 and deserialize from BSON
237
- const buffer = Buffer.from(data, 'base64');
238
- return plugins.bson.deserialize(buffer);
239
- }
240
- calculateChecksum(entry) {
241
- // Simple CRC32-like checksum
242
- const str = JSON.stringify({
243
- lsn: entry.lsn,
244
- timestamp: entry.timestamp,
245
- operation: entry.operation,
246
- dbName: entry.dbName,
247
- collName: entry.collName,
248
- documentId: entry.documentId,
249
- data: entry.data,
250
- previousData: entry.previousData,
251
- txnId: entry.txnId,
252
- });
253
- let crc = 0xFFFFFFFF;
254
- for (let i = 0; i < str.length; i++) {
255
- crc ^= str.charCodeAt(i);
256
- for (let j = 0; j < 8; j++) {
257
- crc = (crc >>> 1) ^ (crc & 1 ? 0xEDB88320 : 0);
258
- }
259
- }
260
- return (~crc) >>> 0;
261
- }
262
- verifyChecksum(entry) {
263
- const savedChecksum = entry.checksum;
264
- entry.checksum = 0;
265
- const calculatedChecksum = this.calculateChecksum(entry);
266
- entry.checksum = savedChecksum;
267
- return calculatedChecksum === savedChecksum;
268
- }
269
- /**
270
- * Recover document from WAL entry
271
- */
272
- recoverDocument(entry) {
273
- if (!entry.data)
274
- return null;
275
- return this.deserializeDocument(entry.data);
276
- }
277
- /**
278
- * Recover previous document state from WAL entry (for rollback)
279
- */
280
- recoverPreviousDocument(entry) {
281
- if (!entry.previousData)
282
- return null;
283
- return this.deserializeDocument(entry.previousData);
284
- }
285
- }
286
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV0FMLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvdHNfc21hcnRkYi9zdG9yYWdlL1dBTC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQTJDekM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxPQUFPLEdBQUc7SUFDTixPQUFPLENBQVM7SUFDaEIsVUFBVSxHQUFXLENBQUMsQ0FBQztJQUN2QixpQkFBaUIsR0FBVyxDQUFDLENBQUM7SUFDOUIsT0FBTyxHQUFnQixFQUFFLENBQUM7SUFDMUIsYUFBYSxHQUFZLEtBQUssQ0FBQztJQUMvQixFQUFFLEdBQUcsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxDQUFDO0lBRXBGLGdEQUFnRDtJQUN4QyxlQUFlLEdBQTZCLElBQUksR0FBRyxFQUFFLENBQUM7SUFFOUQsOERBQThEO0lBQ3RELGtCQUFrQixHQUFXLElBQUksQ0FBQztJQUUxQyxZQUFZLE9BQWUsRUFBRSxPQUF5QztRQUNwRSxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUM7UUFDdkQsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxVQUFVO1FBQ2QsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDdkIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQ2xDLENBQUM7UUFFRCw4QkFBOEI7UUFDOUIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLEdB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