@torrent-tv/proxy 2.9.92 → 2.9.95
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/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/routes/stream/get.js +62 -2
- package/services/hls-session-manager.js +124 -27
- package/services/piece-store/piece-lru.js +71 -0
- package/services/piece-store/shared-piece-store.js +57 -0
- package/services/playback-planner.js +17 -0
- package/services/torrent-worker/client.js +448 -447
- package/services/torrent-worker/piece-reader.js +124 -22
- package/services/torrent-worker/worker.js +412 -410
- package/test/piece-lru.test.js +64 -0
- package/test/read-window.test.js +9 -5
package/test/piece-lru.test.js
CHANGED
|
@@ -107,3 +107,67 @@ test("a nonsensical capacity is refused at construction", () => {
|
|
|
107
107
|
assert.throws(() => new PieceLru(-1), /positive integer/);
|
|
108
108
|
assert.throws(() => new PieceLru(1.5), /positive integer/);
|
|
109
109
|
});
|
|
110
|
+
|
|
111
|
+
test("a declared window is the last thing evicted, not the first", () => {
|
|
112
|
+
const lru = new PieceLru(4);
|
|
113
|
+
// Oldest first: 10 was touched longest ago, so plain recency would take it.
|
|
114
|
+
for (const index of [10, 11, 12, 13]) {
|
|
115
|
+
lru.touch(index);
|
|
116
|
+
}
|
|
117
|
+
lru.protect("reader-a", 10, 11);
|
|
118
|
+
|
|
119
|
+
assert.equal(
|
|
120
|
+
lru.evictionCandidate(),
|
|
121
|
+
12,
|
|
122
|
+
"recency alone would have taken 10; the reader said it is about to read it"
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("protection yields when everything resident is protected", () => {
|
|
127
|
+
// The case the store cannot survive if protection were absolute: at its
|
|
128
|
+
// smallest budget only two pieces are resident, and both belong to a window.
|
|
129
|
+
const lru = new PieceLru(2);
|
|
130
|
+
lru.touch(4);
|
|
131
|
+
lru.touch(5);
|
|
132
|
+
lru.protect("reader-a", 4, 5);
|
|
133
|
+
|
|
134
|
+
assert.equal(lru.evictionCandidate(), 4, "a full store must still be able to admit a piece");
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test("a pin is never overruled, protected or not", () => {
|
|
138
|
+
const lru = new PieceLru(2);
|
|
139
|
+
lru.touch(7);
|
|
140
|
+
lru.touch(8);
|
|
141
|
+
lru.pin(7);
|
|
142
|
+
lru.protect("reader-a", 7, 8);
|
|
143
|
+
|
|
144
|
+
assert.equal(lru.evictionCandidate(), 8, "the piece being read now must stay");
|
|
145
|
+
lru.pin(8);
|
|
146
|
+
assert.equal(lru.evictionCandidate(), null, "nothing may be taken from under a reader");
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("windows of several readers add up, and leaving takes only your own", () => {
|
|
150
|
+
const lru = new PieceLru(6);
|
|
151
|
+
for (const index of [20, 21, 22, 23, 24, 25]) {
|
|
152
|
+
lru.touch(index);
|
|
153
|
+
}
|
|
154
|
+
lru.protect("reader-a", 20, 21);
|
|
155
|
+
lru.protect("reader-b", 22, 23);
|
|
156
|
+
assert.equal(lru.evictionCandidate(), 24);
|
|
157
|
+
|
|
158
|
+
lru.unprotect("reader-b");
|
|
159
|
+
assert.equal(lru.evictionCandidate(), 22, "b's window is free once b has gone");
|
|
160
|
+
assert.equal(lru.protectedCount, 1);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test("a reader moving its window replaces it instead of accumulating", () => {
|
|
164
|
+
const lru = new PieceLru(4);
|
|
165
|
+
for (const index of [30, 31, 32, 33]) {
|
|
166
|
+
lru.touch(index);
|
|
167
|
+
}
|
|
168
|
+
lru.protect("reader-a", 30, 31);
|
|
169
|
+
lru.protect("reader-a", 32, 33);
|
|
170
|
+
|
|
171
|
+
assert.equal(lru.evictionCandidate(), 30, "the pieces already read are free again");
|
|
172
|
+
assert.equal(lru.protectedCount, 1);
|
|
173
|
+
});
|
package/test/read-window.test.js
CHANGED
|
@@ -209,7 +209,7 @@ test("two readers add up, and one leaving takes only its own window", async () =
|
|
|
209
209
|
}
|
|
210
210
|
});
|
|
211
211
|
|
|
212
|
-
test("criticality marks the
|
|
212
|
+
test("criticality marks the window being waited for, not the whole range", async () => {
|
|
213
213
|
// Nothing is present, so the reader blocks on its first piece and marks it.
|
|
214
214
|
let arrived = false;
|
|
215
215
|
const { torrent, store, directory } = await recordingTorrent({
|
|
@@ -226,10 +226,14 @@ test("criticality marks the piece being waited for, not the whole range", async
|
|
|
226
226
|
|
|
227
227
|
const criticals = torrent.calls.filter((entry) => entry.call === "critical");
|
|
228
228
|
assert.equal(criticals.length, 1);
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
229
|
+
const marked = criticals[0].to - criticals[0].from + 1;
|
|
230
|
+
// The window, and nothing beyond it. Marking only the blocked piece made
|
|
231
|
+
// the pieces after it arrive strictly one at a time — measured, the first
|
|
232
|
+
// segment after a seek took 7.2 s for four pieces. Marking the whole
|
|
233
|
+
// requested range would be the old mistake: for ffmpeg's input that is
|
|
234
|
+
// every piece to the end of the file, and the flag stops meaning anything.
|
|
235
|
+
assert.equal(marked, WINDOW_PIECES, `marked ${marked} pieces critical`);
|
|
236
|
+
assert.ok(criticals[0].to < 8000 - 1, "criticality must not reach the end of the file");
|
|
233
237
|
|
|
234
238
|
arrived = true;
|
|
235
239
|
torrent.emit("verified", 0);
|