dataply 0.0.20-alpha.3 → 0.0.20-alpha.5
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
|
@@ -7606,9 +7606,7 @@ var PageMVCCStrategy = class extends AsyncMVCCStrategy2 {
|
|
|
7606
7606
|
}
|
|
7607
7607
|
const cached = this.cache.get(pageId);
|
|
7608
7608
|
if (cached) {
|
|
7609
|
-
|
|
7610
|
-
copy.set(cached);
|
|
7611
|
-
return copy;
|
|
7609
|
+
return cached;
|
|
7612
7610
|
}
|
|
7613
7611
|
const buffer = new Uint8Array(this.pageSize);
|
|
7614
7612
|
const pageStartPos = pageId * this.pageSize;
|
|
@@ -7648,13 +7646,14 @@ var PageMVCCStrategy = class extends AsyncMVCCStrategy2 {
|
|
|
7648
7646
|
if (this.dirtyPages.size === 0) {
|
|
7649
7647
|
return;
|
|
7650
7648
|
}
|
|
7651
|
-
const
|
|
7649
|
+
const snapshot = new Map(this.dirtyPages);
|
|
7650
|
+
const sortedPageIds = Array.from(snapshot.keys()).sort((a, b) => a - b);
|
|
7652
7651
|
for (const pageId of sortedPageIds) {
|
|
7653
|
-
const data =
|
|
7652
|
+
const data = snapshot.get(pageId);
|
|
7654
7653
|
const position = pageId * this.pageSize;
|
|
7655
7654
|
await this._writeToDisk(data, position);
|
|
7655
|
+
this.dirtyPages.delete(pageId);
|
|
7656
7656
|
}
|
|
7657
|
-
this.dirtyPages.clear();
|
|
7658
7657
|
}
|
|
7659
7658
|
/**
|
|
7660
7659
|
* 메인 DB 파일의 물리적 동기화를 수행합니다 (fsync).
|
|
@@ -7736,13 +7735,30 @@ var PageFileSystem = class {
|
|
|
7736
7735
|
this.walManager = walPath ? new WALManager(walPath, pageSize) : null;
|
|
7737
7736
|
this.pageManagerFactory = new PageManagerFactory();
|
|
7738
7737
|
this.pageStrategy = new PageMVCCStrategy(fileHandle, pageSize, pageCacheCapacity);
|
|
7739
|
-
this.lock = new Ryoiki3();
|
|
7740
7738
|
}
|
|
7741
7739
|
pageFactory = new PageManagerFactory();
|
|
7742
7740
|
walManager;
|
|
7743
7741
|
pageManagerFactory;
|
|
7744
7742
|
pageStrategy;
|
|
7745
|
-
|
|
7743
|
+
/** 글로벌 동기화(체크포인트/커밋)를 위한 Mutex */
|
|
7744
|
+
lockPromise = Promise.resolve();
|
|
7745
|
+
/**
|
|
7746
|
+
* 글로벌 동기화 범위 내에서 작업을 실행합니다.
|
|
7747
|
+
* @param task 수행할 비동기 작업
|
|
7748
|
+
*/
|
|
7749
|
+
async runGlobalLock(task) {
|
|
7750
|
+
const previous = this.lockPromise;
|
|
7751
|
+
let resolveLock;
|
|
7752
|
+
this.lockPromise = new Promise((resolve) => {
|
|
7753
|
+
resolveLock = resolve;
|
|
7754
|
+
});
|
|
7755
|
+
await previous;
|
|
7756
|
+
try {
|
|
7757
|
+
return await task();
|
|
7758
|
+
} finally {
|
|
7759
|
+
resolveLock();
|
|
7760
|
+
}
|
|
7761
|
+
}
|
|
7746
7762
|
/**
|
|
7747
7763
|
* Initializes the page file system.
|
|
7748
7764
|
* Performs WAL recovery if necessary.
|
|
@@ -7755,15 +7771,6 @@ var PageFileSystem = class {
|
|
|
7755
7771
|
await this.checkpoint();
|
|
7756
7772
|
}
|
|
7757
7773
|
}
|
|
7758
|
-
async lockCheckpoint(fn) {
|
|
7759
|
-
let lockId;
|
|
7760
|
-
return this.lock.writeLock(async (_lockId) => {
|
|
7761
|
-
lockId = _lockId;
|
|
7762
|
-
await fn();
|
|
7763
|
-
}).finally(() => {
|
|
7764
|
-
this.lock.writeUnlock(lockId);
|
|
7765
|
-
});
|
|
7766
|
-
}
|
|
7767
7774
|
/**
|
|
7768
7775
|
* Returns the page strategy for transaction use.
|
|
7769
7776
|
*/
|
|
@@ -8071,7 +8078,7 @@ var PageFileSystem = class {
|
|
|
8071
8078
|
* 3. WAL 로그 파일 비우기 (Clear/Truncate)
|
|
8072
8079
|
*/
|
|
8073
8080
|
async checkpoint() {
|
|
8074
|
-
|
|
8081
|
+
await this.runGlobalLock(async () => {
|
|
8075
8082
|
await this.pageStrategy.flush();
|
|
8076
8083
|
await this.pageStrategy.sync();
|
|
8077
8084
|
if (this.walManager) {
|
|
@@ -8707,6 +8714,30 @@ var RowTableEngine = class {
|
|
|
8707
8714
|
}
|
|
8708
8715
|
return this.fetchRowByRid(pk, rid, tx);
|
|
8709
8716
|
}
|
|
8717
|
+
/**
|
|
8718
|
+
* Selects multiple rows by their PKs in a single B+ Tree traversal.
|
|
8719
|
+
* @param pks Array of PKs to look up
|
|
8720
|
+
* @param tx Transaction
|
|
8721
|
+
* @returns Array of raw data of the rows in the same order as input PKs
|
|
8722
|
+
*/
|
|
8723
|
+
async selectMany(pks, tx) {
|
|
8724
|
+
if (pks.length === 0) {
|
|
8725
|
+
return [];
|
|
8726
|
+
}
|
|
8727
|
+
const minPk = Math.min(...pks);
|
|
8728
|
+
const maxPk = Math.max(...pks);
|
|
8729
|
+
const pkSet = new Set(pks);
|
|
8730
|
+
const resultMap = /* @__PURE__ */ new Map();
|
|
8731
|
+
const btx = await this.getBPTreeTransaction(tx);
|
|
8732
|
+
const stream = btx.whereStream({ gte: minPk, lte: maxPk });
|
|
8733
|
+
for await (const [rid, pk] of stream) {
|
|
8734
|
+
if (pkSet.has(pk)) {
|
|
8735
|
+
const rowData = await this.fetchRowByRid(pk, rid, tx);
|
|
8736
|
+
resultMap.set(pk, rowData);
|
|
8737
|
+
}
|
|
8738
|
+
}
|
|
8739
|
+
return pks.map((pk) => resultMap.get(pk) ?? null);
|
|
8740
|
+
}
|
|
8710
8741
|
async fetchRowByRid(pk, rid, tx) {
|
|
8711
8742
|
this.keyManager.setBufferFromKey(rid, this.ridBuffer);
|
|
8712
8743
|
const pageId = this.keyManager.getPageId(this.ridBuffer);
|
|
@@ -8905,12 +8936,13 @@ var Transaction = class {
|
|
|
8905
8936
|
* Commits the transaction.
|
|
8906
8937
|
*/
|
|
8907
8938
|
async commit() {
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8939
|
+
await this.context.run(this, async () => {
|
|
8940
|
+
for (const hook of this.commitHooks) {
|
|
8941
|
+
await hook();
|
|
8942
|
+
}
|
|
8943
|
+
});
|
|
8944
|
+
let shouldTriggerCheckpoint = false;
|
|
8945
|
+
await this.pfs.runGlobalLock(async () => {
|
|
8914
8946
|
if (this.pfs.wal && this.dirtyPages.size > 0) {
|
|
8915
8947
|
await this.pfs.wal.prepareCommit(this.dirtyPages);
|
|
8916
8948
|
await this.pfs.wal.writeCommitMarker();
|
|
@@ -8921,13 +8953,16 @@ var Transaction = class {
|
|
|
8921
8953
|
if (this.pfs.wal) {
|
|
8922
8954
|
this.pfs.wal.incrementWrittenPages(this.dirtyPages.size);
|
|
8923
8955
|
if (this.pfs.wal.shouldCheckpoint(this.pfs.options.walCheckpointThreshold)) {
|
|
8924
|
-
|
|
8956
|
+
shouldTriggerCheckpoint = true;
|
|
8925
8957
|
}
|
|
8926
8958
|
}
|
|
8927
|
-
this.dirtyPages.clear();
|
|
8928
|
-
this.undoPages.clear();
|
|
8929
|
-
this.releaseAllLocks();
|
|
8930
8959
|
});
|
|
8960
|
+
if (shouldTriggerCheckpoint) {
|
|
8961
|
+
await this.pfs.checkpoint();
|
|
8962
|
+
}
|
|
8963
|
+
this.dirtyPages.clear();
|
|
8964
|
+
this.undoPages.clear();
|
|
8965
|
+
this.releaseAllLocks();
|
|
8931
8966
|
}
|
|
8932
8967
|
/**
|
|
8933
8968
|
* Rolls back the transaction.
|
|
@@ -9338,6 +9373,19 @@ var DataplyAPI = class {
|
|
|
9338
9373
|
return this.textCodec.decode(data);
|
|
9339
9374
|
}, tx);
|
|
9340
9375
|
}
|
|
9376
|
+
async selectMany(pks, asRaw = false, tx) {
|
|
9377
|
+
if (!this.initialized) {
|
|
9378
|
+
throw new Error("Dataply instance is not initialized");
|
|
9379
|
+
}
|
|
9380
|
+
return this.runWithDefault(async (tx2) => {
|
|
9381
|
+
const results = await this.rowTableEngine.selectMany(pks, tx2);
|
|
9382
|
+
return results.map((data) => {
|
|
9383
|
+
if (data === null) return null;
|
|
9384
|
+
if (asRaw) return data;
|
|
9385
|
+
return this.textCodec.decode(data);
|
|
9386
|
+
});
|
|
9387
|
+
}, tx);
|
|
9388
|
+
}
|
|
9341
9389
|
/**
|
|
9342
9390
|
* Closes the dataply file.
|
|
9343
9391
|
*/
|
|
@@ -9428,6 +9476,9 @@ var Dataply = class {
|
|
|
9428
9476
|
async select(pk, asRaw = false, tx) {
|
|
9429
9477
|
return this.api.select(pk, asRaw, tx);
|
|
9430
9478
|
}
|
|
9479
|
+
async selectMany(pks, asRaw = false, tx) {
|
|
9480
|
+
return this.api.selectMany(pks, asRaw, tx);
|
|
9481
|
+
}
|
|
9431
9482
|
/**
|
|
9432
9483
|
* Closes the dataply file.
|
|
9433
9484
|
*/
|
|
@@ -68,6 +68,16 @@ export declare class Dataply {
|
|
|
68
68
|
select(pk: number, asRaw: true, tx?: Transaction): Promise<Uint8Array | null>;
|
|
69
69
|
select(pk: number, asRaw: false, tx?: Transaction): Promise<string | null>;
|
|
70
70
|
select(pk: number, asRaw?: boolean, tx?: Transaction): Promise<string | null>;
|
|
71
|
+
/**
|
|
72
|
+
* Selects multiple data by their PKs.
|
|
73
|
+
* @param pks Array of PKs to select
|
|
74
|
+
* @param asRaw Whether to return the selected data as raw
|
|
75
|
+
* @param tx Transaction
|
|
76
|
+
* @returns Array of selected data in the same order as input PKs
|
|
77
|
+
*/
|
|
78
|
+
selectMany(pks: number[], asRaw: true, tx?: Transaction): Promise<(Uint8Array | null)[]>;
|
|
79
|
+
selectMany(pks: number[], asRaw: false, tx?: Transaction): Promise<(string | null)[]>;
|
|
80
|
+
selectMany(pks: number[], asRaw?: boolean, tx?: Transaction): Promise<(string | null)[]>;
|
|
71
81
|
/**
|
|
72
82
|
* Closes the dataply file.
|
|
73
83
|
*/
|
|
@@ -157,6 +157,16 @@ export declare class DataplyAPI {
|
|
|
157
157
|
select(pk: number, asRaw: true, tx?: Transaction): Promise<Uint8Array | null>;
|
|
158
158
|
select(pk: number, asRaw: false, tx?: Transaction): Promise<string | null>;
|
|
159
159
|
select(pk: number, asRaw?: boolean, tx?: Transaction): Promise<string | null>;
|
|
160
|
+
/**
|
|
161
|
+
* Selects multiple data by their PKs.
|
|
162
|
+
* @param pks Array of PKs to select
|
|
163
|
+
* @param asRaw Whether to return the selected data as raw
|
|
164
|
+
* @param tx Transaction
|
|
165
|
+
* @returns Array of selected data in the same order as input PKs
|
|
166
|
+
*/
|
|
167
|
+
selectMany(pks: number[], asRaw: true, tx?: Transaction): Promise<(Uint8Array | null)[]>;
|
|
168
|
+
selectMany(pks: number[], asRaw: false, tx?: Transaction): Promise<(string | null)[]>;
|
|
169
|
+
selectMany(pks: number[], asRaw?: boolean, tx?: Transaction): Promise<(string | null)[]>;
|
|
160
170
|
/**
|
|
161
171
|
* Closes the dataply file.
|
|
162
172
|
*/
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { IndexPage, MetadataPage, DataplyOptions } from '../types';
|
|
2
|
-
import { Ryoiki } from 'ryoiki';
|
|
3
2
|
import type { Transaction } from './transaction/Transaction';
|
|
4
3
|
import { PageManagerFactory } from './Page';
|
|
5
4
|
import { WALManager } from './WALManager';
|
|
@@ -17,18 +16,23 @@ export declare class PageFileSystem {
|
|
|
17
16
|
protected readonly walManager: WALManager | null;
|
|
18
17
|
protected readonly pageManagerFactory: PageManagerFactory;
|
|
19
18
|
protected readonly pageStrategy: PageMVCCStrategy;
|
|
20
|
-
|
|
19
|
+
/** 글로벌 동기화(체크포인트/커밋)를 위한 Mutex */
|
|
20
|
+
private lockPromise;
|
|
21
21
|
/**
|
|
22
22
|
* @param pageCacheCapacity 페이지 캐시 크기
|
|
23
23
|
* @param options 데이터플라이 옵션
|
|
24
24
|
*/
|
|
25
25
|
constructor(fileHandle: number, pageSize: number, pageCacheCapacity: number, options: Required<DataplyOptions>);
|
|
26
|
+
/**
|
|
27
|
+
* 글로벌 동기화 범위 내에서 작업을 실행합니다.
|
|
28
|
+
* @param task 수행할 비동기 작업
|
|
29
|
+
*/
|
|
30
|
+
runGlobalLock<T>(task: () => Promise<T>): Promise<T>;
|
|
26
31
|
/**
|
|
27
32
|
* Initializes the page file system.
|
|
28
33
|
* Performs WAL recovery if necessary.
|
|
29
34
|
*/
|
|
30
35
|
init(): Promise<void>;
|
|
31
|
-
lockCheckpoint(fn: () => Promise<void>): Promise<void>;
|
|
32
36
|
/**
|
|
33
37
|
* Returns the page strategy for transaction use.
|
|
34
38
|
*/
|
|
@@ -123,6 +123,13 @@ export declare class RowTableEngine {
|
|
|
123
123
|
* @returns Raw data of the row
|
|
124
124
|
*/
|
|
125
125
|
selectByPK(pk: number, tx: Transaction): Promise<Uint8Array | null>;
|
|
126
|
+
/**
|
|
127
|
+
* Selects multiple rows by their PKs in a single B+ Tree traversal.
|
|
128
|
+
* @param pks Array of PKs to look up
|
|
129
|
+
* @param tx Transaction
|
|
130
|
+
* @returns Array of raw data of the rows in the same order as input PKs
|
|
131
|
+
*/
|
|
132
|
+
selectMany(pks: number[], tx: Transaction): Promise<(Uint8Array | null)[]>;
|
|
126
133
|
private fetchRowByRid;
|
|
127
134
|
/**
|
|
128
135
|
* Returns the count of rows.
|