web-dc-api 0.1.5 → 0.1.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.
Files changed (148) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/dc.min.js +1 -1
  3. package/dist/esm/index.js +1 -1
  4. package/dist/index.d.ts +934 -878
  5. package/package.json +4 -8
  6. package/dist/cjs/helia-core-B1Xqha7a.js +0 -1
  7. package/dist/cjs/helia-core-D8Uv1KjQ.js +0 -1
  8. package/dist/cjs/polkadot-api-7PhQf3ws.js +0 -1
  9. package/dist/cjs/polkadot-api-CtrJVWuZ.js +0 -1
  10. package/dist/esm/chunks/helia-core-BxMqyK2Y.js +0 -1
  11. package/dist/esm/chunks/helia-core-DMXRpcO-.js +0 -1
  12. package/dist/esm/chunks/polkadot-api-5Y9Bw8VT.js +0 -1
  13. package/dist/esm/chunks/polkadot-api-D69Ioun_.js +0 -1
  14. package/lib/common/blowfish/block.ts +0 -259
  15. package/lib/common/blowfish/cipher.ts +0 -144
  16. package/lib/common/blowfish/const.ts +0 -195
  17. package/lib/common/chain.ts +0 -469
  18. package/lib/common/commonclient.ts +0 -202
  19. package/lib/common/constants.ts +0 -55
  20. package/lib/common/dc-key/ed25519.ts +0 -343
  21. package/lib/common/dc-key/keyManager.ts +0 -424
  22. package/lib/common/dcapi.ts +0 -98
  23. package/lib/common/dcutil.ts +0 -627
  24. package/lib/common/define.ts +0 -70
  25. package/lib/common/error.ts +0 -67
  26. package/lib/common/grpc-dc.ts +0 -104
  27. package/lib/common/module-system.ts +0 -184
  28. package/lib/common/service-worker.ts +0 -234
  29. package/lib/common/types/types.ts +0 -344
  30. package/lib/dc.ts +0 -701
  31. package/lib/implements/account/client.ts +0 -185
  32. package/lib/implements/account/manager.ts +0 -683
  33. package/lib/implements/aiproxy/client.ts +0 -357
  34. package/lib/implements/aiproxy/manager.ts +0 -670
  35. package/lib/implements/cache/client.ts +0 -105
  36. package/lib/implements/cache/manager.ts +0 -127
  37. package/lib/implements/comment/client.ts +0 -982
  38. package/lib/implements/comment/manager.ts +0 -1151
  39. package/lib/implements/dc/client.ts +0 -51
  40. package/lib/implements/dc/manager.ts +0 -33
  41. package/lib/implements/file/client.ts +0 -253
  42. package/lib/implements/file/file-cache-manager.ts +0 -142
  43. package/lib/implements/file/manager.ts +0 -1240
  44. package/lib/implements/file/seekableFileStream.ts +0 -344
  45. package/lib/implements/file/streamwriter.ts +0 -322
  46. package/lib/implements/keyvalue/client.ts +0 -376
  47. package/lib/implements/keyvalue/manager.ts +0 -759
  48. package/lib/implements/message/client.ts +0 -250
  49. package/lib/implements/message/manager.ts +0 -215
  50. package/lib/implements/threaddb/cbor/coding.ts +0 -62
  51. package/lib/implements/threaddb/cbor/event.ts +0 -336
  52. package/lib/implements/threaddb/cbor/node.ts +0 -542
  53. package/lib/implements/threaddb/cbor/record.ts +0 -398
  54. package/lib/implements/threaddb/common/AsyncMutex.ts +0 -24
  55. package/lib/implements/threaddb/common/addrinfo.ts +0 -135
  56. package/lib/implements/threaddb/common/dispatcher.ts +0 -81
  57. package/lib/implements/threaddb/common/idbstore-adapter.ts +0 -260
  58. package/lib/implements/threaddb/common/json-patcher.ts +0 -204
  59. package/lib/implements/threaddb/common/key.ts +0 -290
  60. package/lib/implements/threaddb/common/level-adapter.ts +0 -235
  61. package/lib/implements/threaddb/common/lineReader.ts +0 -79
  62. package/lib/implements/threaddb/common/logstore.ts +0 -215
  63. package/lib/implements/threaddb/common/transformed-datastore.ts +0 -308
  64. package/lib/implements/threaddb/core/app.ts +0 -206
  65. package/lib/implements/threaddb/core/core.ts +0 -230
  66. package/lib/implements/threaddb/core/db.ts +0 -249
  67. package/lib/implements/threaddb/core/event.ts +0 -54
  68. package/lib/implements/threaddb/core/head.ts +0 -89
  69. package/lib/implements/threaddb/core/identity.ts +0 -171
  70. package/lib/implements/threaddb/core/logstore.ts +0 -137
  71. package/lib/implements/threaddb/core/options.ts +0 -14
  72. package/lib/implements/threaddb/core/record.ts +0 -54
  73. package/lib/implements/threaddb/db/collection.ts +0 -1910
  74. package/lib/implements/threaddb/db/db.ts +0 -698
  75. package/lib/implements/threaddb/db/json2Query.ts +0 -192
  76. package/lib/implements/threaddb/db/query.ts +0 -524
  77. package/lib/implements/threaddb/dbclient.ts +0 -543
  78. package/lib/implements/threaddb/dbmanager.ts +0 -1906
  79. package/lib/implements/threaddb/lsstoreds/addr_book.ts +0 -549
  80. package/lib/implements/threaddb/lsstoreds/cache.ts +0 -36
  81. package/lib/implements/threaddb/lsstoreds/cyclic_batch.ts +0 -87
  82. package/lib/implements/threaddb/lsstoreds/global.ts +0 -151
  83. package/lib/implements/threaddb/lsstoreds/headbook.ts +0 -373
  84. package/lib/implements/threaddb/lsstoreds/keybook.ts +0 -297
  85. package/lib/implements/threaddb/lsstoreds/logstore.ts +0 -29
  86. package/lib/implements/threaddb/lsstoreds/metadata.ts +0 -223
  87. package/lib/implements/threaddb/net/define.ts +0 -149
  88. package/lib/implements/threaddb/net/grpcClient.ts +0 -589
  89. package/lib/implements/threaddb/net/grpcserver.ts +0 -146
  90. package/lib/implements/threaddb/net/net.ts +0 -2047
  91. package/lib/implements/threaddb/pb/lstore.proto +0 -38
  92. package/lib/implements/threaddb/pb/lstore.ts +0 -393
  93. package/lib/implements/threaddb/pb/lstore_pb.d.ts +0 -433
  94. package/lib/implements/threaddb/pb/lstore_pb.js +0 -1085
  95. package/lib/implements/threaddb/pb/net.proto +0 -194
  96. package/lib/implements/threaddb/pb/net_pb.d.ts +0 -2349
  97. package/lib/implements/threaddb/pb/net_pb.js +0 -5525
  98. package/lib/implements/threaddb/pb/proto-custom-types.ts +0 -212
  99. package/lib/implements/util/client.ts +0 -72
  100. package/lib/implements/util/manager.ts +0 -146
  101. package/lib/implements/wallet/manager.ts +0 -671
  102. package/lib/index.ts +0 -57
  103. package/lib/interfaces/DCContext.ts +0 -51
  104. package/lib/interfaces/aiproxy-interface.ts +0 -145
  105. package/lib/interfaces/auth-interface.ts +0 -118
  106. package/lib/interfaces/cache-interface.ts +0 -22
  107. package/lib/interfaces/client-interface.ts +0 -11
  108. package/lib/interfaces/comment-interface.ts +0 -167
  109. package/lib/interfaces/components/news-component.ts +0 -0
  110. package/lib/interfaces/database-interface.ts +0 -169
  111. package/lib/interfaces/file-interface.ts +0 -120
  112. package/lib/interfaces/index.ts +0 -10
  113. package/lib/interfaces/keyvalue-interface.ts +0 -156
  114. package/lib/interfaces/message-interface.ts +0 -22
  115. package/lib/interfaces/util-interface.ts +0 -31
  116. package/lib/modules/aiproxy-module.ts +0 -246
  117. package/lib/modules/auth-module.ts +0 -753
  118. package/lib/modules/cache-module.ts +0 -99
  119. package/lib/modules/client-module.ts +0 -71
  120. package/lib/modules/comment-module.ts +0 -429
  121. package/lib/modules/components/news-components.ts +0 -390
  122. package/lib/modules/database-module.ts +0 -598
  123. package/lib/modules/file-module.ts +0 -291
  124. package/lib/modules/index.ts +0 -13
  125. package/lib/modules/keyvalue-module.ts +0 -379
  126. package/lib/modules/message-module.ts +0 -107
  127. package/lib/modules/util-module.ts +0 -148
  128. package/lib/polyfills/process-env-browser.ts +0 -1
  129. package/lib/proto/datasource.ts +0 -93
  130. package/lib/proto/dcnet.proto +0 -1601
  131. package/lib/proto/dcnet_proto.d.ts +0 -22857
  132. package/lib/proto/dcnet_proto.js +0 -55204
  133. package/lib/proto/dcnet_proto_sparse.js +0 -55166
  134. package/lib/proto/oidfetch.proto +0 -25
  135. package/lib/proto/oidfetch_proto.d.ts +0 -585
  136. package/lib/proto/oidfetch_proto.js +0 -1247
  137. package/lib/serverless/babel-browser.ts +0 -39
  138. package/lib/serverless/base_entity.ts +0 -78
  139. package/lib/serverless/base_repository.ts +0 -414
  140. package/lib/serverless/browser_schema_extractor.ts +0 -283
  141. package/lib/serverless/decorator_factory.ts +0 -322
  142. package/lib/util/BrowserLineReader.ts +0 -73
  143. package/lib/util/base64.ts +0 -105
  144. package/lib/util/bcrypt.ts +0 -206
  145. package/lib/util/curve25519Encryption.ts +0 -418
  146. package/lib/util/dccrypt.ts +0 -73
  147. package/lib/util/logger.ts +0 -104
  148. package/lib/util/utils.ts +0 -289
