@torrent-tv/proxy 2.80.10 → 2.80.11
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 +1685 -1675
- package/package.json +50 -51
- package/services/encode/run-command.js +729 -707
- package/services/hls-session-manager.js +10168 -10388
- package/services/orchestrators/EncodeOrchestrator.js +726 -726
- package/services/output/LiveOutputs.js +49 -0
- package/services/priority/PriorityOrchestrator.js +278 -174
- package/test/decode-cost-fit.test.js +57 -0
- package/{test-measured/decode-cost.measured.js → test/decode-cost.test.js} +13 -36
- package/test/keyframe-table-budget.test.js +7 -1
- package/test/one-authority.test.js +220 -105
- package/test/piece-store-slow-disk.test.js +32 -2
- package/test/priority-map-per-output.test.js +211 -0
- package/test/quality-variants.test.js +1222 -1209
- package/test/tracks-begin-together.test.js +32 -13
- package/test/tunnel-renewal.test.js +34 -5
- package/test/two-viewers-one-picture.test.js +374 -347
- package/test/viewer-outputs.test.js +277 -278
- package/test-measured/decode-measurement.measured.js +0 -83
|
@@ -19,6 +19,7 @@ import { Timeline } from "../services/output/Timeline.js";
|
|
|
19
19
|
import test from "node:test";
|
|
20
20
|
|
|
21
21
|
import { HlsSessionManager } from "../services/hls-session-manager.js";
|
|
22
|
+
import { trueStartOf } from "../services/encode/run-command.js";
|
|
22
23
|
import { fmp4Format } from "../services/segment-formats/fmp4.js";
|
|
23
24
|
import { ENCODE_RUN_STATE, INITIAL_RUN_STATE } from "../services/encode/encode-run-state.js";
|
|
24
25
|
|
|
@@ -108,20 +109,38 @@ test("a soundtrack follows the picture to the instant the picture really began",
|
|
|
108
109
|
10.5,
|
|
109
110
|
"and every member's table with it — one film, one table, nothing to keep in step"
|
|
110
111
|
);
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
112
|
+
// THE RUN AT THE WRONG INSTANT IS STOPPED, and nothing here places its
|
|
113
|
+
// replacement. What has been learned is that this run is producing in the
|
|
114
|
+
// wrong place, which nothing but the piece it produced could say — the plan
|
|
115
|
+
// reasons about numbers and cannot know it. So the fact is acted on as far as
|
|
116
|
+
// it is known and no further: the run goes, the stretch it held returns to the
|
|
117
|
+
// map, and where the next one stands follows from where the viewers are.
|
|
118
|
+
assert.equal(runBefore.state, ENCODE_RUN_STATE.STOPPED, "the run in the wrong place goes");
|
|
119
|
+
assert.equal(sound.pendingRun, null, "and this path places nothing");
|
|
120
|
+
// The corrected instant reaches whatever the plan places there through the
|
|
121
|
+
// table, which every session of the file shares. It used to be passed as an
|
|
122
|
+
// argument from this one call site, so only a run started by that line ever
|
|
123
|
+
// had it — a run the plan placed at the same number landed apart again.
|
|
124
|
+
assert.equal(
|
|
125
|
+
trueStartOf(sound.timeline, 2),
|
|
126
|
+
10.5,
|
|
127
|
+
"the live table holds the measurement and the published one the prediction"
|
|
128
|
+
);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("where a number really begins is answered only where it has been measured", () => {
|
|
132
|
+
const { sound } = familyAtBoundaryTwo();
|
|
133
|
+
|
|
134
|
+
assert.equal(
|
|
135
|
+
trueStartOf(sound.timeline, 2),
|
|
136
|
+
undefined,
|
|
137
|
+
"the two tables agree, so there is nothing measured to prefer"
|
|
122
138
|
);
|
|
123
|
-
|
|
124
|
-
assert.equal(
|
|
139
|
+
sound.timeline.boundaries[2] = 10.5;
|
|
140
|
+
assert.equal(trueStartOf(sound.timeline, 2), 10.5);
|
|
141
|
+
assert.equal(trueStartOf(sound.timeline, 3), undefined, "and only about the number measured");
|
|
142
|
+
assert.equal(trueStartOf(sound.timeline, 99), undefined, "a number the file does not have");
|
|
143
|
+
assert.equal(trueStartOf(null, 0), undefined, "and no table at all");
|
|
125
144
|
});
|
|
126
145
|
|
|
127
146
|
test("a correction the table already holds moves nobody", () => {
|
|
@@ -19,6 +19,29 @@ import { WebSocketServer } from "ws";
|
|
|
19
19
|
|
|
20
20
|
import { createTunnelClient } from "../services/tunnel-client.js";
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Wait for the thing being asserted, not for a length of time.
|
|
24
|
+
*
|
|
25
|
+
* A chosen interval followed by an assertion does not test — it samples, and
|
|
26
|
+
* what it samples is how busy the machine is. The deadline here is a backstop
|
|
27
|
+
* that turns a hang into a failure; it is never the measurement.
|
|
28
|
+
*
|
|
29
|
+
* @param {() => boolean} until
|
|
30
|
+
* @param {string} what - Named in the failure, since a timeout otherwise says
|
|
31
|
+
* only that something did not happen.
|
|
32
|
+
* @param {number} [limit]
|
|
33
|
+
* @returns {Promise<void>}
|
|
34
|
+
*/
|
|
35
|
+
async function waitFor(until, what, limit = 10_000) {
|
|
36
|
+
const deadline = Date.now() + limit;
|
|
37
|
+
while (!until()) {
|
|
38
|
+
if (Date.now() > deadline) {
|
|
39
|
+
throw new Error(`${what} never happened`);
|
|
40
|
+
}
|
|
41
|
+
await new Promise((resolve) => { setTimeout(resolve, 5); });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
22
45
|
/**
|
|
23
46
|
* A stand-in for the registry's tunnel endpoint, with the one behaviour that
|
|
24
47
|
* matters here: a new connection for a proxy REPLACES the previous one, which
|
|
@@ -92,8 +115,10 @@ test("the connection is replaced before its lifetime runs out, without a gap", a
|
|
|
92
115
|
});
|
|
93
116
|
|
|
94
117
|
client.connect();
|
|
95
|
-
//
|
|
96
|
-
|
|
118
|
+
// Until the renewals have happened, however long this machine takes over
|
|
119
|
+
// them. Waited out as 700 ms instead — about four lifetimes — this asserted
|
|
120
|
+
// how many the scheduler had got round to.
|
|
121
|
+
await waitFor(() => registry.opened() >= 3, "three connections");
|
|
97
122
|
|
|
98
123
|
assert.ok(registry.opened() >= 3, `expected several renewals, saw ${registry.opened()}`);
|
|
99
124
|
// The property this exists for: the registry was never left with nothing.
|
|
@@ -128,11 +153,15 @@ test("a connection killed from outside is still reconnected", async (t) => {
|
|
|
128
153
|
});
|
|
129
154
|
|
|
130
155
|
client.connect();
|
|
131
|
-
await
|
|
156
|
+
await waitFor(() => registry.opened() === 1, "the first connection");
|
|
157
|
+
// And exactly one: the lifetime above is far longer than this test runs, so
|
|
158
|
+
// nothing renews and a second would mean something else had opened it.
|
|
132
159
|
assert.equal(registry.opened(), 1);
|
|
133
160
|
|
|
134
161
|
registry.killCurrent();
|
|
135
|
-
await new Promise((resolve) => { setTimeout(resolve, 300); });
|
|
136
162
|
// The renewal must not have taken the ordinary reconnect away with it.
|
|
137
|
-
|
|
163
|
+
await waitFor(
|
|
164
|
+
() => lines.some((line) => line.includes("Reconnecting in")),
|
|
165
|
+
"the reconnect after a connection was killed from outside"
|
|
166
|
+
);
|
|
138
167
|
});
|