@helia/bitswap 3.1.2-2c225e85 → 3.1.2-92480ee8
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/index.min.js +1 -1
- package/dist/index.min.js.map +3 -3
- package/dist/src/bitswap.d.ts +2 -2
- package/dist/src/bitswap.d.ts.map +1 -1
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +1 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/index.d.ts +10 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/peer-want-lists/index.d.ts +4 -2
- package/dist/src/peer-want-lists/index.d.ts.map +1 -1
- package/dist/src/peer-want-lists/index.js +27 -2
- package/dist/src/peer-want-lists/index.js.map +1 -1
- package/dist/src/peer-want-lists/ledger.d.ts +14 -0
- package/dist/src/peer-want-lists/ledger.d.ts.map +1 -1
- package/dist/src/peer-want-lists/ledger.js +31 -7
- package/dist/src/peer-want-lists/ledger.js.map +1 -1
- package/package.json +3 -3
- package/src/bitswap.ts +2 -2
- package/src/constants.ts +1 -0
- package/src/index.ts +13 -1
- package/src/peer-want-lists/index.ts +37 -4
- package/src/peer-want-lists/ledger.ts +53 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import toBuffer from 'it-to-buffer'
|
|
2
|
-
import { DEFAULT_MAX_SIZE_REPLACE_HAS_WITH_BLOCK } from '../constants.js'
|
|
2
|
+
import { DEFAULT_MAX_SIZE_REPLACE_HAS_WITH_BLOCK, DEFAULT_DO_NOT_RESEND_BLOCK_WINDOW } from '../constants.js'
|
|
3
3
|
import { BlockPresenceType, WantType } from '../pb/message.js'
|
|
4
4
|
import { QueuedBitswapMessage } from '../utils/bitswap-message.js'
|
|
5
5
|
import { cidToPrefix } from '../utils/cid-prefix.js'
|
|
@@ -17,6 +17,7 @@ export interface LedgerComponents {
|
|
|
17
17
|
|
|
18
18
|
export interface LedgerInit {
|
|
19
19
|
maxSizeReplaceHasWithBlock?: number
|
|
20
|
+
doNotResendBlockWindow?: number
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export interface PeerWantListEntry {
|
|
@@ -45,6 +46,19 @@ export interface PeerWantListEntry {
|
|
|
45
46
|
* If we don't have the block and we've told them we don't have the block
|
|
46
47
|
*/
|
|
47
48
|
sentDoNotHave?: boolean
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* If the status is `sending` or `sent`, the block for this CID is or has been
|
|
52
|
+
* sent to the peer so we should not attempt to send it again
|
|
53
|
+
*/
|
|
54
|
+
status: 'want' | 'sending' | 'sent'
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A timestamp for when this want should be removed from the list, typically
|
|
58
|
+
* this is set with the `sent` status to prevent sending duplicate blocks to a
|
|
59
|
+
* peer. Once it has expired the peer can request the block a subsequent time.
|
|
60
|
+
*/
|
|
61
|
+
expires?: number
|
|
48
62
|
}
|
|
49
63
|
|
|
50
64
|
export class Ledger {
|
|
@@ -58,6 +72,7 @@ export class Ledger {
|
|
|
58
72
|
public lastExchange?: number
|
|
59
73
|
private readonly maxSizeReplaceHasWithBlock: number
|
|
60
74
|
private readonly log: Logger
|
|
75
|
+
private readonly doNotResendBlockWindow: number
|
|
61
76
|
|
|
62
77
|
constructor (components: LedgerComponents, init: LedgerInit) {
|
|
63
78
|
this.peerId = components.peerId
|
|
@@ -70,6 +85,7 @@ export class Ledger {
|
|
|
70
85
|
this.bytesSent = 0
|
|
71
86
|
this.bytesReceived = 0
|
|
72
87
|
this.maxSizeReplaceHasWithBlock = init.maxSizeReplaceHasWithBlock ?? DEFAULT_MAX_SIZE_REPLACE_HAS_WITH_BLOCK
|
|
88
|
+
this.doNotResendBlockWindow = init.doNotResendBlockWindow ?? DEFAULT_DO_NOT_RESEND_BLOCK_WINDOW
|
|
73
89
|
}
|
|
74
90
|
|
|
75
91
|
sentBytes (n: number): void {
|
|
@@ -88,18 +104,47 @@ export class Ledger {
|
|
|
88
104
|
return (this.bytesSent / (this.bytesReceived + 1)) // +1 is to prevent division by zero
|
|
89
105
|
}
|
|
90
106
|
|
|
107
|
+
removeExpiredWants (): void {
|
|
108
|
+
// remove any expired wants
|
|
109
|
+
this.wants.forEach((value, key) => {
|
|
110
|
+
if (value.expires != null && value.expires < Date.now()) {
|
|
111
|
+
this.wants.delete(key)
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
91
116
|
public async sendBlocksToPeer (options?: AbortOptions): Promise<void> {
|
|
92
117
|
const message = new QueuedBitswapMessage()
|
|
93
118
|
const sentBlocks = new Set<string>()
|
|
94
119
|
|
|
95
|
-
|
|
120
|
+
// remove any expired wants
|
|
121
|
+
this.removeExpiredWants()
|
|
122
|
+
|
|
123
|
+
// pick unsent wants
|
|
124
|
+
const unsent = [...this.wants.entries()]
|
|
125
|
+
.filter(([key, value]) => value.status === 'want')
|
|
126
|
+
|
|
127
|
+
// update status, ensure we don't send the same blocks repeatedly
|
|
128
|
+
unsent.forEach(([key, value]) => {
|
|
129
|
+
value.status = 'sending'
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
for (const [key, entry] of unsent) {
|
|
96
133
|
try {
|
|
97
134
|
const block = await toBuffer(this.blockstore.get(entry.cid, options))
|
|
98
135
|
|
|
136
|
+
// ensure we still need to send the block/status, status may have
|
|
137
|
+
// changed due to incoming message while we were waiting for async block
|
|
138
|
+
// load
|
|
139
|
+
if (entry.status !== 'sending') {
|
|
140
|
+
continue
|
|
141
|
+
}
|
|
142
|
+
|
|
99
143
|
// do they want the block or just us to tell them we have the block
|
|
100
144
|
if (entry.wantType === WantType.WantHave) {
|
|
101
145
|
if (block.byteLength < this.maxSizeReplaceHasWithBlock) {
|
|
102
146
|
this.log('sending have and block for %c', entry.cid)
|
|
147
|
+
|
|
103
148
|
// if the block is small we just send it to them
|
|
104
149
|
sentBlocks.add(key)
|
|
105
150
|
message.addBlock(entry.cid, {
|
|
@@ -123,11 +168,17 @@ export class Ledger {
|
|
|
123
168
|
prefix: cidToPrefix(entry.cid)
|
|
124
169
|
})
|
|
125
170
|
}
|
|
171
|
+
|
|
172
|
+
entry.status = 'sent'
|
|
173
|
+
entry.expires = Date.now() + this.doNotResendBlockWindow
|
|
126
174
|
} catch (err: any) {
|
|
127
175
|
if (err.name !== 'NotFoundError') {
|
|
128
176
|
throw err
|
|
129
177
|
}
|
|
130
178
|
|
|
179
|
+
// reset status to try again later
|
|
180
|
+
entry.status = 'want'
|
|
181
|
+
|
|
131
182
|
this.log('do not have block for %c', entry.cid)
|
|
132
183
|
|
|
133
184
|
// we don't have the requested block and the remote is not interested
|
|
@@ -157,12 +208,6 @@ export class Ledger {
|
|
|
157
208
|
|
|
158
209
|
// update accounting
|
|
159
210
|
this.sentBytes([...message.blocks.values()].reduce((acc, curr) => acc + curr.data.byteLength, 0))
|
|
160
|
-
|
|
161
|
-
// remove sent blocks from local copy of their want list - they can still
|
|
162
|
-
// re-request if required
|
|
163
|
-
for (const key of sentBlocks) {
|
|
164
|
-
this.wants.delete(key)
|
|
165
|
-
}
|
|
166
211
|
}
|
|
167
212
|
}
|
|
168
213
|
}
|