@@ -1,549 +0,0 @@
1
- import { Datastore, Key, Pair } from 'interface-datastore'
2
- import * as bytes from 'uint8arrays'
3
- import { peerIdFromString } from '@libp2p/peer-id'
4
- import type { PeerId,PrivateKey,PublicKey } from "@libp2p/interface";
5
- import { Multiaddr, multiaddr, isMultiaddr } from '@multiformats/multiaddr'
6
- import { AddrBook,DumpAddrBook} from '../core/logstore' // 核心接口定义
7
- import * as pb from '../pb/lstore'
8
- import {uniqueLogIds,uniqueThreadIds,DSOptions,AllowEmptyRestore,dsThreadKey} from './global'
9
- import {LRUCache} from 'lru-cache'
10
- import { ThreadID } from '@textile/threads-id';
11
- import {DefaultOpts} from './global';
12
- import { TxnDatastoreExtended, Transaction } from '../core/db';
13
- import * as buffer from "buffer/";
14
- import { bases } from 'multiformats/basics';
15
- const { Buffer } = buffer;
16
-
17
- const ADDR_FNV_OFFSET_BASIS = 0xcbf29ce484222325n;
18
- const ADDR_FNV_PRIME = 0x100000001b3n;
19
- const ADDR_MOD64 = 2n ** 64n;
20
-
21
-
22
- // 缓存键类型
23
- type CacheKey = {
24
- threadID: ThreadID
25
- peerID: string
26
- }
27
-
28
- // TTL写入模式
29
- enum TTLWriteMode {
30
- Override,
31
- Extend
32
- }
33
-
34
- // 地址记录增强类型
35
- interface AddrsRecord {
36
- lock: AsyncMutex
37
- data: pb.AddrBookRecord
38
- dirty: boolean
39
- }
40
-
41
-
42
- // NewAddrBook initializes a new datastore-backed address book. It serves as a drop-in replacement for pstoremem
43
- // (memory-backed peerstore), and works with any datastore implementing the ds.Batching interface.
44
- //
45
- // Threads and logs addresses are serialized into protobuf, storing one datastore entry per (thread, log), along with metadata
46
- // to control address expiration. To alleviate disk access and serde overhead, we internally use a read/write-through
47
- // ARC cache, the size of which is adjustable via Options.CacheSize.
48
- export async function newAddrBook(ds: Datastore, opts?: DSOptions): Promise<DsAddrBook> {
49
- if (!opts) {
50
- opts = DefaultOpts();
51
- }
52
- const ab = new DsAddrBook(ds, opts);
53
- if (opts.CacheSize > 0) {
54
- ab.cache = new LRUCache({ max: opts.CacheSize });
55
- } else {
56
- ab.cache = new LRUCache({ max: 0 });
57
- }
58
- return ab;
59
- }
60
-
61
-
62
- export class DsAddrBook implements AddrBook {
63
- private static readonly logBookBase = new Key('/thread/addrs')
64
- private static readonly logBookEdge = new Key('/thread/addrs:edge')
65
-
66
-
67
- private opts: DSOptions
68
- private ds: TxnDatastoreExtended
69
- cache: LRUCache<CacheKey, AddrsRecord>
70
-
71
- constructor( ds: Datastore, opts: DSOptions) {
72
- this.opts = opts
73
- this.ds = ds as TxnDatastoreExtended
74
- this.cache = new LRUCache({ max: opts.CacheSize || 0 })
75
- }
76
-
77
-
78
- async addAddr(t: ThreadID, p: PeerId, addrs: Multiaddr, ttl: number): Promise<void> {
79
-
80
- if (ttl <= 0) return
81
- const cleaned = this.cleanAddrs([addrs])
82
- await this.setAddrs(t, p, cleaned, ttl)
83
- }
84
-
85
- async addAddrs(t: ThreadID, p: PeerId, addrs: Multiaddr[], ttl: number): Promise<void> {
86
- if (ttl <= 0) return
87
- const cleaned = this.cleanAddrs(addrs)
88
- await this.setAddrs(t, p, cleaned, ttl)
89
- }
90
-
91
- cleanAddrs(addrs: (string | Multiaddr | null | undefined)[]): Multiaddr[] {
92
- return addrs.reduce<Multiaddr[]>((acc, item) => {
93
- try {
94
- if (!item) return acc
95
- const addr = typeof item === 'string'
96
- ? multiaddr(item)
97
- : (isMultiaddr(item) ? item : null)
98
- return addr ? [...acc, addr] : acc
99
- } catch {
100
- return acc
101
- }
102
- }, [])
103
- }
104
-
105
-
106
- async setAddr(t: ThreadID, p: PeerId, addr: Multiaddr, ttl: number): Promise<void> {
107
- if (ttl <= 0) return
108
- const cleaned = this.cleanAddrs([addr])
109
- await this.setAddrs(t, p, cleaned, ttl)
110
- }
111
-
112
- async setAddrs(t: ThreadID, logId: PeerId, addrs: Multiaddr[], ttl: number): Promise<void> {
113
- let release = () => {}
114
- try {
115
- const record = await this.loadRecord(t, logId.toString(), true,false)
116
- release = await record.lock.acquire()
117
- const newExp = Date.now() + ttl
118
- const existed = new Array(addrs.length).fill(false)
119
-
120
- // 更新现有地址
121
- outer: for (const [i, addr] of addrs.entries()) {
122
- for (const entry of record.data.addrs) {
123
- if (bytes.compare(addr.bytes, entry.addr) === 0) {
124
- existed[i] = true
125
- entry.ttl = ttl
126
- entry.expiry = newExp
127
- continue outer
128
- }
129
- }
130
- }
131
-
132
- // 添加新地址
133
- const added = addrs
134
- .filter((_, i) => !existed[i])
135
- .map(addr => new pb.AddrBookRecord.AddrEntry({
136
- addr: addr.bytes,
137
- expiry: newExp,
138
- ttl
139
- }))
140
-
141
- record.data.addrs.push(...added)
142
- record.dirty = true
143
- await this.cleanRecord(record)
144
- await this.flushRecord(record)
145
- await this.invalidateEdge(t)
146
- } finally {
147
- release()
148
- }
149
- }
150
-
151
- async updateAddrs(t: ThreadID, logId: PeerId, oldTTL: number, newTTL: number): Promise<void> {
152
- let release = () => {}
153
- try {
154
- const record = await this.loadRecord(t, logId.toString(), true,false)
155
- release = await record.lock.acquire()
156
- const newExp = Date.now() + newTTL
157
- for (const entry of record.data.addrs) {
158
- if (entry.ttl === oldTTL) {
159
- entry.ttl = newTTL
160
- entry.expiry = newExp
161
- record.dirty = true
162
- }
163
- }
164
- await this.cleanRecord(record)
165
- await this.flushRecord(record)
166
- await this.invalidateEdge(t)
167
- } finally {
168
- release()
169
- }
170
-
171
- }
172
-
173
-
174
- async addrs(t: ThreadID, logId: PeerId): Promise<Multiaddr[]> {
175
- let release = () => {}
176
- try {
177
- const record = await this.loadRecord(t, logId.toString(), true,true)
178
- release = await record.lock.acquire()
179
- const addrs: Multiaddr[] = []
180
- for (const entry of record.data.addrs) {
181
- addrs.push(multiaddr(entry.addr))
182
- }
183
- return addrs
184
- } finally {
185
- release()
186
- }
187
- }
188
-
189
-
190
- async clearAddrs(t: ThreadID, logId: PeerId): Promise<void> {
191
- this.cache.delete({ threadID: t, peerID: logId.toString() });
192
-
193
- const key = this.genDSKey(t, logId.toString());
194
- try {
195
- await this.ds.delete(key);
196
- await this.invalidateEdge(t);
197
- } catch (err:any) {
198
- throw new Error(`Failed to clear addresses for log ${logId.toString()}: ${err.message}`);
199
- }
200
- }
201
-
202
-
203
-
204
- async logsWithAddrs(t: ThreadID): Promise<PeerId[]> {
205
- try {
206
- const ids = await uniqueLogIds(this.ds, DsAddrBook.logBookBase.child(new Key(t.toString())), (result) => {
207
- return result.name();
208
- });
209
- return ids;
210
- } catch (err : any) {
211
- throw new Error(`Error while retrieving logs with addresses: ${err.message}`);
212
- }
213
- }
214
-
215
- async threadsFromAddrs(): Promise<ThreadID[]> {
216
- try {
217
- const ids = await uniqueThreadIds(this.ds, DsAddrBook.logBookBase, (result) => {
218
- return result.parent().name();
219
- });
220
- return ids;
221
- } catch (err:any) {
222
- throw new Error(`Error while retrieving thread from addresses: ${err.message}`);
223
- }
224
- }
225
-
226
-
227
-
228
-
229
- async addrsEdge(t: ThreadID, exceptPeerId?: string): Promise<bigint> {
230
- const key = dsThreadKey(t, DsAddrBook.logBookEdge);
231
- const retries = 3
232
- for (let attempt = 1; attempt <= retries; attempt++) {
233
- try {
234
- return await this.calculateEdge(t, key, exceptPeerId);
235
- } catch (err: any) {
236
- if (err.code !== 'TX_CONFLICT') throw err;
237
- await this.randomDelay(attempt);
238
- }
239
- }
240
- throw new Error('Edge computation failed');
241
- }
242
-
243
- private async calculateEdge(t: ThreadID, key: Key, exceptPeerId?: string): Promise<bigint> {
244
- return this.withTransaction(async txn => {
245
- try {
246
- const data = await txn.get(key);
247
- if (data) {
248
- return this.decodeStoredEdge(data);
249
- }
250
- } catch (err: any) {
251
- if (err.code !== 'ERR_NOT_FOUND') throw err;
252
- }
253
-
254
- const addrs = await this.collectAddrs(txn, t, exceptPeerId);
255
- if (addrs.length === 0) throw new Error('Thread not found');
256
-
257
- const edge = this.computeAddrsEdge(addrs);
258
- const buffer = Buffer.alloc(8);
259
- this.writeEdgeValue(buffer, edge);
260
-
261
- await txn.put(key, buffer);
262
- return edge;
263
- });
264
- }
265
-
266
- private async collectAddrs(txn: Transaction, t: ThreadID, exceptPeerId?: string): Promise<{ peerID: PeerId, addr: Uint8Array }[]> {
267
- const query = { prefix: dsThreadKey(t, DsAddrBook.logBookBase).toString() };
268
- const result = txn.query(query);
269
- const now = Date.now();
270
- const as: { peerID: PeerId, addr: Uint8Array }[] = [];
271
-
272
- for await (const entry of result) {
273
- const rawKey = entry.key as any;
274
- const key = rawKey instanceof Key ? rawKey : new Key(rawKey.toString());
275
- const pair: Pair = { key, value: entry.value };
276
- const { tid,pid, record } = this.decodeAddrEntry(pair, true);
277
- if (!record || (exceptPeerId && pid.toString() == exceptPeerId)) {
278
- continue;
279
- }
280
- for (const addr of record.addrs) {
281
- if (addr.expiry > now) {
282
- as.push({ peerID:pid, addr: addr.addr });
283
- }
284
- }
285
- }
286
- return as;
287
- }
288
-
289
- private async withTransaction<T>(fn: (txn: Transaction) => Promise<T>): Promise<T> {
290
- const txn = await this.ds.newTransactionExtended(false);
291
- try {
292
- const result = await fn(txn);
293
- await txn.commit();
294
- return result;
295
- } catch (err: any) {
296
- txn.discard();
297
- throw err;
298
- }
299
- }
300
-
301
- private decodeStoredEdge(data: Uint8Array): bigint {
302
- const buf: any = Buffer.from(data);
303
- const reader = buf as unknown as { readBigUInt64BE?: (offset?: number) => bigint };
304
- if (buf.length >= 8 && typeof reader.readBigUInt64BE === 'function') {
305
- return reader.readBigUInt64BE(0);
306
- }
307
- if (buf.length >= 4) {
308
- return BigInt(buf.readUInt32BE(0));
309
- }
310
- throw new Error('Corrupted head edge value');
311
- }
312
-
313
- private writeEdgeValue(buf: any, value: bigint): void {
314
- const writer = buf as unknown as { writeBigUInt64BE?: (val: bigint, offset?: number) => number };
315
- if (typeof writer.writeBigUInt64BE === 'function') {
316
- writer.writeBigUInt64BE(value, 0);
317
- return;
318
- }
319
- buf.writeUInt32BE(Number(value & 0xffffffffn), 0);
320
- }
321
-
322
- private randomDelay(attempt: number): Promise<void> {
323
- const delay = 50 * attempt + Math.random() * 30;
324
- return new Promise(resolve =>
325
- setTimeout(resolve, delay)
326
- );
327
- }
328
-
329
-
330
-
331
- private async loadRecord(t: ThreadID, p: string, cache: boolean,update:boolean): Promise<AddrsRecord> {
332
- const cacheKey = { threadID: t, peerID: p }
333
- if (this.cache.has(cacheKey)) {
334
- const addrsRecord = this.cache.get(cacheKey)!
335
- await this.cleanRecord(addrsRecord)
336
- if (update) {
337
- await this.flushRecord(addrsRecord)
338
- }
339
- return addrsRecord
340
- }
341
- const key = this.genDSKey(t, p)
342
- try {
343
- const data = await this.ds.get(key)
344
- const record = pb.AddrBookRecord.deserialize(data)
345
- const addrsRecord = { lock: new AsyncMutex(), data: record, dirty: false }
346
- await this.cleanRecord(addrsRecord)
347
- if (update) {
348
- await this.flushRecord(addrsRecord)
349
- }
350
- if (cache) {
351
- this.cache.set(cacheKey, addrsRecord)
352
- return addrsRecord
353
- }
354
- return addrsRecord
355
- } catch (err:any) {
356
- if (err.code === 'ERR_NOT_FOUND') {
357
- const peerIdBytes = new TextEncoder().encode(p)
358
- return {
359
- lock: new AsyncMutex(),
360
- data: pb.AddrBookRecord.fromObject({threadID:t.toBytes(), peerID:peerIdBytes,addrs:[] } ),
361
- dirty: false
362
- }
363
- }
364
- throw err
365
- }
366
- }
367
-
368
- private async cleanRecord(record: AddrsRecord): Promise<boolean> {
369
- const now = Date.now()
370
- const valid = record.data.addrs.filter(a => a.expiry > now)
371
- const changed = valid.length !== record.data.addrs.length
372
- record.data.addrs = valid.sort((a, b) => a.expiry - b.expiry)
373
- return changed
374
- }
375
-
376
- private async flushRecord(record: AddrsRecord): Promise<void> {
377
- const threadId = ThreadID.fromBytes(record.data.threadID)
378
- const logId = new TextDecoder().decode(record.data.peerID)
379
- if (record.data.addrs.length === 0) {
380
- await this.ds.delete(this.genDSKey(threadId, logId))
381
- } else {
382
- const data = record.data.serialize()
383
- await this.ds.put(this.genDSKey(threadId, logId), data)
384
- }
385
- record.dirty = false
386
- }
387
-
388
- private genDSKey(t: ThreadID, p: string): Key {
389
- const tKey = new Key(t.toString())
390
- const pKey = new Key(p)
391
- return DsAddrBook.logBookBase.child(tKey).child(pKey)
392
- }
393
-
394
-
395
- private async invalidateEdge(tid: ThreadID): Promise<void> {
396
- var key = dsThreadKey(tid, DsAddrBook.logBookEdge)
397
- return this.ds.delete(key)
398
- }
399
-
400
-
401
-
402
- private async traverse(withAddrs: boolean): Promise<{ [key: string]: { [key: string]: pb.AddrBookRecord } }> {
403
- const data: { [key: string]: { [key: string]: pb.AddrBookRecord } } = {};
404
- let result = this.ds.query({ prefix: DsAddrBook.logBookBase.toString()});
405
- for await (const entry of result) {
406
- const { tid, pid, record } = this.decodeAddrEntry(entry, withAddrs);
407
- const tidStr = tid.toString();
408
- if (!data[tidStr]) {
409
- data[tidStr] = {};
410
- }
411
- data[tidStr][pid.toString()] = record!;
412
- }
413
- return data;
414
- }
415
-
416
-
417
- private decodeAddrEntry(entry: any, withAddrs: boolean): { tid: ThreadID, pid: PeerId, record?: pb.AddrBookRecord } {
418
- const keyStr = typeof entry.key === 'string' ? entry.key : entry.key.toString();
419
- const kns = keyStr.split('/');
420
- if (kns.length < 3) {
421
- throw new Error(`bad addressbook key detected: ${keyStr}`);
422
- }
423
-
424
- // get thread and log IDs from the key components
425
- const ts = kns[kns.length - 2];
426
- const ls = kns[kns.length - 1];
427
-
428
- const tid = ThreadID.fromString(ts!);
429
- const pid = peerIdFromString(ls!);
430
-
431
- if (withAddrs) {
432
- const record = pb.AddrBookRecord.deserialize(entry.value);
433
- return { tid, pid, record };
434
- }
435
-
436
- return { tid, pid };
437
- }
438
-
439
-
440
-
441
- private computeAddrsEdge(as: { peerID: PeerId, addr: Uint8Array }[]): bigint {
442
- const entries = as.map(item => ({
443
- peerIDBytes: this.decodePeerId(item.peerID.toString(), new TextEncoder()),
444
- addr: item.addr,
445
- }));
446
-
447
- entries.sort((a, b) => {
448
- const peerIDCompare = bytes.compare(a.peerIDBytes, b.peerIDBytes);
449
- if (peerIDCompare !== 0) {
450
- return peerIDCompare;
451
- }
452
- return bytes.compare(a.addr, b.addr);
453
- });
454
-
455
- let hash = ADDR_FNV_OFFSET_BASIS;
456
-
457
- for (const entry of entries) {
458
- hash = this.fnv1a64(entry.peerIDBytes, hash);
459
- hash = this.fnv1a64(entry.addr, hash);
460
- }
461
-
462
- return hash;
463
- }
464
-
465
- private decodePeerId(peerID: string, encoder: TextEncoder): Uint8Array {
466
- if (!peerID) {
467
- return new Uint8Array();
468
- }
469
- try {
470
- return bases.base58btc.baseDecode(peerID);
471
- } catch (err: any) {
472
- return encoder.encode(peerID);
473
- }
474
- }
475
-
476
- private fnv1a64(data: Uint8Array, initial: bigint): bigint {
477
- let hash = initial;
478
- for (const byte of data) {
479
- hash ^= BigInt(byte);
480
- hash = (hash * ADDR_FNV_PRIME) % ADDR_MOD64;
481
- }
482
- return hash;
483
- }
484
-
485
-
486
- // dumpAddrs(): Promise<DumpAddrBook>;
487
- async dumpAddrs(): Promise<DumpAddrBook> {
488
- const dump: { [key: string]: { [key: string]: { addr: Multiaddr, expires: Date }[] } } = {};
489
- const data = await this.traverse(true);
490
-
491
- for (const [tid, logs] of Object.entries(data)) {
492
- const lm: { [key: string]: { addr: Multiaddr, expires: Date }[] } = {};
493
- for (const [lid, rec] of Object.entries(logs)) {
494
- if (rec.addrs.length > 0) {
495
- const addrs = rec.addrs.map(r => ({
496
- addr: multiaddr(r.addr),
497
- expires: new Date(r.expiry)
498
- }));
499
- lm[lid] = addrs.map(a => ({ addr: a.addr, expires: a.expires }));
500
- }
501
- }
502
- dump[tid] = lm;
503
- }
504
- return { data: dump };
505
- }
506
-
507
- async restoreAddrs(dump:DumpAddrBook): Promise<void> {
508
- if (!AllowEmptyRestore && Object.keys(dump.data).length === 0) {
509
- throw new Error('Empty dump');
510
- }
511
-
512
- const stored = await this.traverse(false);
513
-
514
- for (const [tid, logs] of Object.entries(stored)) {
515
- for (const lid of Object.keys(logs)) {
516
- await this.clearAddrs(ThreadID.fromString(tid), peerIdFromString(lid));
517
- }
518
- }
519
- const current = new Date();
520
- for (const [tid, logs] of Object.entries(dump.data)) {
521
- for (const [lid, addrs] of Object.entries(logs)) {
522
- for (const addr of addrs) {
523
- const ttl = addr.expires.getTime() - current.getTime();
524
- if (ttl > 0) {
525
- await this.setAddrs(ThreadID.fromString(tid), peerIdFromString(lid), [multiaddr(addr.addr)], ttl);
526
- }
527
- }
528
- }
529
- }
530
- }
531
- }
532
-
533
- // 辅助类实现
534
- class AsyncMutex {
535
- private queue: (() => void)[] = []
536
- private locked = false
537
-
538
- async acquire(): Promise<() => void> {
539
- while (this.locked) {
540
- await new Promise<void>(resolve => this.queue.push(resolve))
541
- }
542
- this.locked = true
543
- return () => {
544
- this.locked = false
545
- const next = this.queue.shift()
546
- next?.()
547
- }
548
- }
549
- }
@@ -1,36 +0,0 @@
1
- // 修改后的缓存接口声明(保证方法签名严格匹配)
2
- interface CacheStore<K, V> {
3
- get(key: K): V | undefined;
4
- add(key: K, value: V): void; // 明确声明两个参数
5
- remove(key: K): void;
6
- contains(key: K): boolean;
7
- peek(key: K): V | undefined;
8
- keys(): K[];
9
- }
10
-
11
- // 修正实现类的参数匹配
12
- class NoopCache<K, V> implements CacheStore<K, V> {
13
- get(_key: K): V | undefined {
14
- return undefined;
15
- }
16
-
17
- add(_key: K, _value: V): void {
18
- // 空操作,保留两个参数
19
- }
20
-
21
- remove(_key: K): void {
22
- // 空操作,保留单个参数
23
- }
24
-
25
- contains(_key: K): boolean {
26
- return false;
27
- }
28
-
29
- peek(_key: K): V | undefined {
30
- return undefined;
31
- }
32
-
33
- keys(): K[] {
34
- return [];
35
- }
36
- }
@@ -1,87 +0,0 @@
1
- import { Datastore,Batch ,Key} from 'interface-datastore';
2
-
3
-
4
- type CyclicBatchOptions = {
5
- opsPerBatch?: number;
6
- };
7
-
8
- export class CyclicBatch implements Batch {
9
- private currentBatch: Batch | null = null;
10
- private pendingOps = 0;
11
- private readonly threshold: number;
12
- private closed = false;
13
-
14
- constructor(
15
- private readonly ds: Datastore,
16
- options: CyclicBatchOptions = {}
17
- ) {
18
- this.threshold = options.opsPerBatch || 20;
19
- }
20
-
21
- private async initializeBatch(): Promise<void> {
22
- if (!this.currentBatch && !this.closed) {
23
- this.currentBatch = this.ds.batch();
24
- }
25
- }
26
-
27
- private async cycle(): Promise<void> {
28
- if (this.closed) {
29
- throw new Error('Cyclic batch is closed');
30
- }
31
-
32
- if (this.pendingOps < this.threshold || !this.currentBatch) {
33
- return;
34
- }
35
-
36
- try {
37
- await this.currentBatch.commit();
38
- this.pendingOps = 0;
39
- this.currentBatch = this.ds.batch();
40
- } catch (err:any) {
41
- throw new Error(`Batch operation failed: ${err.message}`);
42
- }
43
- }
44
-
45
- async put(key: Key, value: Uint8Array): Promise<void> {
46
- if (this.closed) {
47
- throw new Error('Cannot write to closed batch');
48
- }
49
-
50
- await this.initializeBatch();
51
- await this.cycle();
52
-
53
- if (this.currentBatch) {
54
- this.pendingOps++;
55
- await this.currentBatch.put(key, value);
56
- }
57
- }
58
-
59
- async delete(key: Key): Promise<void> {
60
- if (this.closed) {
61
- throw new Error('Cannot write to closed batch');
62
- }
63
-
64
- await this.initializeBatch();
65
- await this.cycle();
66
-
67
- if (this.currentBatch) {
68
- this.pendingOps++;
69
- await this.currentBatch.delete(key);
70
- }
71
- }
72
-
73
- async commit(): Promise<void> {
74
- if (this.closed) {
75
- throw new Error('Batch already committed');
76
- }
77
-
78
- if (this.currentBatch) {
79
- await this.currentBatch.commit();
80
- this.currentBatch = null;
81
- }
82
-
83
- this.closed = true;
84
- this.pendingOps = 0;
85
- }
86
- }
87
-