Closed danbo closed 2 months ago
I would like to bump this issue with a new reproduction and my explanation of the problem.
If the number of requests in request.dynamic
is less than the prefetch
value, but greater than 0, request.dynamic
tries to get new requests ~as fast as possible~ every frame.
t = ref(true)
def next()
print("Next called #{time.up()}")
if t() then
t := false
request.create("/tmp/test/music/1.mp3")
else
null()
end
end
q = request.dynamic(next, retry_delay=10.)
output.dummy(q, fallible=true)
savonet/liquidsoap:v2.2.4
This is still an issue in 2.2.5 and 2.3.x rolling.
It appears to happen after the first successful request starts playing. If prefetch can't successfully queue up the next request, the function continues to be called repeatedly. In fact, I ran the summarized version above (thanks @vitoyucepi) and it looks like it's running on every frame (0.02s in 2.3.x):
Next called 2.22548508644
Next called 2.24156308174
Next called 2.26178503036
Next called 2.28161716461
Next called 2.30140519142
And every 0.04s in 2.2.5:
Next called 9.41492486
Next called 9.45046186447
Next called 9.49060988426
Next called 9.53048801422
Next called 9.57054781914
Notes:
I see this problem with request.queue() as well since it uses request.dynamic under the hood.
To ensure logic executes within the retry period, I've been using a time based throttle like this (of course the check is actually executing every 0.02s if there is a prefetch error)
lastTime = ref(0.)
...
def next()
rid = ref(null())
currentTime = time()
elapsedSeconds = currentTime - lastTime()
if (elapsedSeconds > 5) then
lastTime.set(currentTime)
...
r = request.create(...)
rid.set(r)
end
rid()
end
The old frame interval is 0.04, the new one is 0.02. So liquidsoap tries to get a new request every frame.
Describe the bug
Requests are being made when they shouldn't need to be during bad / error states. Related to #3026.
To Reproduce
Test script:
Expected behavior
Case 1
State: tcp endpoint down, no script changes, test mp3 file available
Expected behaviour: get_request should only be called when required, ie pre-fetch or the previous one is finishing, vs on error - only a reconnection should be happening on failure and not also a get_request. Streaming should just resume on the reconnected output once it becomes available if the request has already been made and is playing on the other output, ie dummy.
Log:
Case 2
State: output.external commented out, test mp3 filename changed to non-existent one / bad uri
Expected behaviour: get_request should be throttled to the retry_delay value, in the script's case - 5 seconds.
Log:
Version details
Install method Official docker images