@optimystic/db-p2p 0.28.0 → 0.29.0
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/src/cluster/block-transfer-service.d.ts +0 -10
- package/dist/src/cluster/block-transfer-service.d.ts.map +1 -1
- package/dist/src/cluster/block-transfer-service.js +4 -2
- package/dist/src/cluster/block-transfer-service.js.map +1 -1
- package/dist/src/cluster/cluster-policy.d.ts +101 -18
- package/dist/src/cluster/cluster-policy.d.ts.map +1 -1
- package/dist/src/cluster/cluster-policy.js +153 -30
- package/dist/src/cluster/cluster-policy.js.map +1 -1
- package/dist/src/cluster/quorum-restore.d.ts +4 -2
- package/dist/src/cluster/quorum-restore.d.ts.map +1 -1
- package/dist/src/cluster/quorum-restore.js +4 -2
- package/dist/src/cluster/quorum-restore.js.map +1 -1
- package/dist/src/cluster/service.d.ts +12 -9
- package/dist/src/cluster/service.d.ts.map +1 -1
- package/dist/src/cluster/service.js +6 -6
- package/dist/src/cluster/service.js.map +1 -1
- package/dist/src/dispute/service.d.ts +1 -4
- package/dist/src/dispute/service.d.ts.map +1 -1
- package/dist/src/dispute/service.js +2 -1
- package/dist/src/dispute/service.js.map +1 -1
- package/dist/src/libp2p-key-network.d.ts +8 -2
- package/dist/src/libp2p-key-network.d.ts.map +1 -1
- package/dist/src/libp2p-key-network.js +8 -2
- package/dist/src/libp2p-key-network.js.map +1 -1
- package/dist/src/libp2p-node-base.d.ts.map +1 -1
- package/dist/src/libp2p-node-base.js +22 -19
- package/dist/src/libp2p-node-base.js.map +1 -1
- package/dist/src/logger.d.ts +28 -1
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/logger.js +143 -1
- package/dist/src/logger.js.map +1 -1
- package/dist/src/network/network-manager-service.d.ts +1 -4
- package/dist/src/network/network-manager-service.d.ts.map +1 -1
- package/dist/src/network/network-manager-service.js +2 -1
- package/dist/src/network/network-manager-service.js.map +1 -1
- package/dist/src/repo/coordinator-repo.d.ts +183 -13
- package/dist/src/repo/coordinator-repo.d.ts.map +1 -1
- package/dist/src/repo/coordinator-repo.js +686 -107
- package/dist/src/repo/coordinator-repo.js.map +1 -1
- package/dist/src/repo/service.d.ts +9 -6
- package/dist/src/repo/service.d.ts.map +1 -1
- package/dist/src/repo/service.js +4 -5
- package/dist/src/repo/service.js.map +1 -1
- package/dist/src/sync/service.d.ts +1 -2
- package/dist/src/sync/service.d.ts.map +1 -1
- package/dist/src/sync/service.js +2 -1
- package/dist/src/sync/service.js.map +1 -1
- package/dist/src/testing/mesh-harness.d.ts +7 -1
- package/dist/src/testing/mesh-harness.d.ts.map +1 -1
- package/dist/src/testing/mesh-harness.js +2 -1
- package/dist/src/testing/mesh-harness.js.map +1 -1
- package/package.json +2 -2
- package/readme.md +19 -0
- package/src/cluster/block-transfer-service.ts +4 -8
- package/src/cluster/cluster-policy.ts +196 -36
- package/src/cluster/quorum-restore.ts +4 -2
- package/src/cluster/service.ts +14 -9
- package/src/dispute/service.ts +3 -3
- package/src/libp2p-key-network.ts +8 -2
- package/src/libp2p-node-base.ts +22 -19
- package/src/logger.ts +196 -2
- package/src/network/network-manager-service.ts +414 -414
- package/src/protocol-client.ts +196 -196
- package/src/repo/coordinator-repo.ts +833 -122
- package/src/repo/service.ts +12 -9
- package/src/sync/service.ts +3 -5
- package/src/testing/mesh-harness.ts +8 -1
package/src/logger.ts
CHANGED
|
@@ -1,7 +1,181 @@
|
|
|
1
|
+
import { base32 } from 'multiformats/bases/base32'
|
|
2
|
+
import { base58btc } from 'multiformats/bases/base58'
|
|
3
|
+
import { base64 } from 'multiformats/bases/base64'
|
|
1
4
|
import debug from 'debug'
|
|
5
|
+
import type { PeerId } from '@libp2p/interface'
|
|
6
|
+
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
7
|
+
import type { CID } from 'multiformats/cid'
|
|
2
8
|
|
|
3
9
|
const BASE_NAMESPACE = 'optimystic:db-p2p'
|
|
4
10
|
|
|
11
|
+
/*
|
|
12
|
+
* Format specifiers, ported from `@libp2p/logger`'s `src/index.ts` (MIT, same license as this
|
|
13
|
+
* repo). Call sites in this package log lines like `'error handling X from %p - %e'`; those used
|
|
14
|
+
* to reach libp2p's own logger, which registers these. Without the port they would print the
|
|
15
|
+
* literal text `%p` / `%e`.
|
|
16
|
+
*
|
|
17
|
+
* NOTE: these are registered on the `debug` module instance THIS file imports. libp2p's own
|
|
18
|
+
* loggers use `weald` (via @libp2p/logger) and carry their own copy — the two registries are
|
|
19
|
+
* independent, and enabling one from test code does not enable the other.
|
|
20
|
+
*
|
|
21
|
+
* NOTE: `debug.formatters` is process-wide, and the other six packages' `createLogger` factories
|
|
22
|
+
* import the same `debug` module — so importing this file makes `%p`/`%e`/… work from their
|
|
23
|
+
* loggers too. Harmless today (no other package registers any specifier, and none of these letters
|
|
24
|
+
* is a `util.format` specifier except `%c`, whose Node meaning is a no-op that swallows its
|
|
25
|
+
* argument). If a second package ever registers one of these letters, last import wins silently;
|
|
26
|
+
* move the registry somewhere both can share rather than racing on it.
|
|
27
|
+
*
|
|
28
|
+
* NOTE: only `%e` is guaranteed not to throw — its call sites take a `catch`-bound `unknown`. The
|
|
29
|
+
* other six call `.toString()` / an encoder on whatever they are handed, so a caller that passes
|
|
30
|
+
* the wrong type turns a log line into an exception. That matches upstream; tighten them if a
|
|
31
|
+
* call site ever formats a value it did not construct.
|
|
32
|
+
*
|
|
33
|
+
* `%k` (`interface-datastore`'s `Key`) is deliberately NOT ported: `interface-datastore` is not a
|
|
34
|
+
* declared dependency of this package and no call site formats one. Add it if that changes.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
// Add a formatter for converting to a base58 string
|
|
38
|
+
debug.formatters['b'] = (v?: Uint8Array): string => {
|
|
39
|
+
return v == null ? 'undefined' : base58btc.baseEncode(v)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Add a formatter for converting to a base32 string
|
|
43
|
+
debug.formatters['t'] = (v?: Uint8Array): string => {
|
|
44
|
+
return v == null ? 'undefined' : base32.baseEncode(v)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Add a formatter for converting to a base64 string
|
|
48
|
+
debug.formatters['m'] = (v?: Uint8Array): string => {
|
|
49
|
+
return v == null ? 'undefined' : base64.baseEncode(v)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Add a formatter for stringifying peer ids
|
|
53
|
+
debug.formatters['p'] = (v?: PeerId): string => {
|
|
54
|
+
return v == null ? 'undefined' : v.toString()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Add a formatter for stringifying CIDs
|
|
58
|
+
debug.formatters['c'] = (v?: CID): string => {
|
|
59
|
+
return v == null ? 'undefined' : v.toString()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Add a formatter for stringifying Multiaddrs
|
|
63
|
+
debug.formatters['a'] = (v?: Multiaddr): string => {
|
|
64
|
+
return v == null ? 'undefined' : v.toString()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function notEmpty(str?: string): string | undefined {
|
|
68
|
+
if (str == null) {
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
str = str.trim()
|
|
73
|
+
|
|
74
|
+
if (str.length === 0) {
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return str
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function formatError(v: Error, indent = ''): string {
|
|
82
|
+
const message = notEmpty(v.message)
|
|
83
|
+
const stack = notEmpty(v.stack)
|
|
84
|
+
|
|
85
|
+
// some browser errors (mostly from Firefox) have no message or no stack,
|
|
86
|
+
// sometimes both, sometimes neither. Sometimes the message is in the stack,
|
|
87
|
+
// sometimes it isn't so try to do *something* useful
|
|
88
|
+
if (message != null && stack != null) {
|
|
89
|
+
if (stack.includes(message)) {
|
|
90
|
+
return `${stack.split('\n').join(`\n${indent}`)}`
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return `${message}\n${indent}${stack.split('\n').join(`\n${indent}`)}`
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (stack != null) {
|
|
97
|
+
return `${stack.split('\n').join(`\n${indent}`)}`
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (message != null) {
|
|
101
|
+
return `${message}`
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return `${v.toString()}`
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function isAggregateError(err?: any): err is AggregateError {
|
|
108
|
+
return err instanceof AggregateError || (err?.name === 'AggregateError' && Array.isArray(err.errors))
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function printError(err: Error, indent = ''): string {
|
|
112
|
+
if (isAggregateError(err)) {
|
|
113
|
+
let output = formatError(err, indent)
|
|
114
|
+
|
|
115
|
+
if (err.errors.length > 0) {
|
|
116
|
+
indent = `${indent} `
|
|
117
|
+
|
|
118
|
+
output += `\n${indent}${err.errors
|
|
119
|
+
.map(err => `${printError(err, `${indent}`)}`)
|
|
120
|
+
.join(`\n${indent}`)
|
|
121
|
+
}`
|
|
122
|
+
} else {
|
|
123
|
+
output += `\n${indent}[Error list was empty]`
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return output.trim()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return formatError(err, indent)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Add a formatter for stringifying Errors.
|
|
133
|
+
//
|
|
134
|
+
// A call site can hand `%e` anything — `catch (err)` binds `unknown`, and this package's `%e` sites
|
|
135
|
+
// are all in catch blocks. This must never throw: a logger that throws turns a caught error into an
|
|
136
|
+
// uncaught one at exactly the site that was trying to report it.
|
|
137
|
+
//
|
|
138
|
+
// The try/catch is a deliberate deviation from the upstream `@libp2p/logger` port. `formatError`'s
|
|
139
|
+
// last resort is `${v.toString()}`, which raises for the two values that have no usable primitive
|
|
140
|
+
// conversion — a null-prototype object (`throw Object.create(null)`) and a symbol. Upstream has the
|
|
141
|
+
// same hole; here the stated contract is "never throw", so the fallback is explicit.
|
|
142
|
+
debug.formatters['e'] = (v?: Error): string => {
|
|
143
|
+
if (v == null) {
|
|
144
|
+
return 'undefined'
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
return printError(v)
|
|
149
|
+
} catch {
|
|
150
|
+
return '[unformattable error]'
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* A `debug` channel plus the severity sub-channels libp2p's own `Logger` exposes, so a call site
|
|
156
|
+
* can be moved between the two factories without changing what it calls.
|
|
157
|
+
*
|
|
158
|
+
* `error` and `trace` are ordinary child namespaces (`<namespace>:error`), so a wildcard filter
|
|
159
|
+
* the operator already uses — `optimystic:db-p2p:*` — keeps matching them. An EXACT-match filter
|
|
160
|
+
* (`DEBUG=optimystic:db-p2p:repo-service`) does not; that is the same caveat the peer-id suffix
|
|
161
|
+
* already carries, and `docs/debugging.md` already documents it.
|
|
162
|
+
*
|
|
163
|
+
* Unlike libp2p we do NOT conditionally stub out `trace`: libp2p builds a no-op unless a `:trace`
|
|
164
|
+
* namespace is explicitly enabled, but a disabled `debug` channel is already near-free, and the
|
|
165
|
+
* conditional version reads its enablement once at construction — wrong for anything built before
|
|
166
|
+
* `DEBUG` is set. `newScope` is deliberately omitted; `createLogger('parent:child')` says the same
|
|
167
|
+
* thing and nothing calls it.
|
|
168
|
+
*
|
|
169
|
+
* NOTE: because `trace` is a real channel, the wildcard `optimystic:db-p2p:*` that
|
|
170
|
+
* `docs/debugging.md` tells operators to set will also show trace lines. Nothing calls `.trace`
|
|
171
|
+
* yet, so that is currently free; if trace logging ever becomes voluminous, give the docs a
|
|
172
|
+
* narrower default filter rather than stubbing the channel back out.
|
|
173
|
+
*/
|
|
174
|
+
export interface Logger extends debug.Debugger {
|
|
175
|
+
error: debug.Debugger
|
|
176
|
+
trace: debug.Debugger
|
|
177
|
+
}
|
|
178
|
+
|
|
5
179
|
/**
|
|
6
180
|
* Build a `debug` logger under `optimystic:db-p2p:<subNamespace>`, optionally suffixed with the
|
|
7
181
|
* owning node's peer id (`:<first 12 chars>`) so lines from several nodes sharing one process —
|
|
@@ -17,10 +191,30 @@ const BASE_NAMESPACE = 'optimystic:db-p2p'
|
|
|
17
191
|
* the three `peer-address-book` sinks); the package's other ~30 `createLogger` call sites
|
|
18
192
|
* still log under a flat namespace. Thread a peer id through any of them if a future diagnosis
|
|
19
193
|
* needs per-node attribution from that subsystem — the mechanism is already here.
|
|
194
|
+
*
|
|
195
|
+
* The peer-id suffix goes BEFORE `:error` / `:trace` — those are children of the concrete channel,
|
|
196
|
+
* so a two-node process gets `…:x:12D3KooWAb:error`, not `…:x:error:12D3KooWAb`.
|
|
197
|
+
*/
|
|
198
|
+
/*
|
|
199
|
+
* NOTE: `packages/db-p2p/test/logger.spec.ts` asserts that every namespace this package emits has
|
|
200
|
+
* a row in the db-p2p table of `docs/debugging.md`, and it finds them by scanning `src/` for
|
|
201
|
+
* `createLogger("…")` / `createLogger('…')` — STRING LITERALS ONLY. A namespace built from a
|
|
202
|
+
* variable (`createLogger(someName)`) is invisible to that guard, so it would go undocumented
|
|
203
|
+
* silently. No such call site exists today; the two that pass a fallback
|
|
204
|
+
* (`createLogger(init.logPrefix ?? 'repo-service')`) still carry the literal, which is what the
|
|
205
|
+
* scan picks up. If you ever need a fully computed namespace, document it by hand and say so here.
|
|
20
206
|
*/
|
|
21
|
-
export function createLogger(subNamespace: string, peerId?: string):
|
|
207
|
+
export function createLogger(subNamespace: string, peerId?: string): Logger {
|
|
22
208
|
const suffix = peerId ? `:${peerId.substring(0, 12)}` : ''
|
|
23
|
-
|
|
209
|
+
const namespace = `${BASE_NAMESPACE}:${subNamespace}${suffix}`
|
|
210
|
+
// NOTE: `Object.assign` onto the Debugger, never a spread into a fresh object. `debug` defines
|
|
211
|
+
// `enabled` as an accessor property on the function object it returns; assigning onto that
|
|
212
|
+
// object preserves the accessor, whereas spreading would flatten it to a construction-time
|
|
213
|
+
// snapshot boolean and silently break any `if (log.enabled)` guard.
|
|
214
|
+
return Object.assign(debug(namespace), {
|
|
215
|
+
error: debug(`${namespace}:error`),
|
|
216
|
+
trace: debug(`${namespace}:trace`)
|
|
217
|
+
})
|
|
24
218
|
}
|
|
25
219
|
|
|
26
220
|
export const verbose = typeof process !== 'undefined'
|