dataply 0.0.25-alpha.1 → 0.0.26-alpha.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/cjs/index.js +109 -16
- package/dist/types/core/DataplyAPI.d.ts +4 -1
- package/dist/types/core/Logger.d.ts +12 -0
- package/dist/types/core/PageFileSystem.d.ts +3 -1
- package/dist/types/core/RowTableEngine.d.ts +3 -1
- package/dist/types/core/WALManager.d.ts +4 -1
- package/dist/types/types/index.d.ts +29 -0
- package/package.json +4 -4
package/dist/cjs/index.js
CHANGED
|
@@ -8053,19 +8053,14 @@ var HookallSync = class _HookallSync {
|
|
|
8053
8053
|
// src/core/WALManager.ts
|
|
8054
8054
|
var import_node_fs = __toESM(require("node:fs"));
|
|
8055
8055
|
var WALManager = class {
|
|
8056
|
-
fd = null;
|
|
8057
|
-
walFilePath;
|
|
8058
|
-
pageSize;
|
|
8059
|
-
entrySize;
|
|
8060
|
-
buffer;
|
|
8061
|
-
view;
|
|
8062
|
-
totalWrittenPages = 0;
|
|
8063
8056
|
/**
|
|
8064
8057
|
* Constructor
|
|
8065
8058
|
* @param walFilePath WAL file path
|
|
8066
8059
|
* @param pageSize Page size
|
|
8060
|
+
* @param logger Logger instance
|
|
8067
8061
|
*/
|
|
8068
|
-
constructor(walFilePath, pageSize) {
|
|
8062
|
+
constructor(walFilePath, pageSize, logger) {
|
|
8063
|
+
this.logger = logger;
|
|
8069
8064
|
if ((pageSize & pageSize - 1) !== 0) {
|
|
8070
8065
|
throw new Error("Page size must be a power of 2");
|
|
8071
8066
|
}
|
|
@@ -8075,6 +8070,13 @@ var WALManager = class {
|
|
|
8075
8070
|
this.buffer = new Uint8Array(this.entrySize);
|
|
8076
8071
|
this.view = new DataView(this.buffer.buffer);
|
|
8077
8072
|
}
|
|
8073
|
+
fd = null;
|
|
8074
|
+
walFilePath;
|
|
8075
|
+
pageSize;
|
|
8076
|
+
entrySize;
|
|
8077
|
+
buffer;
|
|
8078
|
+
view;
|
|
8079
|
+
totalWrittenPages = 0;
|
|
8078
8080
|
/**
|
|
8079
8081
|
* Opens the log file.
|
|
8080
8082
|
*/
|
|
@@ -8101,11 +8103,11 @@ var WALManager = class {
|
|
|
8101
8103
|
try {
|
|
8102
8104
|
const manager = new PageManagerFactory().getManager(data);
|
|
8103
8105
|
if (!manager.verifyChecksum(data)) {
|
|
8104
|
-
|
|
8106
|
+
this.logger.warn(`Checksum verification failed for PageID ${pageId} during recovery. Ignoring changes.`);
|
|
8105
8107
|
continue;
|
|
8106
8108
|
}
|
|
8107
8109
|
} catch (e) {
|
|
8108
|
-
|
|
8110
|
+
this.logger.warn(`Failed to verify checksum for PageID ${pageId} during recovery: ${e}. Ignoring changes.`);
|
|
8109
8111
|
continue;
|
|
8110
8112
|
}
|
|
8111
8113
|
promises.push(writePage(pageId, data));
|
|
@@ -8422,13 +8424,14 @@ var PageFileSystem = class {
|
|
|
8422
8424
|
* @param pageCacheCapacity 페이지 캐시 크기
|
|
8423
8425
|
* @param options 데이터플라이 옵션
|
|
8424
8426
|
*/
|
|
8425
|
-
constructor(fileHandle, pageSize, pageCacheCapacity, options) {
|
|
8427
|
+
constructor(fileHandle, pageSize, pageCacheCapacity, options, logger) {
|
|
8426
8428
|
this.fileHandle = fileHandle;
|
|
8427
8429
|
this.pageSize = pageSize;
|
|
8428
8430
|
this.pageCacheCapacity = pageCacheCapacity;
|
|
8429
8431
|
this.options = options;
|
|
8432
|
+
this.logger = logger;
|
|
8430
8433
|
const walPath = options.wal;
|
|
8431
|
-
this.walManager = walPath ? new WALManager(walPath, pageSize) : null;
|
|
8434
|
+
this.walManager = walPath ? new WALManager(walPath, pageSize, this.logger) : null;
|
|
8432
8435
|
this.pageManagerFactory = new PageManagerFactory();
|
|
8433
8436
|
this.pageStrategy = new PageMVCCStrategy(fileHandle, pageSize, pageCacheCapacity);
|
|
8434
8437
|
}
|
|
@@ -8460,7 +8463,9 @@ var PageFileSystem = class {
|
|
|
8460
8463
|
* Performs WAL recovery if necessary.
|
|
8461
8464
|
*/
|
|
8462
8465
|
async init() {
|
|
8466
|
+
this.logger.info("Initializing");
|
|
8463
8467
|
if (this.walManager) {
|
|
8468
|
+
this.logger.debug("WALManager found, starting recovery");
|
|
8464
8469
|
await this.walManager.recover(async (pageId, data) => {
|
|
8465
8470
|
await this.pageStrategy.write(pageId, data);
|
|
8466
8471
|
});
|
|
@@ -8632,6 +8637,7 @@ var PageFileSystem = class {
|
|
|
8632
8637
|
* @returns Created or reused page ID
|
|
8633
8638
|
*/
|
|
8634
8639
|
async appendNewPage(pageType = PageManager.CONSTANT.PAGE_TYPE_EMPTY, tx) {
|
|
8640
|
+
this.logger.debug(`Appending new page of type ${pageType}`);
|
|
8635
8641
|
await tx.__acquireWriteLock(0);
|
|
8636
8642
|
const metadata = await this.getMetadata(tx);
|
|
8637
8643
|
const metadataManager = this.pageFactory.getManager(metadata);
|
|
@@ -8735,6 +8741,7 @@ var PageFileSystem = class {
|
|
|
8735
8741
|
* @param tx Transaction
|
|
8736
8742
|
*/
|
|
8737
8743
|
async freeChain(startPageId, tx) {
|
|
8744
|
+
this.logger.debug(`Freeing chain starting at page ${startPageId}`);
|
|
8738
8745
|
let currentPageId = startPageId;
|
|
8739
8746
|
const visited = /* @__PURE__ */ new Set();
|
|
8740
8747
|
while (currentPageId !== -1 && currentPageId !== 0) {
|
|
@@ -8774,6 +8781,7 @@ var PageFileSystem = class {
|
|
|
8774
8781
|
*/
|
|
8775
8782
|
async commitToWAL(dirtyPages) {
|
|
8776
8783
|
if (this.walManager) {
|
|
8784
|
+
this.logger.debug(`Committing ${dirtyPages.size} pages to WAL`);
|
|
8777
8785
|
await this.walManager.prepareCommit(dirtyPages);
|
|
8778
8786
|
await this.walManager.finalizeCommit(true);
|
|
8779
8787
|
}
|
|
@@ -8785,6 +8793,7 @@ var PageFileSystem = class {
|
|
|
8785
8793
|
* 3. WAL 로그 파일 비우기 (Clear/Truncate)
|
|
8786
8794
|
*/
|
|
8787
8795
|
async checkpoint() {
|
|
8796
|
+
this.logger.info("Starting checkpoint");
|
|
8788
8797
|
await this.runGlobalLock(async () => {
|
|
8789
8798
|
await this.pageStrategy.flush();
|
|
8790
8799
|
await this.pageStrategy.sync();
|
|
@@ -8797,6 +8806,7 @@ var PageFileSystem = class {
|
|
|
8797
8806
|
* Closes the page file system.
|
|
8798
8807
|
*/
|
|
8799
8808
|
async close() {
|
|
8809
|
+
this.logger.info("Closing");
|
|
8800
8810
|
await this.checkpoint();
|
|
8801
8811
|
if (this.walManager) {
|
|
8802
8812
|
this.walManager.close();
|
|
@@ -9038,10 +9048,11 @@ var KeyManager = class {
|
|
|
9038
9048
|
|
|
9039
9049
|
// src/core/RowTableEngine.ts
|
|
9040
9050
|
var RowTableEngine = class {
|
|
9041
|
-
constructor(pfs, txContext, options) {
|
|
9051
|
+
constructor(pfs, txContext, options, logger) {
|
|
9042
9052
|
this.pfs = pfs;
|
|
9043
9053
|
this.txContext = txContext;
|
|
9044
9054
|
this.options = options;
|
|
9055
|
+
this.logger = logger;
|
|
9045
9056
|
this.factory = new PageManagerFactory();
|
|
9046
9057
|
this.metadataPageManager = this.factory.getManagerFromType(MetadataPageManager.CONSTANT.PAGE_TYPE_METADATA);
|
|
9047
9058
|
this.dataPageManager = this.factory.getManagerFromType(DataPageManager.CONSTANT.PAGE_TYPE_DATA);
|
|
@@ -9110,6 +9121,7 @@ var RowTableEngine = class {
|
|
|
9110
9121
|
*/
|
|
9111
9122
|
async init() {
|
|
9112
9123
|
if (!this.initialized) {
|
|
9124
|
+
this.logger.info("Initializing B+ Tree");
|
|
9113
9125
|
await this.bptree.init();
|
|
9114
9126
|
this.initialized = true;
|
|
9115
9127
|
}
|
|
@@ -9157,6 +9169,7 @@ var RowTableEngine = class {
|
|
|
9157
9169
|
* @returns Metadata
|
|
9158
9170
|
*/
|
|
9159
9171
|
async getMetadata(tx) {
|
|
9172
|
+
this.logger.debug("Getting metadata");
|
|
9160
9173
|
if (!this.initialized) {
|
|
9161
9174
|
throw new Error("RowTableEngine instance is not initialized");
|
|
9162
9175
|
}
|
|
@@ -9182,6 +9195,7 @@ var RowTableEngine = class {
|
|
|
9182
9195
|
* @returns Array of PKs of the inserted data
|
|
9183
9196
|
*/
|
|
9184
9197
|
async insert(dataList, incrementRowCount, overflowForcly, tx) {
|
|
9198
|
+
this.logger.debug(`Inserting ${dataList.length} rows (overflowForcly: ${overflowForcly})`);
|
|
9185
9199
|
if (dataList.length === 0) {
|
|
9186
9200
|
return [];
|
|
9187
9201
|
}
|
|
@@ -9283,6 +9297,7 @@ var RowTableEngine = class {
|
|
|
9283
9297
|
* @param tx Transaction
|
|
9284
9298
|
*/
|
|
9285
9299
|
async update(pk, data, tx) {
|
|
9300
|
+
this.logger.debug(`Updating row with PK: ${pk}`);
|
|
9286
9301
|
await tx.__acquireWriteLock(0);
|
|
9287
9302
|
const rid = await this.getRidByPK(pk, tx);
|
|
9288
9303
|
if (rid === null) {
|
|
@@ -9368,6 +9383,7 @@ var RowTableEngine = class {
|
|
|
9368
9383
|
* @param tx Transaction
|
|
9369
9384
|
*/
|
|
9370
9385
|
async delete(pk, decrementRowCount, tx) {
|
|
9386
|
+
this.logger.debug(`Deleting row with PK: ${pk}`);
|
|
9371
9387
|
await tx.__acquireWriteLock(0);
|
|
9372
9388
|
const rid = await this.getRidByPK(pk, tx);
|
|
9373
9389
|
if (rid === null) {
|
|
@@ -9427,6 +9443,7 @@ var RowTableEngine = class {
|
|
|
9427
9443
|
* @returns Raw data of the row
|
|
9428
9444
|
*/
|
|
9429
9445
|
async selectByPK(pk, tx) {
|
|
9446
|
+
this.logger.debug(`Selecting row by PK: ${pk}`);
|
|
9430
9447
|
const rid = await this.getRidByPK(pk, tx);
|
|
9431
9448
|
if (rid === null) {
|
|
9432
9449
|
return null;
|
|
@@ -9441,6 +9458,7 @@ var RowTableEngine = class {
|
|
|
9441
9458
|
* @returns Array of raw data of the rows in the same order as input PKs
|
|
9442
9459
|
*/
|
|
9443
9460
|
async selectMany(pks, tx) {
|
|
9461
|
+
this.logger.debug(`Selecting many rows (${pks.length} PKs)`);
|
|
9444
9462
|
const collections = await this.collectItemsByPage(pks, tx);
|
|
9445
9463
|
return this.fetchRowsByRids(collections, pks.length, tx);
|
|
9446
9464
|
}
|
|
@@ -9828,26 +9846,80 @@ var TransactionContext = class {
|
|
|
9828
9846
|
}
|
|
9829
9847
|
};
|
|
9830
9848
|
|
|
9849
|
+
// src/core/Logger.ts
|
|
9850
|
+
var Colors = {
|
|
9851
|
+
reset: "\x1B[0m",
|
|
9852
|
+
debug: "\x1B[36m",
|
|
9853
|
+
// Cyan
|
|
9854
|
+
info: "\x1B[32m",
|
|
9855
|
+
// Green
|
|
9856
|
+
warn: "\x1B[33m",
|
|
9857
|
+
// Yellow
|
|
9858
|
+
error: "\x1B[31m",
|
|
9859
|
+
// Red
|
|
9860
|
+
white: "\x1B[37m",
|
|
9861
|
+
// White
|
|
9862
|
+
grey: "\x1B[90m"
|
|
9863
|
+
};
|
|
9864
|
+
var Logger = class {
|
|
9865
|
+
level;
|
|
9866
|
+
moduleName;
|
|
9867
|
+
constructor(moduleName, level = 2 /* Info */) {
|
|
9868
|
+
this.moduleName = moduleName;
|
|
9869
|
+
this.level = level;
|
|
9870
|
+
}
|
|
9871
|
+
setLevel(level) {
|
|
9872
|
+
this.level = level;
|
|
9873
|
+
}
|
|
9874
|
+
shouldLog(level) {
|
|
9875
|
+
if (this.level === 0 /* None */) return false;
|
|
9876
|
+
return level >= this.level;
|
|
9877
|
+
}
|
|
9878
|
+
debug(message, ...args) {
|
|
9879
|
+
if (this.shouldLog(1 /* Debug */)) {
|
|
9880
|
+
console.debug(`${Colors.debug}[DEBUG] [${this.moduleName}]${Colors.reset} ${Colors.white}${message}${Colors.reset}`, ...args);
|
|
9881
|
+
}
|
|
9882
|
+
}
|
|
9883
|
+
info(message, ...args) {
|
|
9884
|
+
if (this.shouldLog(2 /* Info */)) {
|
|
9885
|
+
console.info(`${Colors.info}[INFO] [${this.moduleName}]${Colors.reset} ${Colors.white}${message}${Colors.reset}`, ...args);
|
|
9886
|
+
}
|
|
9887
|
+
}
|
|
9888
|
+
warn(message, ...args) {
|
|
9889
|
+
if (this.shouldLog(3 /* Warning */)) {
|
|
9890
|
+
console.warn(`${Colors.warn}[WARN] [${this.moduleName}]${Colors.reset} ${Colors.white}${message}${Colors.reset}`, ...args);
|
|
9891
|
+
}
|
|
9892
|
+
}
|
|
9893
|
+
error(message, ...args) {
|
|
9894
|
+
if (this.shouldLog(4 /* Error */)) {
|
|
9895
|
+
console.error(`${Colors.error}[ERROR] [${this.moduleName}]${Colors.reset} ${Colors.white}${message}${Colors.reset}`, ...args);
|
|
9896
|
+
}
|
|
9897
|
+
}
|
|
9898
|
+
};
|
|
9899
|
+
|
|
9831
9900
|
// src/core/DataplyAPI.ts
|
|
9832
9901
|
var DataplyAPI = class {
|
|
9833
9902
|
constructor(file, options) {
|
|
9834
9903
|
this.file = file;
|
|
9835
9904
|
this.hook = useHookall(this);
|
|
9836
9905
|
this.options = this.verboseOptions(options);
|
|
9906
|
+
this.logger = new Logger("DataplyAPI", this.options.logLevel);
|
|
9837
9907
|
this.isNewlyCreated = !import_node_fs3.default.existsSync(file);
|
|
9838
9908
|
this.fileHandle = this.createOrOpen(file, this.options);
|
|
9839
9909
|
this.pfs = new PageFileSystem(
|
|
9840
9910
|
this.fileHandle,
|
|
9841
9911
|
this.options.pageSize,
|
|
9842
9912
|
this.options.pageCacheCapacity,
|
|
9843
|
-
this.options
|
|
9913
|
+
this.options,
|
|
9914
|
+
this.logger
|
|
9844
9915
|
);
|
|
9845
9916
|
this.textCodec = new TextCodec();
|
|
9846
9917
|
this.txContext = new TransactionContext();
|
|
9847
9918
|
this.lockManager = new LockManager();
|
|
9848
|
-
this.rowTableEngine = new RowTableEngine(this.pfs, this.txContext, this.options);
|
|
9919
|
+
this.rowTableEngine = new RowTableEngine(this.pfs, this.txContext, this.options, this.logger);
|
|
9849
9920
|
this.initialized = false;
|
|
9850
9921
|
this.txIdCounter = 0;
|
|
9922
|
+
this.logger.debug(`DataplyAPI instance created with file: ${file}`);
|
|
9851
9923
|
}
|
|
9852
9924
|
/**
|
|
9853
9925
|
* These are not the same options that were used when the database was created.
|
|
@@ -9869,6 +9941,8 @@ var DataplyAPI = class {
|
|
|
9869
9941
|
txContext;
|
|
9870
9942
|
/** Hook */
|
|
9871
9943
|
hook;
|
|
9944
|
+
/** Logger */
|
|
9945
|
+
logger;
|
|
9872
9946
|
/** Whether the database was initialized via `init()` */
|
|
9873
9947
|
initialized;
|
|
9874
9948
|
/** Whether the database was created this time. */
|
|
@@ -9883,6 +9957,7 @@ var DataplyAPI = class {
|
|
|
9883
9957
|
* @returns Whether the page file is a valid Dataply file
|
|
9884
9958
|
*/
|
|
9885
9959
|
verifyFormat(fileHandle) {
|
|
9960
|
+
this.logger.debug(`Verifying format for file handle: ${fileHandle}`);
|
|
9886
9961
|
const size = MetadataPageManager.CONSTANT.OFFSET_MAGIC_STRING + MetadataPageManager.CONSTANT.MAGIC_STRING.length;
|
|
9887
9962
|
const metadataPage = new Uint8Array(size);
|
|
9888
9963
|
import_node_fs3.default.readSync(fileHandle, metadataPage, 0, size, 0);
|
|
@@ -9902,7 +9977,8 @@ var DataplyAPI = class {
|
|
|
9902
9977
|
pageCacheCapacity: 1e4,
|
|
9903
9978
|
pagePreallocationCount: 1e3,
|
|
9904
9979
|
wal: null,
|
|
9905
|
-
walCheckpointThreshold: 1e3
|
|
9980
|
+
walCheckpointThreshold: 1e3,
|
|
9981
|
+
logLevel: 2 /* Info */
|
|
9906
9982
|
}, options);
|
|
9907
9983
|
}
|
|
9908
9984
|
/**
|
|
@@ -9913,6 +9989,7 @@ var DataplyAPI = class {
|
|
|
9913
9989
|
* @param fileHandle File handle
|
|
9914
9990
|
*/
|
|
9915
9991
|
initializeFile(file, fileHandle, options) {
|
|
9992
|
+
this.logger.info(`Initializing new dataply file: ${file}`);
|
|
9916
9993
|
const metadataPageManager = new MetadataPageManager();
|
|
9917
9994
|
const bitmapPageManager = new BitmapPageManager();
|
|
9918
9995
|
const dataPageManager = new DataPageManager();
|
|
@@ -9962,6 +10039,7 @@ var DataplyAPI = class {
|
|
|
9962
10039
|
* @returns File handle
|
|
9963
10040
|
*/
|
|
9964
10041
|
createOrOpen(file, options) {
|
|
10042
|
+
this.logger.info(`Opening dataply file: ${file}`);
|
|
9965
10043
|
let fileHandle;
|
|
9966
10044
|
if (options.pageCacheCapacity < 100) {
|
|
9967
10045
|
throw new Error("Page cache capacity must be at least 100");
|
|
@@ -9997,6 +10075,7 @@ var DataplyAPI = class {
|
|
|
9997
10075
|
* If not called, the dataply instance cannot be used.
|
|
9998
10076
|
*/
|
|
9999
10077
|
async init() {
|
|
10078
|
+
this.logger.info("Initializing DataplyAPI");
|
|
10000
10079
|
if (this.initialized) {
|
|
10001
10080
|
return;
|
|
10002
10081
|
}
|
|
@@ -10016,6 +10095,7 @@ var DataplyAPI = class {
|
|
|
10016
10095
|
* @returns Transaction object
|
|
10017
10096
|
*/
|
|
10018
10097
|
createTransaction() {
|
|
10098
|
+
this.logger.debug(`Creating transaction: ${this.txIdCounter + 1}`);
|
|
10019
10099
|
return new Transaction(
|
|
10020
10100
|
++this.txIdCounter,
|
|
10021
10101
|
this.txContext,
|
|
@@ -10040,6 +10120,7 @@ var DataplyAPI = class {
|
|
|
10040
10120
|
* @returns A release function
|
|
10041
10121
|
*/
|
|
10042
10122
|
acquireWriteLock() {
|
|
10123
|
+
this.logger.debug("Acquiring write lock");
|
|
10043
10124
|
const previous = this.writeQueue;
|
|
10044
10125
|
let release;
|
|
10045
10126
|
this.writeQueue = new Promise((resolve) => {
|
|
@@ -10057,6 +10138,7 @@ var DataplyAPI = class {
|
|
|
10057
10138
|
* @returns The result of the callback.
|
|
10058
10139
|
*/
|
|
10059
10140
|
async runWithDefaultWrite(callback, tx) {
|
|
10141
|
+
this.logger.debug("Running with default write transaction");
|
|
10060
10142
|
if (!tx) {
|
|
10061
10143
|
const release = await this.acquireWriteLock();
|
|
10062
10144
|
const internalTx = this.createTransaction();
|
|
@@ -10080,6 +10162,7 @@ var DataplyAPI = class {
|
|
|
10080
10162
|
return result;
|
|
10081
10163
|
}
|
|
10082
10164
|
async runWithDefault(callback, tx) {
|
|
10165
|
+
this.logger.debug("Running with default transaction");
|
|
10083
10166
|
const isInternalTx = !tx;
|
|
10084
10167
|
if (!tx) {
|
|
10085
10168
|
tx = this.createTransaction();
|
|
@@ -10107,6 +10190,7 @@ var DataplyAPI = class {
|
|
|
10107
10190
|
* @returns An AsyncGenerator that yields values from the callback.
|
|
10108
10191
|
*/
|
|
10109
10192
|
async *streamWithDefault(callback, tx) {
|
|
10193
|
+
this.logger.debug("Streaming with default transaction");
|
|
10110
10194
|
const isInternalTx = !tx;
|
|
10111
10195
|
if (!tx) {
|
|
10112
10196
|
tx = this.createTransaction();
|
|
@@ -10134,6 +10218,7 @@ var DataplyAPI = class {
|
|
|
10134
10218
|
* @returns Metadata of the dataply.
|
|
10135
10219
|
*/
|
|
10136
10220
|
async getMetadata(tx) {
|
|
10221
|
+
this.logger.debug("Getting metadata");
|
|
10137
10222
|
if (!this.initialized) {
|
|
10138
10223
|
throw new Error("Dataply instance is not initialized");
|
|
10139
10224
|
}
|
|
@@ -10147,6 +10232,7 @@ var DataplyAPI = class {
|
|
|
10147
10232
|
* @returns PK of the added data
|
|
10148
10233
|
*/
|
|
10149
10234
|
async insert(data, incrementRowCount, tx) {
|
|
10235
|
+
this.logger.debug("Inserting data");
|
|
10150
10236
|
if (!this.initialized) {
|
|
10151
10237
|
throw new Error("Dataply instance is not initialized");
|
|
10152
10238
|
}
|
|
@@ -10167,6 +10253,7 @@ var DataplyAPI = class {
|
|
|
10167
10253
|
* @returns PK of the added data
|
|
10168
10254
|
*/
|
|
10169
10255
|
async insertAsOverflow(data, incrementRowCount, tx) {
|
|
10256
|
+
this.logger.debug("Inserting data as overflow");
|
|
10170
10257
|
if (!this.initialized) {
|
|
10171
10258
|
throw new Error("Dataply instance is not initialized");
|
|
10172
10259
|
}
|
|
@@ -10188,6 +10275,7 @@ var DataplyAPI = class {
|
|
|
10188
10275
|
* @returns Array of PKs of the added data
|
|
10189
10276
|
*/
|
|
10190
10277
|
async insertBatch(dataList, incrementRowCount, tx) {
|
|
10278
|
+
this.logger.debug(`Inserting batch data: ${dataList.length} items`);
|
|
10191
10279
|
if (!this.initialized) {
|
|
10192
10280
|
throw new Error("Dataply instance is not initialized");
|
|
10193
10281
|
}
|
|
@@ -10206,6 +10294,7 @@ var DataplyAPI = class {
|
|
|
10206
10294
|
* @param tx Transaction
|
|
10207
10295
|
*/
|
|
10208
10296
|
async update(pk, data, tx) {
|
|
10297
|
+
this.logger.debug(`Updating data for PK: ${pk}`);
|
|
10209
10298
|
if (!this.initialized) {
|
|
10210
10299
|
throw new Error("Dataply instance is not initialized");
|
|
10211
10300
|
}
|
|
@@ -10223,6 +10312,7 @@ var DataplyAPI = class {
|
|
|
10223
10312
|
* @param tx Transaction
|
|
10224
10313
|
*/
|
|
10225
10314
|
async delete(pk, decrementRowCount, tx) {
|
|
10315
|
+
this.logger.debug(`Deleting data for PK: ${pk}`);
|
|
10226
10316
|
if (!this.initialized) {
|
|
10227
10317
|
throw new Error("Dataply instance is not initialized");
|
|
10228
10318
|
}
|
|
@@ -10232,6 +10322,7 @@ var DataplyAPI = class {
|
|
|
10232
10322
|
}, tx);
|
|
10233
10323
|
}
|
|
10234
10324
|
async select(pk, asRaw = false, tx) {
|
|
10325
|
+
this.logger.debug(`Selecting data for PK: ${pk}`);
|
|
10235
10326
|
if (!this.initialized) {
|
|
10236
10327
|
throw new Error("Dataply instance is not initialized");
|
|
10237
10328
|
}
|
|
@@ -10243,6 +10334,7 @@ var DataplyAPI = class {
|
|
|
10243
10334
|
}, tx);
|
|
10244
10335
|
}
|
|
10245
10336
|
async selectMany(pks, asRaw = false, tx) {
|
|
10337
|
+
this.logger.debug(`Selecting many data: ${pks.length} keys`);
|
|
10246
10338
|
if (!this.initialized) {
|
|
10247
10339
|
throw new Error("Dataply instance is not initialized");
|
|
10248
10340
|
}
|
|
@@ -10259,6 +10351,7 @@ var DataplyAPI = class {
|
|
|
10259
10351
|
* Closes the dataply file.
|
|
10260
10352
|
*/
|
|
10261
10353
|
async close() {
|
|
10354
|
+
this.logger.info("Closing DataplyAPI");
|
|
10262
10355
|
if (!this.initialized) {
|
|
10263
10356
|
throw new Error("Dataply instance is not initialized");
|
|
10264
10357
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type DataplyOptions, type DataplyMetadata } from '../types';
|
|
2
2
|
import { type IHookall } from 'hookall';
|
|
3
3
|
import { PageFileSystem } from './PageFileSystem';
|
|
4
4
|
import { RowTableEngine } from './RowTableEngine';
|
|
@@ -6,6 +6,7 @@ import { TextCodec } from '../utils/TextCodec';
|
|
|
6
6
|
import { LockManager } from './transaction/LockManager';
|
|
7
7
|
import { Transaction } from './transaction/Transaction';
|
|
8
8
|
import { TransactionContext } from './transaction/TxContext';
|
|
9
|
+
import { Logger } from './Logger';
|
|
9
10
|
interface DataplyAPIAsyncHook {
|
|
10
11
|
init: (tx: Transaction, isNewlyCreated: boolean) => Promise<Transaction>;
|
|
11
12
|
close: () => Promise<void>;
|
|
@@ -35,6 +36,8 @@ export declare class DataplyAPI {
|
|
|
35
36
|
protected readonly txContext: TransactionContext;
|
|
36
37
|
/** Hook */
|
|
37
38
|
protected readonly hook: IHookall<DataplyAPIAsyncHook>;
|
|
39
|
+
/** Logger */
|
|
40
|
+
protected readonly logger: Logger;
|
|
38
41
|
/** Whether the database was initialized via `init()` */
|
|
39
42
|
protected initialized: boolean;
|
|
40
43
|
/** Whether the database was created this time. */
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LogLevel } from '../types';
|
|
2
|
+
export declare class Logger {
|
|
3
|
+
private level;
|
|
4
|
+
private moduleName;
|
|
5
|
+
constructor(moduleName: string, level?: LogLevel);
|
|
6
|
+
setLevel(level: LogLevel): void;
|
|
7
|
+
private shouldLog;
|
|
8
|
+
debug(message: string, ...args: any[]): void;
|
|
9
|
+
info(message: string, ...args: any[]): void;
|
|
10
|
+
warn(message: string, ...args: any[]): void;
|
|
11
|
+
error(message: string, ...args: any[]): void;
|
|
12
|
+
}
|
|
@@ -3,6 +3,7 @@ import type { Transaction } from './transaction/Transaction';
|
|
|
3
3
|
import { PageManagerFactory } from './Page';
|
|
4
4
|
import { WALManager } from './WALManager';
|
|
5
5
|
import { PageMVCCStrategy } from './PageMVCCStrategy';
|
|
6
|
+
import { Logger } from './Logger';
|
|
6
7
|
/**
|
|
7
8
|
* Page File System class.
|
|
8
9
|
* mvcc-api 기반으로 페이지 관리를 수행합니다.
|
|
@@ -12,6 +13,7 @@ export declare class PageFileSystem {
|
|
|
12
13
|
readonly pageSize: number;
|
|
13
14
|
readonly pageCacheCapacity: number;
|
|
14
15
|
readonly options: Required<DataplyOptions>;
|
|
16
|
+
protected readonly logger: Logger;
|
|
15
17
|
protected readonly pageFactory: PageManagerFactory;
|
|
16
18
|
protected readonly walManager: WALManager | null;
|
|
17
19
|
protected readonly pageManagerFactory: PageManagerFactory;
|
|
@@ -22,7 +24,7 @@ export declare class PageFileSystem {
|
|
|
22
24
|
* @param pageCacheCapacity 페이지 캐시 크기
|
|
23
25
|
* @param options 데이터플라이 옵션
|
|
24
26
|
*/
|
|
25
|
-
constructor(fileHandle: number, pageSize: number, pageCacheCapacity: number, options: Required<DataplyOptions
|
|
27
|
+
constructor(fileHandle: number, pageSize: number, pageCacheCapacity: number, options: Required<DataplyOptions>, logger: Logger);
|
|
26
28
|
/**
|
|
27
29
|
* 글로벌 동기화 범위 내에서 작업을 실행합니다.
|
|
28
30
|
* @param task 수행할 비동기 작업
|
|
@@ -7,10 +7,12 @@ import { KeyManager } from './KeyManager';
|
|
|
7
7
|
import { PageManagerFactory } from './Page';
|
|
8
8
|
import { Transaction } from './transaction/Transaction';
|
|
9
9
|
import { TransactionContext } from './transaction/TxContext';
|
|
10
|
+
import { Logger } from './Logger';
|
|
10
11
|
export declare class RowTableEngine {
|
|
11
12
|
protected readonly pfs: PageFileSystem;
|
|
12
13
|
protected readonly txContext: TransactionContext;
|
|
13
14
|
protected readonly options: Required<DataplyOptions>;
|
|
15
|
+
protected readonly logger: Logger;
|
|
14
16
|
protected readonly bptree: BPTreeAsync<number, number>;
|
|
15
17
|
protected readonly strategy: RowIdentifierStrategy;
|
|
16
18
|
protected readonly order: number;
|
|
@@ -24,7 +26,7 @@ export declare class RowTableEngine {
|
|
|
24
26
|
private readonly ridBuffer;
|
|
25
27
|
private readonly pageIdBuffer;
|
|
26
28
|
private initialized;
|
|
27
|
-
constructor(pfs: PageFileSystem, txContext: TransactionContext, options: Required<DataplyOptions
|
|
29
|
+
constructor(pfs: PageFileSystem, txContext: TransactionContext, options: Required<DataplyOptions>, logger: Logger);
|
|
28
30
|
/**
|
|
29
31
|
* Retrieves the BPTree transaction associated with the given transaction.
|
|
30
32
|
* If it doesn't exist, it creates a new one and registers commit/rollback hooks.
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { Logger } from './Logger';
|
|
1
2
|
/**
|
|
2
3
|
* WAL (Write-Ahead Logging) Manager class.
|
|
3
4
|
* Records changes to a log file and manages them to ensure atomicity of the database.
|
|
4
5
|
* Handles commit phases and crash recovery.
|
|
5
6
|
*/
|
|
6
7
|
export declare class WALManager {
|
|
8
|
+
private readonly logger;
|
|
7
9
|
private fd;
|
|
8
10
|
private readonly walFilePath;
|
|
9
11
|
private readonly pageSize;
|
|
@@ -15,8 +17,9 @@ export declare class WALManager {
|
|
|
15
17
|
* Constructor
|
|
16
18
|
* @param walFilePath WAL file path
|
|
17
19
|
* @param pageSize Page size
|
|
20
|
+
* @param logger Logger instance
|
|
18
21
|
*/
|
|
19
|
-
constructor(walFilePath: string, pageSize: number);
|
|
22
|
+
constructor(walFilePath: string, pageSize: number, logger: Logger);
|
|
20
23
|
/**
|
|
21
24
|
* Opens the log file.
|
|
22
25
|
*/
|
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
export declare enum LogLevel {
|
|
2
|
+
/**
|
|
3
|
+
* No logging.
|
|
4
|
+
*/
|
|
5
|
+
None = 0,
|
|
6
|
+
/**
|
|
7
|
+
* Debug logging.
|
|
8
|
+
*/
|
|
9
|
+
Debug = 1,
|
|
10
|
+
/**
|
|
11
|
+
* Info logging.
|
|
12
|
+
*/
|
|
13
|
+
Info = 2,
|
|
14
|
+
/**
|
|
15
|
+
* Warning logging.
|
|
16
|
+
*/
|
|
17
|
+
Warning = 3,
|
|
18
|
+
/**
|
|
19
|
+
* Error logging.
|
|
20
|
+
*/
|
|
21
|
+
Error = 4
|
|
22
|
+
}
|
|
1
23
|
export interface DataplyOptions {
|
|
2
24
|
/**
|
|
3
25
|
* The size of a page in bytes.
|
|
@@ -10,6 +32,8 @@ export interface DataplyOptions {
|
|
|
10
32
|
wal?: string | undefined | null;
|
|
11
33
|
/**
|
|
12
34
|
* The maximum number of pages to cache in memory.
|
|
35
|
+
* This value **DOES NOT** guarantee that the application's memory usage will be exactly `pageSize * pageCacheCapacity`.
|
|
36
|
+
* This value is only a recommendation for optimizing memory usage.
|
|
13
37
|
* Default is 10000.
|
|
14
38
|
*/
|
|
15
39
|
pageCacheCapacity?: number;
|
|
@@ -23,6 +47,11 @@ export interface DataplyOptions {
|
|
|
23
47
|
* Default is 1000.
|
|
24
48
|
*/
|
|
25
49
|
walCheckpointThreshold?: number;
|
|
50
|
+
/**
|
|
51
|
+
* The log level.
|
|
52
|
+
* Default is `LogLevel.Info`.
|
|
53
|
+
*/
|
|
54
|
+
logLevel?: LogLevel;
|
|
26
55
|
}
|
|
27
56
|
export interface DataplyMetadata {
|
|
28
57
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dataply",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.26-alpha.0",
|
|
4
4
|
"description": "A lightweight storage engine for Node.js with support for MVCC, WAL.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "izure <admin@izure.org>",
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/jest": "^30.0.0",
|
|
41
|
-
"@types/node": "^25.0
|
|
42
|
-
"esbuild": "^0.27.
|
|
43
|
-
"jest": "^30.
|
|
41
|
+
"@types/node": "^25.4.0",
|
|
42
|
+
"esbuild": "^0.27.3",
|
|
43
|
+
"jest": "^30.3.0",
|
|
44
44
|
"ts-jest": "^29.4.6",
|
|
45
45
|
"typescript": "^5.9.3"
|
|
46
46
|
},
|