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 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
- console.warn(`[WALManager] Checksum verification failed for PageID ${pageId} during recovery. Ignoring changes.`);
8107
+ this.logger.warn(`Checksum verification failed for PageID ${pageId} during recovery. Ignoring changes.`);
8105
8108
  continue;
8106
8109
  }
8107
8110
  } catch (e) {
8108
- console.warn(`[WALManager] Failed to verify checksum for PageID ${pageId} during recovery: ${e}. Ignoring changes.`);
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 { DataplyOptions, DataplyMetadata } from '../types';
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
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dataply",
3
- "version": "0.0.25",
3
+ "version": "0.0.26-alpha.1",
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>",