@push.rocks/smartdb 1.0.1 → 2.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.
Files changed (110) hide show
  1. package/.smartconfig.json +7 -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/ts_local/classes.localsmartdb.d.ts +5 -5
  6. package/dist_ts/ts_local/classes.localsmartdb.js +5 -6
  7. package/dist_ts/ts_local/plugins.d.ts +1 -2
  8. package/dist_ts/ts_local/plugins.js +3 -3
  9. package/dist_ts/ts_smartdb/index.d.ts +1 -24
  10. package/dist_ts/ts_smartdb/index.js +4 -29
  11. package/dist_ts/ts_smartdb/plugins.d.ts +2 -10
  12. package/dist_ts/ts_smartdb/plugins.js +3 -13
  13. package/dist_ts/ts_smartdb/rust-db-bridge.d.ts +43 -0
  14. package/dist_ts/ts_smartdb/rust-db-bridge.js +98 -0
  15. package/dist_ts/ts_smartdb/server/SmartdbServer.d.ts +8 -37
  16. package/dist_ts/ts_smartdb/server/SmartdbServer.js +49 -204
  17. package/dist_ts/ts_smartdb/server/index.d.ts +0 -4
  18. package/dist_ts/ts_smartdb/server/index.js +1 -5
  19. package/license +3 -1
  20. package/package.json +9 -12
  21. package/readme.md +84 -171
  22. package/ts/00_commitinfo_data.ts +2 -2
  23. package/ts/ts_local/classes.localsmartdb.ts +5 -6
  24. package/ts/ts_local/plugins.ts +1 -3
  25. package/ts/ts_smartdb/index.ts +3 -41
  26. package/ts/ts_smartdb/plugins.ts +2 -15
  27. package/ts/ts_smartdb/rust-db-bridge.ts +138 -0
  28. package/ts/ts_smartdb/server/SmartdbServer.ts +53 -248
  29. package/ts/ts_smartdb/server/index.ts +0 -7
  30. package/dist_ts/ts_smartdb/engine/AggregationEngine.d.ts +0 -66
  31. package/dist_ts/ts_smartdb/engine/AggregationEngine.js +0 -189
  32. package/dist_ts/ts_smartdb/engine/IndexEngine.d.ts +0 -97
  33. package/dist_ts/ts_smartdb/engine/IndexEngine.js +0 -678
  34. package/dist_ts/ts_smartdb/engine/QueryEngine.d.ts +0 -54
  35. package/dist_ts/ts_smartdb/engine/QueryEngine.js +0 -271
  36. package/dist_ts/ts_smartdb/engine/QueryPlanner.d.ts +0 -64
  37. package/dist_ts/ts_smartdb/engine/QueryPlanner.js +0 -308
  38. package/dist_ts/ts_smartdb/engine/SessionEngine.d.ts +0 -117
  39. package/dist_ts/ts_smartdb/engine/SessionEngine.js +0 -232
  40. package/dist_ts/ts_smartdb/engine/TransactionEngine.d.ts +0 -85
  41. package/dist_ts/ts_smartdb/engine/TransactionEngine.js +0 -287
  42. package/dist_ts/ts_smartdb/engine/UpdateEngine.d.ts +0 -47
  43. package/dist_ts/ts_smartdb/engine/UpdateEngine.js +0 -461
  44. package/dist_ts/ts_smartdb/errors/SmartdbErrors.d.ts +0 -100
  45. package/dist_ts/ts_smartdb/errors/SmartdbErrors.js +0 -155
  46. package/dist_ts/ts_smartdb/server/CommandRouter.d.ts +0 -87
  47. package/dist_ts/ts_smartdb/server/CommandRouter.js +0 -222
  48. package/dist_ts/ts_smartdb/server/WireProtocol.d.ts +0 -117
  49. package/dist_ts/ts_smartdb/server/WireProtocol.js +0 -298
  50. package/dist_ts/ts_smartdb/server/handlers/AdminHandler.d.ts +0 -100
  51. package/dist_ts/ts_smartdb/server/handlers/AdminHandler.js +0 -668
  52. package/dist_ts/ts_smartdb/server/handlers/AggregateHandler.d.ts +0 -31
  53. package/dist_ts/ts_smartdb/server/handlers/AggregateHandler.js +0 -277
  54. package/dist_ts/ts_smartdb/server/handlers/DeleteHandler.d.ts +0 -8
  55. package/dist_ts/ts_smartdb/server/handlers/DeleteHandler.js +0 -95
  56. package/dist_ts/ts_smartdb/server/handlers/FindHandler.d.ts +0 -31
  57. package/dist_ts/ts_smartdb/server/handlers/FindHandler.js +0 -291
  58. package/dist_ts/ts_smartdb/server/handlers/HelloHandler.d.ts +0 -11
  59. package/dist_ts/ts_smartdb/server/handlers/HelloHandler.js +0 -62
  60. package/dist_ts/ts_smartdb/server/handlers/IndexHandler.d.ts +0 -20
  61. package/dist_ts/ts_smartdb/server/handlers/IndexHandler.js +0 -183
  62. package/dist_ts/ts_smartdb/server/handlers/InsertHandler.d.ts +0 -8
  63. package/dist_ts/ts_smartdb/server/handlers/InsertHandler.js +0 -79
  64. package/dist_ts/ts_smartdb/server/handlers/UpdateHandler.d.ts +0 -24
  65. package/dist_ts/ts_smartdb/server/handlers/UpdateHandler.js +0 -296
  66. package/dist_ts/ts_smartdb/server/handlers/index.d.ts +0 -8
  67. package/dist_ts/ts_smartdb/server/handlers/index.js +0 -10
  68. package/dist_ts/ts_smartdb/storage/FileStorageAdapter.d.ts +0 -85
  69. package/dist_ts/ts_smartdb/storage/FileStorageAdapter.js +0 -465
  70. package/dist_ts/ts_smartdb/storage/IStorageAdapter.d.ts +0 -145
  71. package/dist_ts/ts_smartdb/storage/IStorageAdapter.js +0 -2
  72. package/dist_ts/ts_smartdb/storage/MemoryStorageAdapter.d.ts +0 -67
  73. package/dist_ts/ts_smartdb/storage/MemoryStorageAdapter.js +0 -378
  74. package/dist_ts/ts_smartdb/storage/OpLog.d.ts +0 -93
  75. package/dist_ts/ts_smartdb/storage/OpLog.js +0 -221
  76. package/dist_ts/ts_smartdb/storage/WAL.d.ts +0 -117
  77. package/dist_ts/ts_smartdb/storage/WAL.js +0 -286
  78. package/dist_ts/ts_smartdb/types/interfaces.d.ts +0 -363
  79. package/dist_ts/ts_smartdb/types/interfaces.js +0 -2
  80. package/dist_ts/ts_smartdb/utils/checksum.d.ts +0 -30
  81. package/dist_ts/ts_smartdb/utils/checksum.js +0 -77
  82. package/dist_ts/ts_smartdb/utils/index.d.ts +0 -1
  83. package/dist_ts/ts_smartdb/utils/index.js +0 -2
  84. package/ts/ts_smartdb/engine/AggregationEngine.ts +0 -283
  85. package/ts/ts_smartdb/engine/IndexEngine.ts +0 -798
  86. package/ts/ts_smartdb/engine/QueryEngine.ts +0 -301
  87. package/ts/ts_smartdb/engine/QueryPlanner.ts +0 -393
  88. package/ts/ts_smartdb/engine/SessionEngine.ts +0 -292
  89. package/ts/ts_smartdb/engine/TransactionEngine.ts +0 -351
  90. package/ts/ts_smartdb/engine/UpdateEngine.ts +0 -506
  91. package/ts/ts_smartdb/errors/SmartdbErrors.ts +0 -181
  92. package/ts/ts_smartdb/server/CommandRouter.ts +0 -289
  93. package/ts/ts_smartdb/server/WireProtocol.ts +0 -416
  94. package/ts/ts_smartdb/server/handlers/AdminHandler.ts +0 -719
  95. package/ts/ts_smartdb/server/handlers/AggregateHandler.ts +0 -342
  96. package/ts/ts_smartdb/server/handlers/DeleteHandler.ts +0 -115
  97. package/ts/ts_smartdb/server/handlers/FindHandler.ts +0 -330
  98. package/ts/ts_smartdb/server/handlers/HelloHandler.ts +0 -78
  99. package/ts/ts_smartdb/server/handlers/IndexHandler.ts +0 -207
  100. package/ts/ts_smartdb/server/handlers/InsertHandler.ts +0 -97
  101. package/ts/ts_smartdb/server/handlers/UpdateHandler.ts +0 -344
  102. package/ts/ts_smartdb/server/handlers/index.ts +0 -10
  103. package/ts/ts_smartdb/storage/FileStorageAdapter.ts +0 -562
  104. package/ts/ts_smartdb/storage/IStorageAdapter.ts +0 -208
  105. package/ts/ts_smartdb/storage/MemoryStorageAdapter.ts +0 -455
  106. package/ts/ts_smartdb/storage/OpLog.ts +0 -282
  107. package/ts/ts_smartdb/storage/WAL.ts +0 -375
  108. package/ts/ts_smartdb/types/interfaces.ts +0 -433
  109. package/ts/ts_smartdb/utils/checksum.ts +0 -88
  110. 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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