cojson 0.9.12 → 0.9.18
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/.turbo/turbo-build.log +3 -3
- package/CHANGELOG.md +12 -0
- package/dist/native/PeerState.js +5 -1
- package/dist/native/PeerState.js.map +1 -1
- package/dist/native/base64url.js +0 -6
- package/dist/native/base64url.js.map +1 -1
- package/dist/native/coValueCore.js +4 -10
- package/dist/native/coValueCore.js.map +1 -1
- package/dist/native/coValueState.js +8 -4
- package/dist/native/coValueState.js.map +1 -1
- package/dist/native/coValues/account.js +2 -1
- package/dist/native/coValues/account.js.map +1 -1
- package/dist/native/coValues/coList.js +0 -7
- package/dist/native/coValues/coList.js.map +1 -1
- package/dist/native/coValues/coStream.js +3 -8
- package/dist/native/coValues/coStream.js.map +1 -1
- package/dist/native/coValues/group.js +3 -2
- package/dist/native/coValues/group.js.map +1 -1
- package/dist/native/crypto/PureJSCrypto.js +2 -1
- package/dist/native/crypto/PureJSCrypto.js.map +1 -1
- package/dist/native/crypto/WasmCrypto.js +2 -2
- package/dist/native/crypto/WasmCrypto.js.map +1 -1
- package/dist/native/crypto/crypto.js +2 -4
- package/dist/native/crypto/crypto.js.map +1 -1
- package/dist/native/exports.js +2 -1
- package/dist/native/exports.js.map +1 -1
- package/dist/native/localNode.js +7 -6
- package/dist/native/localNode.js.map +1 -1
- package/dist/native/logger.js +58 -0
- package/dist/native/logger.js.map +1 -0
- package/dist/native/permissions.js +8 -8
- package/dist/native/permissions.js.map +1 -1
- package/dist/native/storage/FileSystem.js +0 -10
- package/dist/native/storage/FileSystem.js.map +1 -1
- package/dist/native/storage/index.js +12 -19
- package/dist/native/storage/index.js.map +1 -1
- package/dist/native/sync.js +42 -29
- package/dist/native/sync.js.map +1 -1
- package/dist/web/PeerState.js +5 -1
- package/dist/web/PeerState.js.map +1 -1
- package/dist/web/base64url.js +0 -6
- package/dist/web/base64url.js.map +1 -1
- package/dist/web/coValueCore.js +4 -10
- package/dist/web/coValueCore.js.map +1 -1
- package/dist/web/coValueState.js +8 -4
- package/dist/web/coValueState.js.map +1 -1
- package/dist/web/coValues/account.js +2 -1
- package/dist/web/coValues/account.js.map +1 -1
- package/dist/web/coValues/coList.js +0 -7
- package/dist/web/coValues/coList.js.map +1 -1
- package/dist/web/coValues/coStream.js +3 -8
- package/dist/web/coValues/coStream.js.map +1 -1
- package/dist/web/coValues/group.js +3 -2
- package/dist/web/coValues/group.js.map +1 -1
- package/dist/web/crypto/PureJSCrypto.js +2 -1
- package/dist/web/crypto/PureJSCrypto.js.map +1 -1
- package/dist/web/crypto/WasmCrypto.js +2 -2
- package/dist/web/crypto/WasmCrypto.js.map +1 -1
- package/dist/web/crypto/crypto.js +2 -4
- package/dist/web/crypto/crypto.js.map +1 -1
- package/dist/web/exports.js +2 -1
- package/dist/web/exports.js.map +1 -1
- package/dist/web/localNode.js +7 -6
- package/dist/web/localNode.js.map +1 -1
- package/dist/web/logger.js +58 -0
- package/dist/web/logger.js.map +1 -0
- package/dist/web/permissions.js +8 -8
- package/dist/web/permissions.js.map +1 -1
- package/dist/web/storage/FileSystem.js +0 -10
- package/dist/web/storage/FileSystem.js.map +1 -1
- package/dist/web/storage/index.js +12 -19
- package/dist/web/storage/index.js.map +1 -1
- package/dist/web/sync.js +42 -29
- package/dist/web/sync.js.map +1 -1
- package/package.json +1 -1
- package/src/PeerState.ts +5 -1
- package/src/base64url.ts +1 -6
- package/src/coValueCore.ts +4 -10
- package/src/coValueState.ts +8 -4
- package/src/coValues/account.ts +2 -1
- package/src/coValues/coList.ts +0 -7
- package/src/coValues/coStream.ts +3 -8
- package/src/coValues/group.ts +3 -2
- package/src/crypto/PureJSCrypto.ts +4 -1
- package/src/crypto/WasmCrypto.ts +4 -2
- package/src/crypto/crypto.ts +2 -4
- package/src/exports.ts +4 -1
- package/src/localNode.ts +9 -9
- package/src/logger.ts +80 -0
- package/src/permissions.ts +10 -16
- package/src/storage/FileSystem.ts +0 -12
- package/src/storage/index.ts +18 -33
- package/src/sync.ts +49 -39
- package/src/tests/PeerState.test.ts +0 -3
- package/src/tests/logger.test.ts +149 -0
package/src/exports.ts
CHANGED
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
} from "./ids.js";
|
|
39
39
|
import { Stringified, parseJSON, stableStringify } from "./jsonStringify.js";
|
|
40
40
|
import { LocalNode } from "./localNode.js";
|
|
41
|
-
import type { Role } from "./permissions.js";
|
|
41
|
+
import type { AccountRole, Role } from "./permissions.js";
|
|
42
42
|
import { Channel, connectedPeers } from "./streamUtils.js";
|
|
43
43
|
import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromSessionID.js";
|
|
44
44
|
import { expectGroup } from "./typeUtils/expectGroup.js";
|
|
@@ -74,6 +74,7 @@ import {
|
|
|
74
74
|
|
|
75
75
|
type Value = JsonValue | AnyRawCoValue;
|
|
76
76
|
|
|
77
|
+
import { logger } from "./logger.js";
|
|
77
78
|
import { getPriorityFromHeader } from "./priority.js";
|
|
78
79
|
import { FileSystem } from "./storage/FileSystem.js";
|
|
79
80
|
import { BlockFilename, LSMStorage, WalFilename } from "./storage/index.js";
|
|
@@ -141,6 +142,7 @@ export {
|
|
|
141
142
|
emptyKnownState,
|
|
142
143
|
RawCoPlainText,
|
|
143
144
|
stringifyOpID,
|
|
145
|
+
logger,
|
|
144
146
|
};
|
|
145
147
|
|
|
146
148
|
export type {
|
|
@@ -156,6 +158,7 @@ export type {
|
|
|
156
158
|
Stringified,
|
|
157
159
|
CoStreamItem,
|
|
158
160
|
OpID,
|
|
161
|
+
AccountRole,
|
|
159
162
|
};
|
|
160
163
|
|
|
161
164
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
package/src/localNode.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
} from "./coValues/group.js";
|
|
28
28
|
import { AgentSecret, CryptoProvider } from "./crypto/crypto.js";
|
|
29
29
|
import { AgentID, RawCoID, SessionID, isAgentID } from "./ids.js";
|
|
30
|
+
import { logger } from "./logger.js";
|
|
30
31
|
import { Peer, PeerID, SyncManager } from "./sync.js";
|
|
31
32
|
import { expectGroup } from "./typeUtils/expectGroup.js";
|
|
32
33
|
|
|
@@ -230,7 +231,7 @@ export class LocalNode {
|
|
|
230
231
|
|
|
231
232
|
return node;
|
|
232
233
|
} catch (e) {
|
|
233
|
-
|
|
234
|
+
logger.error("Error withLoadedAccount: " + (e as Error)?.message);
|
|
234
235
|
throw e;
|
|
235
236
|
}
|
|
236
237
|
}
|
|
@@ -269,7 +270,9 @@ export class LocalNode {
|
|
|
269
270
|
this.syncManager.getServerAndStoragePeers(skipLoadingFromPeer);
|
|
270
271
|
|
|
271
272
|
await entry.loadFromPeers(peers).catch((e) => {
|
|
272
|
-
|
|
273
|
+
logger.error("Error loading from peers: " + (e as Error)?.message, {
|
|
274
|
+
id,
|
|
275
|
+
});
|
|
273
276
|
});
|
|
274
277
|
}
|
|
275
278
|
|
|
@@ -311,8 +314,6 @@ export class LocalNode {
|
|
|
311
314
|
let stopped = false;
|
|
312
315
|
let unsubscribe!: () => void;
|
|
313
316
|
|
|
314
|
-
// console.log("Subscribing to " + id);
|
|
315
|
-
|
|
316
317
|
this.load(id)
|
|
317
318
|
.then((coValue) => {
|
|
318
319
|
if (stopped) {
|
|
@@ -325,11 +326,12 @@ export class LocalNode {
|
|
|
325
326
|
unsubscribe = coValue.subscribe(callback);
|
|
326
327
|
})
|
|
327
328
|
.catch((e) => {
|
|
328
|
-
|
|
329
|
+
logger.error(
|
|
330
|
+
"Error subscribing to " + id + ": " + (e as Error)?.message,
|
|
331
|
+
);
|
|
329
332
|
});
|
|
330
333
|
|
|
331
334
|
return () => {
|
|
332
|
-
console.log("Unsubscribing from " + id);
|
|
333
335
|
stopped = true;
|
|
334
336
|
unsubscribe?.();
|
|
335
337
|
};
|
|
@@ -390,9 +392,7 @@ export class LocalNode {
|
|
|
390
392
|
(existingRole === "reader" && inviteRole === "readerInvite") ||
|
|
391
393
|
(existingRole && inviteRole === "writeOnlyInvite")
|
|
392
394
|
) {
|
|
393
|
-
|
|
394
|
-
"Not accepting invite that would replace or downgrade role",
|
|
395
|
-
);
|
|
395
|
+
logger.debug("Not accepting invite that would replace or downgrade role");
|
|
396
396
|
return;
|
|
397
397
|
}
|
|
398
398
|
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { JsonValue } from "./jsonValue.js";
|
|
2
|
+
|
|
3
|
+
export enum LogLevel {
|
|
4
|
+
DEBUG = 0,
|
|
5
|
+
INFO = 1,
|
|
6
|
+
WARN = 2,
|
|
7
|
+
ERROR = 3,
|
|
8
|
+
NONE = 4,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface LogSystem {
|
|
12
|
+
debug(message: string, attributes?: Record<string, JsonValue>): void;
|
|
13
|
+
info(message: string, attributes?: Record<string, JsonValue>): void;
|
|
14
|
+
warn(message: string, attributes?: Record<string, JsonValue>): void;
|
|
15
|
+
error(message: string, attributes?: Record<string, JsonValue>): void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Default console-based logging system
|
|
19
|
+
export class ConsoleLogSystem implements LogSystem {
|
|
20
|
+
debug(message: string, attributes?: Record<string, JsonValue>) {
|
|
21
|
+
console.debug(message, attributes);
|
|
22
|
+
}
|
|
23
|
+
info(message: string, attributes?: Record<string, JsonValue>) {
|
|
24
|
+
console.info(message, attributes);
|
|
25
|
+
}
|
|
26
|
+
warn(message: string, attributes?: Record<string, JsonValue>) {
|
|
27
|
+
console.warn(message, attributes);
|
|
28
|
+
}
|
|
29
|
+
error(message: string, attributes?: Record<string, JsonValue>) {
|
|
30
|
+
console.error(message, attributes);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class Logger {
|
|
35
|
+
private level: LogLevel;
|
|
36
|
+
private logSystem: LogSystem;
|
|
37
|
+
|
|
38
|
+
constructor(
|
|
39
|
+
level: LogLevel = LogLevel.INFO,
|
|
40
|
+
logSystem: LogSystem = new ConsoleLogSystem(),
|
|
41
|
+
) {
|
|
42
|
+
this.level = level;
|
|
43
|
+
this.logSystem = logSystem;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
setLevel(level: LogLevel) {
|
|
47
|
+
this.level = level;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
setLogSystem(logSystem: LogSystem) {
|
|
51
|
+
this.logSystem = logSystem;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
debug(message: string, attributes?: Record<string, JsonValue>) {
|
|
55
|
+
if (this.level <= LogLevel.DEBUG) {
|
|
56
|
+
this.logSystem.debug(message, attributes);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
info(message: string, attributes?: Record<string, JsonValue>) {
|
|
61
|
+
if (this.level <= LogLevel.INFO) {
|
|
62
|
+
this.logSystem.info(message, attributes);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
warn(message: string, attributes?: Record<string, JsonValue>) {
|
|
67
|
+
if (this.level <= LogLevel.WARN) {
|
|
68
|
+
this.logSystem.warn(message, attributes);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
error(message: string, attributes?: Record<string, JsonValue>) {
|
|
73
|
+
if (this.level <= LogLevel.ERROR) {
|
|
74
|
+
this.logSystem.error(message, attributes);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Create default logger instance
|
|
80
|
+
export const logger = new Logger();
|
package/src/permissions.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "./ids.js";
|
|
15
15
|
import { parseJSON } from "./jsonStringify.js";
|
|
16
16
|
import { JsonValue } from "./jsonValue.js";
|
|
17
|
+
import { logger } from "./logger.js";
|
|
17
18
|
import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromSessionID.js";
|
|
18
19
|
import { expectGroup } from "./typeUtils/expectGroup.js";
|
|
19
20
|
|
|
@@ -41,12 +42,15 @@ export function disablePermissionErrors() {
|
|
|
41
42
|
logPermissionErrors = false;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
function logPermissionError(
|
|
45
|
+
function logPermissionError(
|
|
46
|
+
message: string,
|
|
47
|
+
attributes?: Record<string, JsonValue>,
|
|
48
|
+
) {
|
|
45
49
|
if (logPermissionErrors === false) {
|
|
46
50
|
return;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
logger.warn("Permission error: " + message, attributes);
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
export function determineValidTransactions(
|
|
@@ -204,7 +208,6 @@ function determineValidTransactionsForGroup(
|
|
|
204
208
|
const writeKeys = new Set<string>();
|
|
205
209
|
|
|
206
210
|
for (const { sessionID, txIndex, tx } of allTransactionsSorted) {
|
|
207
|
-
// console.log("before", { memberState, validTransactions });
|
|
208
211
|
const transactor = accountOrAgentIDfromSessionID(sessionID);
|
|
209
212
|
|
|
210
213
|
if (tx.privacy === "private") {
|
|
@@ -227,17 +230,10 @@ function determineValidTransactionsForGroup(
|
|
|
227
230
|
try {
|
|
228
231
|
changes = parseJSON(tx.changes);
|
|
229
232
|
} catch (e) {
|
|
230
|
-
logPermissionError(
|
|
231
|
-
coValue.id,
|
|
232
|
-
"Invalid JSON in transaction",
|
|
233
|
-
e,
|
|
233
|
+
logPermissionError("Invalid JSON in transaction", {
|
|
234
|
+
id: coValue.id,
|
|
234
235
|
tx,
|
|
235
|
-
|
|
236
|
-
k === "changes" || k === "encryptedChanges"
|
|
237
|
-
? v.slice(0, 20) + "..."
|
|
238
|
-
: v,
|
|
239
|
-
),
|
|
240
|
-
);
|
|
236
|
+
});
|
|
241
237
|
continue;
|
|
242
238
|
}
|
|
243
239
|
|
|
@@ -458,8 +454,6 @@ function determineValidTransactionsForGroup(
|
|
|
458
454
|
|
|
459
455
|
memberState[affectedMember] = change.value;
|
|
460
456
|
validTransactions.push({ txID: { sessionID, txIndex }, tx });
|
|
461
|
-
|
|
462
|
-
// console.log("after", { memberState, validTransactions });
|
|
463
457
|
}
|
|
464
458
|
|
|
465
459
|
return { validTransactions, memberState };
|
|
@@ -473,7 +467,7 @@ function agentInAccountOrMemberInGroup(
|
|
|
473
467
|
return groupAtTime.currentAgentID().match(
|
|
474
468
|
(agentID) => agentID,
|
|
475
469
|
(e) => {
|
|
476
|
-
|
|
470
|
+
logger.error(
|
|
477
471
|
"Error while determining current agent ID in valid transactions",
|
|
478
472
|
e,
|
|
479
473
|
);
|
|
@@ -87,26 +87,15 @@ export async function writeBlock<WH, RH, FS extends FileSystem<WH, RH>>(
|
|
|
87
87
|
const headerBytes = textEncoder.encode(JSON.stringify(blockHeader));
|
|
88
88
|
await fs.append(file, headerBytes);
|
|
89
89
|
|
|
90
|
-
// console.log(
|
|
91
|
-
// "full file",
|
|
92
|
-
// yield* $(
|
|
93
|
-
// fs.read(file as unknown as RH, 0, offset + headerBytes.length),
|
|
94
|
-
// ),
|
|
95
|
-
// );
|
|
96
|
-
|
|
97
90
|
const filename: BlockFilename = `L${level}-${(blockNumber + "").padStart(
|
|
98
91
|
3,
|
|
99
92
|
"0",
|
|
100
93
|
)}-${hash.digest().replace("hash_", "").slice(0, 15)}-H${
|
|
101
94
|
headerBytes.length
|
|
102
95
|
}.jsonl`;
|
|
103
|
-
// console.log("renaming to" + filename);
|
|
104
96
|
await fs.closeAndRename(file, filename);
|
|
105
97
|
|
|
106
98
|
return filename;
|
|
107
|
-
|
|
108
|
-
// console.log("Wrote block", filename, blockHeader);
|
|
109
|
-
// console.log("IDs in block", blockHeader.map(e => e.id));
|
|
110
99
|
}
|
|
111
100
|
|
|
112
101
|
export async function writeToWal<WH, RH, FS extends FileSystem<WH, RH>>(
|
|
@@ -120,6 +109,5 @@ export async function writeToWal<WH, RH, FS extends FileSystem<WH, RH>>(
|
|
|
120
109
|
...chunk,
|
|
121
110
|
};
|
|
122
111
|
const bytes = textEncoder.encode(JSON.stringify(walEntry) + "\n");
|
|
123
|
-
console.log("writing to WAL", handle, id, bytes.length);
|
|
124
112
|
return fs.append(handle, bytes);
|
|
125
113
|
}
|
package/src/storage/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { CoID, RawCoValue } from "../coValue.js";
|
|
|
2
2
|
import { CoValueHeader, Transaction } from "../coValueCore.js";
|
|
3
3
|
import { Signature } from "../crypto/crypto.js";
|
|
4
4
|
import { RawCoID } from "../ids.js";
|
|
5
|
+
import { logger } from "../logger.js";
|
|
5
6
|
import { connectedPeers } from "../streamUtils.js";
|
|
6
7
|
import {
|
|
7
8
|
CoValueKnownState,
|
|
@@ -68,7 +69,6 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
68
69
|
|
|
69
70
|
const processMessages = async () => {
|
|
70
71
|
for await (const msg of fromLocalNode) {
|
|
71
|
-
console.log("Storage msg start", nMsg);
|
|
72
72
|
try {
|
|
73
73
|
if (msg === "Disconnected" || msg === "PingTimeout") {
|
|
74
74
|
throw new Error("Unexpected Disconnected message");
|
|
@@ -83,32 +83,30 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
83
83
|
await this.sendNewContent(msg.id, msg, undefined);
|
|
84
84
|
}
|
|
85
85
|
} catch (e) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
),
|
|
86
|
+
logger.error(
|
|
87
|
+
`Error reading from localNode, handling msg\n\n${JSON.stringify(
|
|
88
|
+
msg,
|
|
89
|
+
(k, v) =>
|
|
90
|
+
k === "changes" || k === "encryptedChanges"
|
|
91
|
+
? v.slice(0, 20) + "..."
|
|
92
|
+
: v,
|
|
93
|
+
)}
|
|
94
|
+
Error: ${e instanceof Error ? e.message : "Unknown error"},
|
|
95
|
+
`,
|
|
97
96
|
);
|
|
98
97
|
}
|
|
99
|
-
console.log("Storage msg end", nMsg);
|
|
100
98
|
nMsg++;
|
|
101
99
|
}
|
|
102
100
|
};
|
|
103
101
|
|
|
104
102
|
processMessages().catch((e) =>
|
|
105
|
-
|
|
103
|
+
logger.error("Error in processMessages in storage", e),
|
|
106
104
|
);
|
|
107
105
|
|
|
108
106
|
setTimeout(
|
|
109
107
|
() =>
|
|
110
108
|
this.compact().catch((e) => {
|
|
111
|
-
|
|
109
|
+
logger.error("Error while compacting", e);
|
|
112
110
|
}),
|
|
113
111
|
20000,
|
|
114
112
|
);
|
|
@@ -134,7 +132,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
134
132
|
sessions: {},
|
|
135
133
|
asDependencyOf,
|
|
136
134
|
})
|
|
137
|
-
.catch((e) =>
|
|
135
|
+
.catch((e) => logger.error("Error while pushing known", e));
|
|
138
136
|
|
|
139
137
|
return;
|
|
140
138
|
}
|
|
@@ -190,13 +188,13 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
190
188
|
...ourKnown,
|
|
191
189
|
asDependencyOf,
|
|
192
190
|
})
|
|
193
|
-
.catch((e) =>
|
|
191
|
+
.catch((e) => logger.error("Error while pushing known", e));
|
|
194
192
|
|
|
195
193
|
for (const message of newContentMessages) {
|
|
196
194
|
if (Object.keys(message.new).length === 0) continue;
|
|
197
195
|
this.toLocalNode
|
|
198
196
|
.push(message)
|
|
199
|
-
.catch((e) =>
|
|
197
|
+
.catch((e) => logger.error("Error while pushing new content", e));
|
|
200
198
|
}
|
|
201
199
|
|
|
202
200
|
this.coValues[id] = coValue;
|
|
@@ -232,14 +230,13 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
232
230
|
|
|
233
231
|
if (!coValue) {
|
|
234
232
|
if (newContent.header) {
|
|
235
|
-
// console.log("Creating in WAL", newContent.id);
|
|
236
233
|
await this.withWAL((wal) =>
|
|
237
234
|
writeToWal(wal, this.fs, newContent.id, newContentAsChunk),
|
|
238
235
|
);
|
|
239
236
|
|
|
240
237
|
this.coValues[newContent.id] = newContentAsChunk;
|
|
241
238
|
} else {
|
|
242
|
-
|
|
239
|
+
logger.warn("Incontiguous incoming update for " + newContent.id);
|
|
243
240
|
return;
|
|
244
241
|
}
|
|
245
242
|
} else {
|
|
@@ -264,7 +261,6 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
264
261
|
),
|
|
265
262
|
);
|
|
266
263
|
} else {
|
|
267
|
-
// console.log("Appending to WAL", newContent.id);
|
|
268
264
|
await this.withWAL((wal) =>
|
|
269
265
|
writeToWal(wal, this.fs, newContent.id, newContentAsChunk),
|
|
270
266
|
);
|
|
@@ -301,8 +297,6 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
301
297
|
|
|
302
298
|
const { handle, size } = await this.getBlockHandle(blockFile, fs);
|
|
303
299
|
|
|
304
|
-
// console.log("Attempting to load", id, blockFile);
|
|
305
|
-
|
|
306
300
|
if (!cachedHeader) {
|
|
307
301
|
cachedHeader = {};
|
|
308
302
|
const header = await readHeader(blockFile, handle, size, fs);
|
|
@@ -317,8 +311,6 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
317
311
|
}
|
|
318
312
|
const headerEntry = cachedHeader[id];
|
|
319
313
|
|
|
320
|
-
// console.log("Header entry", id, headerEntry);
|
|
321
|
-
|
|
322
314
|
if (headerEntry) {
|
|
323
315
|
const nextChunk = await readChunk(handle, headerEntry, fs);
|
|
324
316
|
if (result) {
|
|
@@ -354,7 +346,6 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
354
346
|
|
|
355
347
|
const coValues = new Map<RawCoID, CoValueChunk>();
|
|
356
348
|
|
|
357
|
-
console.log("Compacting WAL files", walFiles);
|
|
358
349
|
if (walFiles.length === 0) return;
|
|
359
350
|
|
|
360
351
|
const oldWal = this.currentWal;
|
|
@@ -411,8 +402,6 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
411
402
|
return acc;
|
|
412
403
|
}, 0);
|
|
413
404
|
|
|
414
|
-
console.log([...coValues.keys()], fileNames, highestBlockNumber);
|
|
415
|
-
|
|
416
405
|
await writeBlock(coValues, MAX_N_LEVELS, highestBlockNumber + 1, this.fs);
|
|
417
406
|
|
|
418
407
|
for (const walFile of walFiles) {
|
|
@@ -438,15 +427,11 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
438
427
|
blockFilesByLevelInOrder[level]!.push(blockFile);
|
|
439
428
|
}
|
|
440
429
|
|
|
441
|
-
console.log(blockFilesByLevelInOrder);
|
|
442
|
-
|
|
443
430
|
for (let level = MAX_N_LEVELS; level > 0; level--) {
|
|
444
431
|
const nBlocksDesired = Math.pow(2, level);
|
|
445
432
|
const blocksInLevel = blockFilesByLevelInOrder[level];
|
|
446
433
|
|
|
447
434
|
if (blocksInLevel && blocksInLevel.length > nBlocksDesired) {
|
|
448
|
-
console.log("Compacting blocks in level", level, blocksInLevel);
|
|
449
|
-
|
|
450
435
|
const coValues = new Map<RawCoID, CoValueChunk>();
|
|
451
436
|
|
|
452
437
|
for (const blockFile of blocksInLevel) {
|
|
@@ -517,7 +502,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
517
502
|
setTimeout(
|
|
518
503
|
() =>
|
|
519
504
|
this.compact().catch((e) => {
|
|
520
|
-
|
|
505
|
+
logger.error("Error while compacting", e);
|
|
521
506
|
}),
|
|
522
507
|
5000,
|
|
523
508
|
);
|
package/src/sync.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { CoValueCore } from "./coValueCore.js";
|
|
|
6
6
|
import { Signature } from "./crypto/crypto.js";
|
|
7
7
|
import { RawCoID, SessionID } from "./ids.js";
|
|
8
8
|
import { LocalNode } from "./localNode.js";
|
|
9
|
+
import { logger } from "./logger.js";
|
|
9
10
|
import { CoValuePriority } from "./priority.js";
|
|
10
11
|
|
|
11
12
|
export type CoValueKnownState = {
|
|
@@ -22,6 +23,10 @@ export function emptyKnownState(id: RawCoID): CoValueKnownState {
|
|
|
22
23
|
};
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
function getErrorMessage(e: unknown) {
|
|
27
|
+
return e instanceof Error ? e.message : "Unknown error";
|
|
28
|
+
}
|
|
29
|
+
|
|
25
30
|
export type SyncMessage =
|
|
26
31
|
| LoadMessage
|
|
27
32
|
| KnownStateMessage
|
|
@@ -150,7 +155,7 @@ export class SyncManager {
|
|
|
150
155
|
|
|
151
156
|
async handleSyncMessage(msg: SyncMessage, peer: PeerState) {
|
|
152
157
|
if (peer.erroredCoValues.has(msg.id)) {
|
|
153
|
-
|
|
158
|
+
logger.warn(
|
|
154
159
|
`Skipping message ${msg.action} on errored coValue ${msg.id} from peer ${peer.id}`,
|
|
155
160
|
);
|
|
156
161
|
return;
|
|
@@ -182,7 +187,7 @@ export class SyncManager {
|
|
|
182
187
|
|
|
183
188
|
if (entry.state.type !== "available") {
|
|
184
189
|
entry.loadFromPeers([peer]).catch((e: unknown) => {
|
|
185
|
-
|
|
190
|
+
logger.error("Error sending load: " + getErrorMessage(e));
|
|
186
191
|
});
|
|
187
192
|
return;
|
|
188
193
|
}
|
|
@@ -199,7 +204,7 @@ export class SyncManager {
|
|
|
199
204
|
action: "load",
|
|
200
205
|
...coValue.knownState(),
|
|
201
206
|
}).catch((e: unknown) => {
|
|
202
|
-
|
|
207
|
+
logger.error("Error sending load: " + getErrorMessage(e));
|
|
203
208
|
});
|
|
204
209
|
}
|
|
205
210
|
}
|
|
@@ -229,7 +234,7 @@ export class SyncManager {
|
|
|
229
234
|
asDependencyOf,
|
|
230
235
|
...coValue.knownState(),
|
|
231
236
|
}).catch((e: unknown) => {
|
|
232
|
-
|
|
237
|
+
logger.error("Error sending known state: " + getErrorMessage(e));
|
|
233
238
|
});
|
|
234
239
|
|
|
235
240
|
peer.toldKnownState.add(id);
|
|
@@ -256,15 +261,8 @@ export class SyncManager {
|
|
|
256
261
|
const sendPieces = async () => {
|
|
257
262
|
let lastYield = performance.now();
|
|
258
263
|
for (const [_i, piece] of newContentPieces.entries()) {
|
|
259
|
-
// console.log(
|
|
260
|
-
// `${id} -> ${peer.id}: Sending content piece ${i + 1}/${
|
|
261
|
-
// newContentPieces.length
|
|
262
|
-
// } header: ${!!piece.header}`,
|
|
263
|
-
// // Object.values(piece.new).map((s) => s.newTransactions)
|
|
264
|
-
// );
|
|
265
|
-
|
|
266
264
|
this.trySendToPeer(peer, piece).catch((e: unknown) => {
|
|
267
|
-
|
|
265
|
+
logger.error("Error sending content piece: " + getErrorMessage(e));
|
|
268
266
|
});
|
|
269
267
|
|
|
270
268
|
if (performance.now() - lastYield > 10) {
|
|
@@ -277,7 +275,7 @@ export class SyncManager {
|
|
|
277
275
|
};
|
|
278
276
|
|
|
279
277
|
sendPieces().catch((e) => {
|
|
280
|
-
|
|
278
|
+
logger.error("Error sending new content piece, retrying", e);
|
|
281
279
|
peer.optimisticKnownStates.dispatch({
|
|
282
280
|
type: "SET",
|
|
283
281
|
id,
|
|
@@ -337,7 +335,10 @@ export class SyncManager {
|
|
|
337
335
|
return;
|
|
338
336
|
}
|
|
339
337
|
if (msg === "PingTimeout") {
|
|
340
|
-
|
|
338
|
+
logger.error("Ping timeout from peer", {
|
|
339
|
+
peerId: peer.id,
|
|
340
|
+
peerRole: peer.role,
|
|
341
|
+
});
|
|
341
342
|
return;
|
|
342
343
|
}
|
|
343
344
|
try {
|
|
@@ -360,13 +361,22 @@ export class SyncManager {
|
|
|
360
361
|
processMessages()
|
|
361
362
|
.then(() => {
|
|
362
363
|
if (peer.crashOnClose) {
|
|
363
|
-
|
|
364
|
+
logger.error("Unexepcted close from peer", {
|
|
365
|
+
peerId: peer.id,
|
|
366
|
+
peerRole: peer.role,
|
|
367
|
+
});
|
|
364
368
|
this.local.crashed = new Error("Unexpected close from peer");
|
|
365
369
|
throw new Error("Unexpected close from peer");
|
|
366
370
|
}
|
|
367
371
|
})
|
|
368
372
|
.catch((e) => {
|
|
369
|
-
|
|
373
|
+
logger.error(
|
|
374
|
+
"Error processing messages from peer: " + getErrorMessage(e),
|
|
375
|
+
{
|
|
376
|
+
peerId: peer.id,
|
|
377
|
+
peerRole: peer.role,
|
|
378
|
+
},
|
|
379
|
+
);
|
|
370
380
|
if (peer.crashOnClose) {
|
|
371
381
|
this.local.crashed = e;
|
|
372
382
|
throw new Error(e);
|
|
@@ -406,13 +416,13 @@ export class SyncManager {
|
|
|
406
416
|
// where we can get informations about the coValue
|
|
407
417
|
if (msg.header || Object.keys(msg.sessions).length > 0) {
|
|
408
418
|
entry.loadFromPeers([peer]).catch((e) => {
|
|
409
|
-
|
|
419
|
+
logger.error("Error loading coValue in handleLoad", e);
|
|
410
420
|
});
|
|
411
421
|
}
|
|
412
422
|
return;
|
|
413
423
|
} else {
|
|
414
424
|
this.local.loadCoValueCore(msg.id, peer.id).catch((e) => {
|
|
415
|
-
|
|
425
|
+
logger.error("Error loading coValue in handleLoad", e);
|
|
416
426
|
});
|
|
417
427
|
}
|
|
418
428
|
}
|
|
@@ -439,7 +449,7 @@ export class SyncManager {
|
|
|
439
449
|
header: false,
|
|
440
450
|
sessions: {},
|
|
441
451
|
}).catch((e) => {
|
|
442
|
-
|
|
452
|
+
logger.error("Error sending known state back", e);
|
|
443
453
|
});
|
|
444
454
|
|
|
445
455
|
return;
|
|
@@ -449,7 +459,7 @@ export class SyncManager {
|
|
|
449
459
|
await this.sendNewContentIncludingDependencies(msg.id, peer);
|
|
450
460
|
})
|
|
451
461
|
.catch((e) => {
|
|
452
|
-
|
|
462
|
+
logger.error("Error loading coValue in handleLoad loading state", e);
|
|
453
463
|
});
|
|
454
464
|
}
|
|
455
465
|
|
|
@@ -484,7 +494,7 @@ export class SyncManager {
|
|
|
484
494
|
peer.role === "storage" ? undefined : peer.id,
|
|
485
495
|
)
|
|
486
496
|
.catch((e) => {
|
|
487
|
-
|
|
497
|
+
logger.error(
|
|
488
498
|
`Error loading coValue ${msg.id} to create loading state, as dependency of ${msg.asDependencyOf}`,
|
|
489
499
|
e,
|
|
490
500
|
);
|
|
@@ -521,7 +531,7 @@ export class SyncManager {
|
|
|
521
531
|
|
|
522
532
|
if (entry.state.type !== "available") {
|
|
523
533
|
if (!msg.header) {
|
|
524
|
-
|
|
534
|
+
logger.error("Expected header to be sent in first message");
|
|
525
535
|
return;
|
|
526
536
|
}
|
|
527
537
|
|
|
@@ -584,7 +594,7 @@ export class SyncManager {
|
|
|
584
594
|
: t.changes.length,
|
|
585
595
|
)
|
|
586
596
|
.reduce((a, b) => a + b, 0);
|
|
587
|
-
|
|
597
|
+
logger.debug(
|
|
588
598
|
`Adding incoming transactions took ${(after - before).toFixed(
|
|
589
599
|
2,
|
|
590
600
|
)}ms for ${totalTxLength} bytes = bandwidth: ${(
|
|
@@ -602,17 +612,11 @@ export class SyncManager {
|
|
|
602
612
|
// );
|
|
603
613
|
|
|
604
614
|
if (result.isErr()) {
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
peer.
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
newTransactions.length + " new transactions",
|
|
611
|
-
"after: " + newContentForSession.after,
|
|
612
|
-
"our last known tx idx initially: " + ourKnownTxIdx,
|
|
613
|
-
"our last known tx idx now: " +
|
|
614
|
-
coValue.sessionLogs.get(sessionID)?.transactions.length,
|
|
615
|
-
);
|
|
615
|
+
logger.error("Failed to add transactions: " + result.error.type, {
|
|
616
|
+
peerId: peer.id,
|
|
617
|
+
peerRole: peer.role,
|
|
618
|
+
id: msg.id,
|
|
619
|
+
});
|
|
616
620
|
peer.erroredCoValues.set(msg.id, result.error);
|
|
617
621
|
continue;
|
|
618
622
|
}
|
|
@@ -633,7 +637,13 @@ export class SyncManager {
|
|
|
633
637
|
isCorrection: true,
|
|
634
638
|
...coValue.knownState(),
|
|
635
639
|
}).catch((e) => {
|
|
636
|
-
|
|
640
|
+
logger.error(
|
|
641
|
+
"Error sending known state correction: " + getErrorMessage(e),
|
|
642
|
+
{
|
|
643
|
+
peerId: peer.id,
|
|
644
|
+
peerRole: peer.role,
|
|
645
|
+
},
|
|
646
|
+
);
|
|
637
647
|
});
|
|
638
648
|
} else {
|
|
639
649
|
/**
|
|
@@ -647,7 +657,10 @@ export class SyncManager {
|
|
|
647
657
|
action: "known",
|
|
648
658
|
...coValue.knownState(),
|
|
649
659
|
}).catch((e: unknown) => {
|
|
650
|
-
|
|
660
|
+
logger.error("Error sending known state: " + getErrorMessage(e), {
|
|
661
|
+
peerId: peer.id,
|
|
662
|
+
peerRole: peer.role,
|
|
663
|
+
});
|
|
651
664
|
});
|
|
652
665
|
}
|
|
653
666
|
|
|
@@ -681,9 +694,6 @@ export class SyncManager {
|
|
|
681
694
|
const done = new Promise<void>((resolve) => {
|
|
682
695
|
queueMicrotask(async () => {
|
|
683
696
|
delete this.requestedSyncs[coValue.id];
|
|
684
|
-
// if (entry.nRequestsThisTick >= 2) {
|
|
685
|
-
// console.log("Syncing", coValue.id, "for", entry.nRequestsThisTick, "requests");
|
|
686
|
-
// }
|
|
687
697
|
await this.actuallySyncCoValue(coValue);
|
|
688
698
|
resolve();
|
|
689
699
|
});
|