@feltdb/core 0.11.6 → 0.11.7
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/create/package-versions.js +1 -1
- package/dist/file-db.d.ts +143 -14
- package/dist/file-db.d.ts.map +1 -1
- package/dist/file-db.js +690 -244
- package/dist/file-journal.d.ts +70 -0
- package/dist/file-journal.d.ts.map +1 -0
- package/dist/file-journal.js +184 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// One release train keeps generated applications installable. The repository
|
|
2
2
|
// validation script checks these values against every workspace manifest.
|
|
3
|
-
export const FELTDB_PACKAGE_VERSION = '0.11.
|
|
3
|
+
export const FELTDB_PACKAGE_VERSION = '0.11.7';
|
|
4
4
|
export const feltdbPackageRange = `^${FELTDB_PACKAGE_VERSION}`;
|
package/dist/file-db.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ import type { FreshnessCapability } from './freshness.js';
|
|
|
3
3
|
import type { OperationAdmissionInput, OperationAdmissionResult, OperationTransitionInput, OperationTransitionResult } from './operation-admission.js';
|
|
4
4
|
import type { AtomicTransactionRequest, AtomicTransactionResult } from './transaction.js';
|
|
5
5
|
import type { AuthorityQueryRequest } from './http-db.js';
|
|
6
|
+
import { type PersistenceProfile } from './file-journal.js';
|
|
7
|
+
export { JournalCorruptionError } from './file-journal.js';
|
|
8
|
+
export type { PersistenceProfile, PersistencePhase, PhaseSummary } from './file-journal.js';
|
|
6
9
|
interface JsResult {
|
|
7
10
|
success: boolean;
|
|
8
11
|
data?: string;
|
|
@@ -18,11 +21,49 @@ interface PortableEvent {
|
|
|
18
21
|
origin: string;
|
|
19
22
|
value?: unknown;
|
|
20
23
|
}
|
|
24
|
+
export interface FileJsDbOptions {
|
|
25
|
+
compaction?: {
|
|
26
|
+
/**
|
|
27
|
+
* `auto` (default) compacts after a commit once the journal is large
|
|
28
|
+
* enough, outside that commit's acknowledgement. `manual` compacts only
|
|
29
|
+
* when `compact()` is called.
|
|
30
|
+
*/
|
|
31
|
+
mode?: 'auto' | 'manual';
|
|
32
|
+
/** Never compact automatically below this journal size. Default 8 MiB. */
|
|
33
|
+
minJournalBytes?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Compact automatically once the journal exceeds this multiple of the
|
|
36
|
+
* snapshot. Default 1, which bounds the bytes rewritten per byte
|
|
37
|
+
* appended to a constant over time.
|
|
38
|
+
*/
|
|
39
|
+
journalToSnapshotRatio?: number;
|
|
40
|
+
};
|
|
41
|
+
/** Collect persistence timings. Also enabled by `FELTDB_PERSISTENCE_PROFILE=1`. */
|
|
42
|
+
profile?: boolean;
|
|
43
|
+
}
|
|
44
|
+
export interface PersistenceStatus {
|
|
45
|
+
format: 'none' | 'legacy-snapshot' | 'snapshot+journal';
|
|
46
|
+
source: 'primary' | 'backup' | 'empty';
|
|
47
|
+
generation: number;
|
|
48
|
+
commit: number;
|
|
49
|
+
sequence: number;
|
|
50
|
+
snapshotBytes: number;
|
|
51
|
+
journalBytes: number;
|
|
52
|
+
journalRecords: number;
|
|
53
|
+
recovery: 'clean' | {
|
|
54
|
+
tornTail: {
|
|
55
|
+
byteOffset: number;
|
|
56
|
+
discardedBytes: number;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
}
|
|
21
60
|
export declare class FileJsDb implements JsDb {
|
|
22
61
|
private readonly dataPath;
|
|
23
62
|
private readonly statePath;
|
|
63
|
+
private readonly backupPath;
|
|
24
64
|
private readonly lockPath;
|
|
25
65
|
private state;
|
|
66
|
+
private view;
|
|
26
67
|
private readonly origin;
|
|
27
68
|
private readonly peers;
|
|
28
69
|
private lockFd;
|
|
@@ -30,11 +71,104 @@ export declare class FileJsDb implements JsDb {
|
|
|
30
71
|
private readonly applied;
|
|
31
72
|
private readonly queryEngine;
|
|
32
73
|
private indexedSequence;
|
|
33
|
-
|
|
34
|
-
private
|
|
35
|
-
private
|
|
74
|
+
private readonly profiler;
|
|
75
|
+
private readonly compaction;
|
|
76
|
+
private compactionScheduled;
|
|
77
|
+
constructor(path: string, options?: FileJsDbOptions);
|
|
78
|
+
private journalPath;
|
|
79
|
+
private snapshotKey;
|
|
80
|
+
private parseSnapshot;
|
|
81
|
+
/**
|
|
82
|
+
* Read the snapshot this handle should start from: the primary, or the
|
|
83
|
+
* backup when the primary cannot be read (unchanged from the single-file
|
|
84
|
+
* runtime), or nothing at all.
|
|
85
|
+
*/
|
|
86
|
+
private readSnapshot;
|
|
36
87
|
private initializeState;
|
|
37
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Materialize the durable state from scratch: snapshot, then every complete
|
|
90
|
+
* commit in its journal, in order. A journal that disappears while it is
|
|
91
|
+
* being read has been superseded by a compaction, so the read starts over
|
|
92
|
+
* from the new snapshot. One that is missing for the current snapshot is
|
|
93
|
+
* corruption.
|
|
94
|
+
*/
|
|
95
|
+
private loadDurableState;
|
|
96
|
+
private adopt;
|
|
97
|
+
/** Apply one commit to memory. The only way any mutation reaches memory. */
|
|
98
|
+
private applyCommit;
|
|
99
|
+
/**
|
|
100
|
+
* Bring memory up to date with the durable files.
|
|
101
|
+
*
|
|
102
|
+
* While the snapshot is unchanged, only journal bytes after the last
|
|
103
|
+
* complete record already applied are read, so a read costs what was
|
|
104
|
+
* committed since the previous read — not the size of all history. Any
|
|
105
|
+
* change to the snapshot, or a journal that no longer continues what was
|
|
106
|
+
* applied, falls back to a complete load.
|
|
107
|
+
*/
|
|
108
|
+
private refresh;
|
|
109
|
+
/** Apply newly committed journal records. False when a full load is required. */
|
|
110
|
+
private tailJournal;
|
|
111
|
+
/** A commit body starting from the current sequence. */
|
|
112
|
+
private stage;
|
|
113
|
+
private stageRow;
|
|
114
|
+
private stageEvent;
|
|
115
|
+
/** Stage a row write together with the event that records it. */
|
|
116
|
+
private stagePut;
|
|
117
|
+
/**
|
|
118
|
+
* Make one commit durable, then visible. Caller holds the lock and has
|
|
119
|
+
* refreshed, so memory reflects every earlier commit.
|
|
120
|
+
*
|
|
121
|
+
* 1 body framed and written, without its terminator
|
|
122
|
+
* 2 fdatasync ← the record's bytes are durable
|
|
123
|
+
* 3 terminator written ← the commit boundary exists
|
|
124
|
+
* 4 fdatasync ← the boundary is durable
|
|
125
|
+
* 5 applied to memory, success returned
|
|
126
|
+
*
|
|
127
|
+
* A crash before 3 leaves an unterminated record that recovery discards; it
|
|
128
|
+
* was never acknowledged. Readers only accept terminated records, so no
|
|
129
|
+
* process can observe a commit whose bytes were not already durable. A
|
|
130
|
+
* failure at any step removes whatever was written, so a failed commit is
|
|
131
|
+
* not visible after it returns either.
|
|
132
|
+
*/
|
|
133
|
+
private persist;
|
|
134
|
+
private timedSync;
|
|
135
|
+
private compactionDue;
|
|
136
|
+
/**
|
|
137
|
+
* Compaction runs after the commit that made it due has been acknowledged,
|
|
138
|
+
* never as part of it, and under the same lock as every other writer.
|
|
139
|
+
*/
|
|
140
|
+
private scheduleCompaction;
|
|
141
|
+
/**
|
|
142
|
+
* Rewrite the current state as a new snapshot and start an empty journal.
|
|
143
|
+
* Caller holds the lock and has refreshed.
|
|
144
|
+
*
|
|
145
|
+
* 1 new empty journal G+1 created and synced
|
|
146
|
+
* 2 snapshot naming (G+1, commit C) written to a temporary file, synced
|
|
147
|
+
* 3 previous snapshot linked as the backup
|
|
148
|
+
* 4 snapshot renamed into place, directory synced ← compaction commits
|
|
149
|
+
* 5 journals other than G and G+1 removed
|
|
150
|
+
*
|
|
151
|
+
* A crash before 4 leaves the previous snapshot and journal authoritative;
|
|
152
|
+
* an orphaned journal G+1 is never read and is removed by the next
|
|
153
|
+
* compaction. After 4 the new snapshot is complete by itself.
|
|
154
|
+
*/
|
|
155
|
+
private compactLocked;
|
|
156
|
+
private syncDirectory;
|
|
157
|
+
/**
|
|
158
|
+
* Fold the journal into a new snapshot now. Logical state is unchanged;
|
|
159
|
+
* only its physical representation is. Normal commits never do this.
|
|
160
|
+
*/
|
|
161
|
+
compact(): PersistenceStatus;
|
|
162
|
+
/** How the durable state is currently represented on disk. */
|
|
163
|
+
persistence_status(): PersistenceStatus;
|
|
164
|
+
/**
|
|
165
|
+
* Persistence timings collected by this handle: mutation, serialization,
|
|
166
|
+
* write, fsync, commit, compaction and recovery. Empty unless profiling was
|
|
167
|
+
* enabled with the `profile` option or `FELTDB_PERSISTENCE_PROFILE=1`.
|
|
168
|
+
*/
|
|
169
|
+
persistence_profile(options?: {
|
|
170
|
+
reset?: boolean;
|
|
171
|
+
}): PersistenceProfile;
|
|
38
172
|
private isStalelock;
|
|
39
173
|
private cleanupStaleLock;
|
|
40
174
|
private acquireLockAsync;
|
|
@@ -42,19 +176,15 @@ export declare class FileJsDb implements JsDb {
|
|
|
42
176
|
private ownsLock;
|
|
43
177
|
private acquireLockSync;
|
|
44
178
|
private withMutationLock;
|
|
45
|
-
private refresh;
|
|
46
|
-
private saveState;
|
|
47
|
-
private event;
|
|
48
179
|
/**
|
|
49
180
|
* Commit several operations atomically and durably.
|
|
50
181
|
*
|
|
51
|
-
* The
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* leaves one of those two states on disk — never a mixture.
|
|
182
|
+
* The whole transaction is one journal record, and a record is either
|
|
183
|
+
* terminated — committed, every mutation in it — or discarded on recovery.
|
|
184
|
+
* A reader or a restart sees the whole transaction or none of it.
|
|
55
185
|
*
|
|
56
|
-
* Order matters here. The
|
|
57
|
-
*
|
|
186
|
+
* Order matters here. The commit is made durable *before* it is applied in
|
|
187
|
+
* memory, so a failed write cannot leave memory ahead of disk.
|
|
58
188
|
*/
|
|
59
189
|
commit_transaction(request: AtomicTransactionRequest): Promise<AtomicTransactionResult>;
|
|
60
190
|
insert(key: string, value: string): JsResult;
|
|
@@ -125,5 +255,4 @@ export declare class FileJsDb implements JsDb {
|
|
|
125
255
|
}>;
|
|
126
256
|
close(): void;
|
|
127
257
|
}
|
|
128
|
-
export {};
|
|
129
258
|
//# sourceMappingURL=file-db.d.ts.map
|
package/dist/file-db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-db.d.ts","sourceRoot":"","sources":["../src/file-db.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,KAAK,EACV,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,yBAAyB,EAG1B,MAAM,0BAA0B,CAAC;AAalC,OAAO,KAAK,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAO1F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"file-db.d.ts","sourceRoot":"","sources":["../src/file-db.ts"],"names":[],"mappings":"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"}
|