dataply 0.0.25 → 0.0.26-alpha.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.
- package/dist/cjs/index.js +117 -9
- package/dist/types/core/DataplyAPI.d.ts +6 -1
- package/dist/types/core/Logger.d.ts +17 -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 +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -8060,12 +8060,14 @@ var WALManager = class {
|
|
|
8060
8060
|
buffer;
|
|
8061
8061
|
view;
|
|
8062
8062
|
totalWrittenPages = 0;
|
|
8063
|
+
logger;
|
|
8063
8064
|
/**
|
|
8064
8065
|
* Constructor
|
|
8065
8066
|
* @param walFilePath WAL file path
|
|
8066
8067
|
* @param pageSize Page size
|
|
8068
|
+
* @param logger Logger instance
|
|
8067
8069
|
*/
|
|
8068
|
-
constructor(walFilePath, pageSize) {
|
|
8070
|
+
constructor(walFilePath, pageSize, logger) {
|
|
8069
8071
|
if ((pageSize & pageSize - 1) !== 0) {
|
|
8070
8072
|
throw new Error("Page size must be a power of 2");
|
|
8071
8073
|
}
|
|
@@ -8074,6 +8076,7 @@ var WALManager = class {
|
|
|
8074
8076
|
this.entrySize = 4 + pageSize;
|
|
8075
8077
|
this.buffer = new Uint8Array(this.entrySize);
|
|
8076
8078
|
this.view = new DataView(this.buffer.buffer);
|
|
8079
|
+
this.logger = logger;
|
|
8077
8080
|
}
|
|
8078
8081
|
/**
|
|
8079
8082
|
* Opens the log file.
|
|
@@ -8101,11 +8104,11 @@ var WALManager = class {
|
|
|
8101
8104
|
try {
|
|
8102
8105
|
const manager = new PageManagerFactory().getManager(data);
|
|
8103
8106
|
if (!manager.verifyChecksum(data)) {
|
|
8104
|
-
|
|
8107
|
+
this.logger.warn(`Checksum verification failed for PageID ${pageId} during recovery. Ignoring changes.`);
|
|
8105
8108
|
continue;
|
|
8106
8109
|
}
|
|
8107
8110
|
} catch (e) {
|
|
8108
|
-
|
|
8111
|
+
this.logger.warn(`Failed to verify checksum for PageID ${pageId} during recovery: ${e}. Ignoring changes.`);
|
|
8109
8112
|
continue;
|
|
8110
8113
|
}
|
|
8111
8114
|
promises.push(writePage(pageId, data));
|
|
@@ -8422,20 +8425,22 @@ var PageFileSystem = class {
|
|
|
8422
8425
|
* @param pageCacheCapacity 페이지 캐시 크기
|
|
8423
8426
|
* @param options 데이터플라이 옵션
|
|
8424
8427
|
*/
|
|
8425
|
-
constructor(fileHandle, pageSize, pageCacheCapacity, options) {
|
|
8428
|
+
constructor(fileHandle, pageSize, pageCacheCapacity, options, logger, walLogger) {
|
|
8426
8429
|
this.fileHandle = fileHandle;
|
|
8427
8430
|
this.pageSize = pageSize;
|
|
8428
8431
|
this.pageCacheCapacity = pageCacheCapacity;
|
|
8429
8432
|
this.options = options;
|
|
8430
8433
|
const walPath = options.wal;
|
|
8431
|
-
this.walManager = walPath ? new WALManager(walPath, pageSize) : null;
|
|
8434
|
+
this.walManager = walPath && walLogger ? new WALManager(walPath, pageSize, walLogger) : null;
|
|
8432
8435
|
this.pageManagerFactory = new PageManagerFactory();
|
|
8433
8436
|
this.pageStrategy = new PageMVCCStrategy(fileHandle, pageSize, pageCacheCapacity);
|
|
8437
|
+
this.logger = logger;
|
|
8434
8438
|
}
|
|
8435
8439
|
pageFactory = new PageManagerFactory();
|
|
8436
8440
|
walManager;
|
|
8437
8441
|
pageManagerFactory;
|
|
8438
8442
|
pageStrategy;
|
|
8443
|
+
logger;
|
|
8439
8444
|
/** 글로벌 동기화(체크포인트/커밋)를 위한 Mutex */
|
|
8440
8445
|
lockPromise = Promise.resolve();
|
|
8441
8446
|
/**
|
|
@@ -8460,7 +8465,9 @@ var PageFileSystem = class {
|
|
|
8460
8465
|
* Performs WAL recovery if necessary.
|
|
8461
8466
|
*/
|
|
8462
8467
|
async init() {
|
|
8468
|
+
this.logger.info("Initializing");
|
|
8463
8469
|
if (this.walManager) {
|
|
8470
|
+
this.logger.debug("WALManager found, starting recovery");
|
|
8464
8471
|
await this.walManager.recover(async (pageId, data) => {
|
|
8465
8472
|
await this.pageStrategy.write(pageId, data);
|
|
8466
8473
|
});
|
|
@@ -8632,6 +8639,7 @@ var PageFileSystem = class {
|
|
|
8632
8639
|
* @returns Created or reused page ID
|
|
8633
8640
|
*/
|
|
8634
8641
|
async appendNewPage(pageType = PageManager.CONSTANT.PAGE_TYPE_EMPTY, tx) {
|
|
8642
|
+
this.logger.debug(`Appending new page of type ${pageType}`);
|
|
8635
8643
|
await tx.__acquireWriteLock(0);
|
|
8636
8644
|
const metadata = await this.getMetadata(tx);
|
|
8637
8645
|
const metadataManager = this.pageFactory.getManager(metadata);
|
|
@@ -8735,6 +8743,7 @@ var PageFileSystem = class {
|
|
|
8735
8743
|
* @param tx Transaction
|
|
8736
8744
|
*/
|
|
8737
8745
|
async freeChain(startPageId, tx) {
|
|
8746
|
+
this.logger.debug(`Freeing chain starting at page ${startPageId}`);
|
|
8738
8747
|
let currentPageId = startPageId;
|
|
8739
8748
|
const visited = /* @__PURE__ */ new Set();
|
|
8740
8749
|
while (currentPageId !== -1 && currentPageId !== 0) {
|
|
@@ -8774,6 +8783,7 @@ var PageFileSystem = class {
|
|
|
8774
8783
|
*/
|
|
8775
8784
|
async commitToWAL(dirtyPages) {
|
|
8776
8785
|
if (this.walManager) {
|
|
8786
|
+
this.logger.debug(`Committing ${dirtyPages.size} pages to WAL`);
|
|
8777
8787
|
await this.walManager.prepareCommit(dirtyPages);
|
|
8778
8788
|
await this.walManager.finalizeCommit(true);
|
|
8779
8789
|
}
|
|
@@ -8785,6 +8795,7 @@ var PageFileSystem = class {
|
|
|
8785
8795
|
* 3. WAL 로그 파일 비우기 (Clear/Truncate)
|
|
8786
8796
|
*/
|
|
8787
8797
|
async checkpoint() {
|
|
8798
|
+
this.logger.info("Starting checkpoint");
|
|
8788
8799
|
await this.runGlobalLock(async () => {
|
|
8789
8800
|
await this.pageStrategy.flush();
|
|
8790
8801
|
await this.pageStrategy.sync();
|
|
@@ -8797,6 +8808,7 @@ var PageFileSystem = class {
|
|
|
8797
8808
|
* Closes the page file system.
|
|
8798
8809
|
*/
|
|
8799
8810
|
async close() {
|
|
8811
|
+
this.logger.info("Closing");
|
|
8800
8812
|
await this.checkpoint();
|
|
8801
8813
|
if (this.walManager) {
|
|
8802
8814
|
this.walManager.close();
|
|
@@ -9038,7 +9050,7 @@ var KeyManager = class {
|
|
|
9038
9050
|
|
|
9039
9051
|
// src/core/RowTableEngine.ts
|
|
9040
9052
|
var RowTableEngine = class {
|
|
9041
|
-
constructor(pfs, txContext, options) {
|
|
9053
|
+
constructor(pfs, txContext, options, logger) {
|
|
9042
9054
|
this.pfs = pfs;
|
|
9043
9055
|
this.txContext = txContext;
|
|
9044
9056
|
this.options = options;
|
|
@@ -9048,6 +9060,7 @@ var RowTableEngine = class {
|
|
|
9048
9060
|
this.overflowPageManager = this.factory.getManagerFromType(OverflowPageManager.CONSTANT.PAGE_TYPE_OVERFLOW);
|
|
9049
9061
|
this.rowManager = new Row();
|
|
9050
9062
|
this.keyManager = new KeyManager();
|
|
9063
|
+
this.logger = logger;
|
|
9051
9064
|
this.ridBuffer = new Uint8Array(Row.CONSTANT.SIZE_RID);
|
|
9052
9065
|
this.pageIdBuffer = new Uint8Array(DataPageManager.CONSTANT.SIZE_PAGE_ID);
|
|
9053
9066
|
this.maxBodySize = this.pfs.pageSize - DataPageManager.CONSTANT.SIZE_PAGE_HEADER;
|
|
@@ -9076,6 +9089,7 @@ var RowTableEngine = class {
|
|
|
9076
9089
|
maxBodySize;
|
|
9077
9090
|
ridBuffer;
|
|
9078
9091
|
pageIdBuffer;
|
|
9092
|
+
logger;
|
|
9079
9093
|
initialized = false;
|
|
9080
9094
|
/**
|
|
9081
9095
|
* Retrieves the BPTree transaction associated with the given transaction.
|
|
@@ -9110,6 +9124,7 @@ var RowTableEngine = class {
|
|
|
9110
9124
|
*/
|
|
9111
9125
|
async init() {
|
|
9112
9126
|
if (!this.initialized) {
|
|
9127
|
+
this.logger.info("Initializing B+ Tree");
|
|
9113
9128
|
await this.bptree.init();
|
|
9114
9129
|
this.initialized = true;
|
|
9115
9130
|
}
|
|
@@ -9157,6 +9172,7 @@ var RowTableEngine = class {
|
|
|
9157
9172
|
* @returns Metadata
|
|
9158
9173
|
*/
|
|
9159
9174
|
async getMetadata(tx) {
|
|
9175
|
+
this.logger.debug("Getting metadata");
|
|
9160
9176
|
if (!this.initialized) {
|
|
9161
9177
|
throw new Error("RowTableEngine instance is not initialized");
|
|
9162
9178
|
}
|
|
@@ -9182,6 +9198,7 @@ var RowTableEngine = class {
|
|
|
9182
9198
|
* @returns Array of PKs of the inserted data
|
|
9183
9199
|
*/
|
|
9184
9200
|
async insert(dataList, incrementRowCount, overflowForcly, tx) {
|
|
9201
|
+
this.logger.debug(`Inserting ${dataList.length} rows (overflowForcly: ${overflowForcly})`);
|
|
9185
9202
|
if (dataList.length === 0) {
|
|
9186
9203
|
return [];
|
|
9187
9204
|
}
|
|
@@ -9283,6 +9300,7 @@ var RowTableEngine = class {
|
|
|
9283
9300
|
* @param tx Transaction
|
|
9284
9301
|
*/
|
|
9285
9302
|
async update(pk, data, tx) {
|
|
9303
|
+
this.logger.debug(`Updating row with PK: ${pk}`);
|
|
9286
9304
|
await tx.__acquireWriteLock(0);
|
|
9287
9305
|
const rid = await this.getRidByPK(pk, tx);
|
|
9288
9306
|
if (rid === null) {
|
|
@@ -9368,6 +9386,7 @@ var RowTableEngine = class {
|
|
|
9368
9386
|
* @param tx Transaction
|
|
9369
9387
|
*/
|
|
9370
9388
|
async delete(pk, decrementRowCount, tx) {
|
|
9389
|
+
this.logger.debug(`Deleting row with PK: ${pk}`);
|
|
9371
9390
|
await tx.__acquireWriteLock(0);
|
|
9372
9391
|
const rid = await this.getRidByPK(pk, tx);
|
|
9373
9392
|
if (rid === null) {
|
|
@@ -9427,6 +9446,7 @@ var RowTableEngine = class {
|
|
|
9427
9446
|
* @returns Raw data of the row
|
|
9428
9447
|
*/
|
|
9429
9448
|
async selectByPK(pk, tx) {
|
|
9449
|
+
this.logger.debug(`Selecting row by PK: ${pk}`);
|
|
9430
9450
|
const rid = await this.getRidByPK(pk, tx);
|
|
9431
9451
|
if (rid === null) {
|
|
9432
9452
|
return null;
|
|
@@ -9441,6 +9461,7 @@ var RowTableEngine = class {
|
|
|
9441
9461
|
* @returns Array of raw data of the rows in the same order as input PKs
|
|
9442
9462
|
*/
|
|
9443
9463
|
async selectMany(pks, tx) {
|
|
9464
|
+
this.logger.debug(`Selecting many rows (${pks.length} PKs)`);
|
|
9444
9465
|
const collections = await this.collectItemsByPage(pks, tx);
|
|
9445
9466
|
return this.fetchRowsByRids(collections, pks.length, tx);
|
|
9446
9467
|
}
|
|
@@ -9828,26 +9849,90 @@ var TransactionContext = class {
|
|
|
9828
9849
|
}
|
|
9829
9850
|
};
|
|
9830
9851
|
|
|
9852
|
+
// src/core/Logger.ts
|
|
9853
|
+
var Colors = {
|
|
9854
|
+
reset: "\x1B[0m",
|
|
9855
|
+
debug: "\x1B[36m",
|
|
9856
|
+
// Cyan
|
|
9857
|
+
info: "\x1B[32m",
|
|
9858
|
+
// Green
|
|
9859
|
+
warn: "\x1B[33m",
|
|
9860
|
+
// Yellow
|
|
9861
|
+
error: "\x1B[31m",
|
|
9862
|
+
// Red
|
|
9863
|
+
white: "\x1B[37m",
|
|
9864
|
+
// White
|
|
9865
|
+
grey: "\x1B[90m"
|
|
9866
|
+
// Grey
|
|
9867
|
+
};
|
|
9868
|
+
var LoggerManager = class {
|
|
9869
|
+
level;
|
|
9870
|
+
constructor(level = 2 /* Info */) {
|
|
9871
|
+
this.level = level;
|
|
9872
|
+
}
|
|
9873
|
+
setLevel(level) {
|
|
9874
|
+
this.level = level;
|
|
9875
|
+
}
|
|
9876
|
+
shouldLog(level) {
|
|
9877
|
+
if (this.level === 0 /* None */) return false;
|
|
9878
|
+
return level >= this.level;
|
|
9879
|
+
}
|
|
9880
|
+
create(moduleName) {
|
|
9881
|
+
return new Logger(this, moduleName);
|
|
9882
|
+
}
|
|
9883
|
+
};
|
|
9884
|
+
var Logger = class {
|
|
9885
|
+
constructor(parent, moduleName) {
|
|
9886
|
+
this.parent = parent;
|
|
9887
|
+
this.moduleName = moduleName;
|
|
9888
|
+
}
|
|
9889
|
+
debug(message, ...args) {
|
|
9890
|
+
if (this.parent.shouldLog(1 /* Debug */)) {
|
|
9891
|
+
console.debug(`${Colors.debug}[DEBUG] [${this.moduleName}]${Colors.reset} ${Colors.white}${message}${Colors.reset}`, ...args);
|
|
9892
|
+
}
|
|
9893
|
+
}
|
|
9894
|
+
info(message, ...args) {
|
|
9895
|
+
if (this.parent.shouldLog(2 /* Info */)) {
|
|
9896
|
+
console.info(`${Colors.info}[INFO] [${this.moduleName}]${Colors.reset} ${Colors.white}${message}${Colors.reset}`, ...args);
|
|
9897
|
+
}
|
|
9898
|
+
}
|
|
9899
|
+
warn(message, ...args) {
|
|
9900
|
+
if (this.parent.shouldLog(3 /* Warning */)) {
|
|
9901
|
+
console.warn(`${Colors.warn}[WARN] [${this.moduleName}]${Colors.reset} ${Colors.white}${message}${Colors.reset}`, ...args);
|
|
9902
|
+
}
|
|
9903
|
+
}
|
|
9904
|
+
error(message, ...args) {
|
|
9905
|
+
if (this.parent.shouldLog(4 /* Error */)) {
|
|
9906
|
+
console.error(`${Colors.error}[ERROR] [${this.moduleName}]${Colors.reset} ${Colors.white}${message}${Colors.reset}`, ...args);
|
|
9907
|
+
}
|
|
9908
|
+
}
|
|
9909
|
+
};
|
|
9910
|
+
|
|
9831
9911
|
// src/core/DataplyAPI.ts
|
|
9832
9912
|
var DataplyAPI = class {
|
|
9833
9913
|
constructor(file, options) {
|
|
9834
9914
|
this.file = file;
|
|
9835
9915
|
this.hook = useHookall(this);
|
|
9836
9916
|
this.options = this.verboseOptions(options);
|
|
9917
|
+
this.loggerManager = new LoggerManager(this.options.logLevel);
|
|
9918
|
+
this.logger = this.loggerManager.create("DataplyAPI");
|
|
9837
9919
|
this.isNewlyCreated = !import_node_fs3.default.existsSync(file);
|
|
9838
9920
|
this.fileHandle = this.createOrOpen(file, this.options);
|
|
9839
9921
|
this.pfs = new PageFileSystem(
|
|
9840
9922
|
this.fileHandle,
|
|
9841
9923
|
this.options.pageSize,
|
|
9842
9924
|
this.options.pageCacheCapacity,
|
|
9843
|
-
this.options
|
|
9925
|
+
this.options,
|
|
9926
|
+
this.loggerManager.create("PageFileSystem"),
|
|
9927
|
+
options.wal ? this.loggerManager.create("WALManager") : void 0
|
|
9844
9928
|
);
|
|
9845
9929
|
this.textCodec = new TextCodec();
|
|
9846
9930
|
this.txContext = new TransactionContext();
|
|
9847
9931
|
this.lockManager = new LockManager();
|
|
9848
|
-
this.rowTableEngine = new RowTableEngine(this.pfs, this.txContext, this.options);
|
|
9932
|
+
this.rowTableEngine = new RowTableEngine(this.pfs, this.txContext, this.options, this.loggerManager.create("RowTableEngine"));
|
|
9849
9933
|
this.initialized = false;
|
|
9850
9934
|
this.txIdCounter = 0;
|
|
9935
|
+
this.logger.debug(`DataplyAPI instance created with file: ${file}`);
|
|
9851
9936
|
}
|
|
9852
9937
|
/**
|
|
9853
9938
|
* These are not the same options that were used when the database was created.
|
|
@@ -9869,6 +9954,10 @@ var DataplyAPI = class {
|
|
|
9869
9954
|
txContext;
|
|
9870
9955
|
/** Hook */
|
|
9871
9956
|
hook;
|
|
9957
|
+
/** Base Logger */
|
|
9958
|
+
loggerManager;
|
|
9959
|
+
/** Logger module for DataplyAPI */
|
|
9960
|
+
logger;
|
|
9872
9961
|
/** Whether the database was initialized via `init()` */
|
|
9873
9962
|
initialized;
|
|
9874
9963
|
/** Whether the database was created this time. */
|
|
@@ -9883,6 +9972,7 @@ var DataplyAPI = class {
|
|
|
9883
9972
|
* @returns Whether the page file is a valid Dataply file
|
|
9884
9973
|
*/
|
|
9885
9974
|
verifyFormat(fileHandle) {
|
|
9975
|
+
this.logger.debug(`Verifying format for file handle: ${fileHandle}`);
|
|
9886
9976
|
const size = MetadataPageManager.CONSTANT.OFFSET_MAGIC_STRING + MetadataPageManager.CONSTANT.MAGIC_STRING.length;
|
|
9887
9977
|
const metadataPage = new Uint8Array(size);
|
|
9888
9978
|
import_node_fs3.default.readSync(fileHandle, metadataPage, 0, size, 0);
|
|
@@ -9902,7 +9992,8 @@ var DataplyAPI = class {
|
|
|
9902
9992
|
pageCacheCapacity: 1e4,
|
|
9903
9993
|
pagePreallocationCount: 1e3,
|
|
9904
9994
|
wal: null,
|
|
9905
|
-
walCheckpointThreshold: 1e3
|
|
9995
|
+
walCheckpointThreshold: 1e3,
|
|
9996
|
+
logLevel: 2 /* Info */
|
|
9906
9997
|
}, options);
|
|
9907
9998
|
}
|
|
9908
9999
|
/**
|
|
@@ -9913,6 +10004,7 @@ var DataplyAPI = class {
|
|
|
9913
10004
|
* @param fileHandle File handle
|
|
9914
10005
|
*/
|
|
9915
10006
|
initializeFile(file, fileHandle, options) {
|
|
10007
|
+
this.logger.info(`Initializing new dataply file: ${file}`);
|
|
9916
10008
|
const metadataPageManager = new MetadataPageManager();
|
|
9917
10009
|
const bitmapPageManager = new BitmapPageManager();
|
|
9918
10010
|
const dataPageManager = new DataPageManager();
|
|
@@ -9962,6 +10054,7 @@ var DataplyAPI = class {
|
|
|
9962
10054
|
* @returns File handle
|
|
9963
10055
|
*/
|
|
9964
10056
|
createOrOpen(file, options) {
|
|
10057
|
+
this.logger.info(`Opening dataply file: ${file}`);
|
|
9965
10058
|
let fileHandle;
|
|
9966
10059
|
if (options.pageCacheCapacity < 100) {
|
|
9967
10060
|
throw new Error("Page cache capacity must be at least 100");
|
|
@@ -9997,6 +10090,7 @@ var DataplyAPI = class {
|
|
|
9997
10090
|
* If not called, the dataply instance cannot be used.
|
|
9998
10091
|
*/
|
|
9999
10092
|
async init() {
|
|
10093
|
+
this.logger.info("Initializing DataplyAPI");
|
|
10000
10094
|
if (this.initialized) {
|
|
10001
10095
|
return;
|
|
10002
10096
|
}
|
|
@@ -10016,6 +10110,7 @@ var DataplyAPI = class {
|
|
|
10016
10110
|
* @returns Transaction object
|
|
10017
10111
|
*/
|
|
10018
10112
|
createTransaction() {
|
|
10113
|
+
this.logger.debug(`Creating transaction: ${this.txIdCounter + 1}`);
|
|
10019
10114
|
return new Transaction(
|
|
10020
10115
|
++this.txIdCounter,
|
|
10021
10116
|
this.txContext,
|
|
@@ -10040,6 +10135,7 @@ var DataplyAPI = class {
|
|
|
10040
10135
|
* @returns A release function
|
|
10041
10136
|
*/
|
|
10042
10137
|
acquireWriteLock() {
|
|
10138
|
+
this.logger.debug("Acquiring write lock");
|
|
10043
10139
|
const previous = this.writeQueue;
|
|
10044
10140
|
let release;
|
|
10045
10141
|
this.writeQueue = new Promise((resolve) => {
|
|
@@ -10057,6 +10153,7 @@ var DataplyAPI = class {
|
|
|
10057
10153
|
* @returns The result of the callback.
|
|
10058
10154
|
*/
|
|
10059
10155
|
async runWithDefaultWrite(callback, tx) {
|
|
10156
|
+
this.logger.debug("Running with default write transaction");
|
|
10060
10157
|
if (!tx) {
|
|
10061
10158
|
const release = await this.acquireWriteLock();
|
|
10062
10159
|
const internalTx = this.createTransaction();
|
|
@@ -10080,6 +10177,7 @@ var DataplyAPI = class {
|
|
|
10080
10177
|
return result;
|
|
10081
10178
|
}
|
|
10082
10179
|
async runWithDefault(callback, tx) {
|
|
10180
|
+
this.logger.debug("Running with default transaction");
|
|
10083
10181
|
const isInternalTx = !tx;
|
|
10084
10182
|
if (!tx) {
|
|
10085
10183
|
tx = this.createTransaction();
|
|
@@ -10107,6 +10205,7 @@ var DataplyAPI = class {
|
|
|
10107
10205
|
* @returns An AsyncGenerator that yields values from the callback.
|
|
10108
10206
|
*/
|
|
10109
10207
|
async *streamWithDefault(callback, tx) {
|
|
10208
|
+
this.logger.debug("Streaming with default transaction");
|
|
10110
10209
|
const isInternalTx = !tx;
|
|
10111
10210
|
if (!tx) {
|
|
10112
10211
|
tx = this.createTransaction();
|
|
@@ -10134,6 +10233,7 @@ var DataplyAPI = class {
|
|
|
10134
10233
|
* @returns Metadata of the dataply.
|
|
10135
10234
|
*/
|
|
10136
10235
|
async getMetadata(tx) {
|
|
10236
|
+
this.logger.debug("Getting metadata");
|
|
10137
10237
|
if (!this.initialized) {
|
|
10138
10238
|
throw new Error("Dataply instance is not initialized");
|
|
10139
10239
|
}
|
|
@@ -10147,6 +10247,7 @@ var DataplyAPI = class {
|
|
|
10147
10247
|
* @returns PK of the added data
|
|
10148
10248
|
*/
|
|
10149
10249
|
async insert(data, incrementRowCount, tx) {
|
|
10250
|
+
this.logger.debug("Inserting data");
|
|
10150
10251
|
if (!this.initialized) {
|
|
10151
10252
|
throw new Error("Dataply instance is not initialized");
|
|
10152
10253
|
}
|
|
@@ -10167,6 +10268,7 @@ var DataplyAPI = class {
|
|
|
10167
10268
|
* @returns PK of the added data
|
|
10168
10269
|
*/
|
|
10169
10270
|
async insertAsOverflow(data, incrementRowCount, tx) {
|
|
10271
|
+
this.logger.debug("Inserting data as overflow");
|
|
10170
10272
|
if (!this.initialized) {
|
|
10171
10273
|
throw new Error("Dataply instance is not initialized");
|
|
10172
10274
|
}
|
|
@@ -10188,6 +10290,7 @@ var DataplyAPI = class {
|
|
|
10188
10290
|
* @returns Array of PKs of the added data
|
|
10189
10291
|
*/
|
|
10190
10292
|
async insertBatch(dataList, incrementRowCount, tx) {
|
|
10293
|
+
this.logger.debug(`Inserting batch data: ${dataList.length} items`);
|
|
10191
10294
|
if (!this.initialized) {
|
|
10192
10295
|
throw new Error("Dataply instance is not initialized");
|
|
10193
10296
|
}
|
|
@@ -10206,6 +10309,7 @@ var DataplyAPI = class {
|
|
|
10206
10309
|
* @param tx Transaction
|
|
10207
10310
|
*/
|
|
10208
10311
|
async update(pk, data, tx) {
|
|
10312
|
+
this.logger.debug(`Updating data for PK: ${pk}`);
|
|
10209
10313
|
if (!this.initialized) {
|
|
10210
10314
|
throw new Error("Dataply instance is not initialized");
|
|
10211
10315
|
}
|
|
@@ -10223,6 +10327,7 @@ var DataplyAPI = class {
|
|
|
10223
10327
|
* @param tx Transaction
|
|
10224
10328
|
*/
|
|
10225
10329
|
async delete(pk, decrementRowCount, tx) {
|
|
10330
|
+
this.logger.debug(`Deleting data for PK: ${pk}`);
|
|
10226
10331
|
if (!this.initialized) {
|
|
10227
10332
|
throw new Error("Dataply instance is not initialized");
|
|
10228
10333
|
}
|
|
@@ -10232,6 +10337,7 @@ var DataplyAPI = class {
|
|
|
10232
10337
|
}, tx);
|
|
10233
10338
|
}
|
|
10234
10339
|
async select(pk, asRaw = false, tx) {
|
|
10340
|
+
this.logger.debug(`Selecting data for PK: ${pk}`);
|
|
10235
10341
|
if (!this.initialized) {
|
|
10236
10342
|
throw new Error("Dataply instance is not initialized");
|
|
10237
10343
|
}
|
|
@@ -10243,6 +10349,7 @@ var DataplyAPI = class {
|
|
|
10243
10349
|
}, tx);
|
|
10244
10350
|
}
|
|
10245
10351
|
async selectMany(pks, asRaw = false, tx) {
|
|
10352
|
+
this.logger.debug(`Selecting many data: ${pks.length} keys`);
|
|
10246
10353
|
if (!this.initialized) {
|
|
10247
10354
|
throw new Error("Dataply instance is not initialized");
|
|
10248
10355
|
}
|
|
@@ -10259,6 +10366,7 @@ var DataplyAPI = class {
|
|
|
10259
10366
|
* Closes the dataply file.
|
|
10260
10367
|
*/
|
|
10261
10368
|
async close() {
|
|
10369
|
+
this.logger.info("Closing DataplyAPI");
|
|
10262
10370
|
if (!this.initialized) {
|
|
10263
10371
|
throw new Error("Dataply instance is not initialized");
|
|
10264
10372
|
}
|
|
@@ -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 { LoggerManager, Logger } from './Logger';
|
|
9
10
|
interface DataplyAPIAsyncHook {
|
|
10
11
|
init: (tx: Transaction, isNewlyCreated: boolean) => Promise<Transaction>;
|
|
11
12
|
close: () => Promise<void>;
|
|
@@ -35,6 +36,10 @@ export declare class DataplyAPI {
|
|
|
35
36
|
protected readonly txContext: TransactionContext;
|
|
36
37
|
/** Hook */
|
|
37
38
|
protected readonly hook: IHookall<DataplyAPIAsyncHook>;
|
|
39
|
+
/** Base Logger */
|
|
40
|
+
protected readonly loggerManager: LoggerManager;
|
|
41
|
+
/** Logger module for DataplyAPI */
|
|
42
|
+
protected readonly logger: Logger;
|
|
38
43
|
/** Whether the database was initialized via `init()` */
|
|
39
44
|
protected initialized: boolean;
|
|
40
45
|
/** Whether the database was created this time. */
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { LogLevel } from '../types';
|
|
2
|
+
export declare class LoggerManager {
|
|
3
|
+
private level;
|
|
4
|
+
constructor(level?: LogLevel);
|
|
5
|
+
setLevel(level: LogLevel): void;
|
|
6
|
+
shouldLog(level: LogLevel): boolean;
|
|
7
|
+
create(moduleName: string): Logger;
|
|
8
|
+
}
|
|
9
|
+
export declare class Logger {
|
|
10
|
+
private readonly parent;
|
|
11
|
+
private readonly moduleName;
|
|
12
|
+
constructor(parent: LoggerManager, moduleName: string);
|
|
13
|
+
debug(message: string, ...args: any[]): void;
|
|
14
|
+
info(message: string, ...args: any[]): void;
|
|
15
|
+
warn(message: string, ...args: any[]): void;
|
|
16
|
+
error(message: string, ...args: any[]): void;
|
|
17
|
+
}
|
|
@@ -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 기반으로 페이지 관리를 수행합니다.
|
|
@@ -16,13 +17,14 @@ export declare class PageFileSystem {
|
|
|
16
17
|
protected readonly walManager: WALManager | null;
|
|
17
18
|
protected readonly pageManagerFactory: PageManagerFactory;
|
|
18
19
|
protected readonly pageStrategy: PageMVCCStrategy;
|
|
20
|
+
protected readonly logger: Logger;
|
|
19
21
|
/** 글로벌 동기화(체크포인트/커밋)를 위한 Mutex */
|
|
20
22
|
private lockPromise;
|
|
21
23
|
/**
|
|
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, walLogger?: Logger);
|
|
26
28
|
/**
|
|
27
29
|
* 글로벌 동기화 범위 내에서 작업을 실행합니다.
|
|
28
30
|
* @param task 수행할 비동기 작업
|
|
@@ -7,6 +7,7 @@ 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;
|
|
@@ -23,8 +24,9 @@ export declare class RowTableEngine {
|
|
|
23
24
|
protected readonly maxBodySize: number;
|
|
24
25
|
private readonly ridBuffer;
|
|
25
26
|
private readonly pageIdBuffer;
|
|
27
|
+
private readonly logger;
|
|
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,3 +1,4 @@
|
|
|
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.
|
|
@@ -11,12 +12,14 @@ export declare class WALManager {
|
|
|
11
12
|
private buffer;
|
|
12
13
|
private view;
|
|
13
14
|
private totalWrittenPages;
|
|
15
|
+
private readonly logger;
|
|
14
16
|
/**
|
|
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
|
/**
|