refactor: refactor segment remuxer...
This commit is contained in:
parent
ebf75ab487
commit
35ef14b31c
@ -52,15 +52,17 @@ def parse(
|
|||||||
observer.on_next(tag)
|
observer.on_next(tag)
|
||||||
stream.close()
|
stream.close()
|
||||||
except EOFError as e:
|
except EOFError as e:
|
||||||
|
logger.debug(f'Error occurred while parsing stream: {repr(e)}')
|
||||||
if complete_on_eof:
|
if complete_on_eof:
|
||||||
observer.on_completed()
|
observer.on_completed()
|
||||||
else:
|
else:
|
||||||
if not ignore_eof:
|
if not ignore_eof:
|
||||||
observer.on_error(e)
|
observer.on_error(e)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
if ignore_value_error:
|
logger.debug(
|
||||||
logger.debug(f'Error occurred while parsing stream: {repr(e)}')
|
f'Error occurred while parsing stream: {repr(e)}', exc_info=e
|
||||||
else:
|
)
|
||||||
|
if not ignore_value_error:
|
||||||
observer.on_error(e)
|
observer.on_error(e)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
observer.on_error(e)
|
observer.on_error(e)
|
||||||
|
@ -7,6 +7,8 @@ from typing import Final, List, Optional, Union
|
|||||||
import urllib3
|
import urllib3
|
||||||
from reactivex import Observable, abc
|
from reactivex import Observable, abc
|
||||||
from reactivex.disposable import CompositeDisposable, Disposable, SerialDisposable
|
from reactivex.disposable import CompositeDisposable, Disposable, SerialDisposable
|
||||||
|
from tenacity import Retrying, stop_after_delay, wait_fixed
|
||||||
|
from tenacity.retry import retry_if_not_exception_type
|
||||||
|
|
||||||
from blrec.bili.live import Live
|
from blrec.bili.live import Live
|
||||||
from blrec.utils.io import wait_for
|
from blrec.utils.io import wait_for
|
||||||
@ -69,12 +71,20 @@ class SegmentRemuxer:
|
|||||||
if isinstance(data, InitSectionData):
|
if isinstance(data, InitSectionData):
|
||||||
init_section_data = data.payload
|
init_section_data = data.payload
|
||||||
segment_data_cache.clear()
|
segment_data_cache.clear()
|
||||||
|
logger.debug('Stop stream remuxer for init section')
|
||||||
|
self._stream_remuxer.stop()
|
||||||
|
|
||||||
|
if self._stream_remuxer.exception and not self._stream_remuxer.stopped:
|
||||||
|
logger.debug(
|
||||||
|
'Stop stream remuxer due to '
|
||||||
|
+ repr(self._stream_remuxer.exception)
|
||||||
|
)
|
||||||
self._stream_remuxer.stop()
|
self._stream_remuxer.stop()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self._stream_remuxer.stopped:
|
if self._stream_remuxer.stopped:
|
||||||
while True:
|
|
||||||
self._stream_remuxer.start()
|
self._stream_remuxer.start()
|
||||||
|
while True:
|
||||||
ready = self._stream_remuxer.wait(timeout=1)
|
ready = self._stream_remuxer.wait(timeout=1)
|
||||||
if disposed:
|
if disposed:
|
||||||
return
|
return
|
||||||
@ -94,6 +104,7 @@ class SegmentRemuxer:
|
|||||||
write(data.payload)
|
write(data.payload)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f'Failed to write data to stream remuxer: {repr(e)}')
|
logger.warning(f'Failed to write data to stream remuxer: {repr(e)}')
|
||||||
|
logger.debug(f'Stop stream remuxer due to {repr(e)}')
|
||||||
self._stream_remuxer.stop()
|
self._stream_remuxer.stop()
|
||||||
if len(segment_data_cache) >= self._MAX_SEGMENT_DATA_CACHE:
|
if len(segment_data_cache) >= self._MAX_SEGMENT_DATA_CACHE:
|
||||||
segment_data_cache = segment_data_cache[
|
segment_data_cache = segment_data_cache[
|
||||||
@ -121,6 +132,10 @@ class SegmentRemuxer:
|
|||||||
return Observable(subscribe)
|
return Observable(subscribe)
|
||||||
|
|
||||||
|
|
||||||
|
class CloseRemuxedStream(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class RemuxedStream(io.RawIOBase):
|
class RemuxedStream(io.RawIOBase):
|
||||||
def __init__(
|
def __init__(
|
||||||
self, stream_remuxer: StreamRemuxer, *, read_timeout: float = 10
|
self, stream_remuxer: StreamRemuxer, *, read_timeout: float = 10
|
||||||
@ -133,21 +148,27 @@ class RemuxedStream(io.RawIOBase):
|
|||||||
if self._stream_remuxer.stopped:
|
if self._stream_remuxer.stopped:
|
||||||
ready = self._stream_remuxer.wait(timeout=self._read_timeout)
|
ready = self._stream_remuxer.wait(timeout=self._read_timeout)
|
||||||
if not ready:
|
if not ready:
|
||||||
logger.debug(
|
msg = f'Stream remuxer not ready in {self._read_timeout} seconds'
|
||||||
f'Stream remuxer not ready in {self._read_timeout} seconds'
|
logger.debug(msg)
|
||||||
)
|
raise EOFError(msg)
|
||||||
raise EOFError
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
for attempt in Retrying(
|
||||||
|
reraise=True,
|
||||||
|
retry=retry_if_not_exception_type(TimeoutError),
|
||||||
|
wait=wait_fixed(1),
|
||||||
|
stop=stop_after_delay(self._read_timeout),
|
||||||
|
):
|
||||||
|
with attempt:
|
||||||
data = wait_for(
|
data = wait_for(
|
||||||
self._stream_remuxer.output.read,
|
self._stream_remuxer.output.read,
|
||||||
args=(size,),
|
args=(size,),
|
||||||
timeout=self._read_timeout,
|
timeout=self._read_timeout,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as exc:
|
||||||
logger.warning(f'Failed to read data from stream remuxer: {repr(e)}')
|
logger.warning(f'Failed to read data from stream remuxer: {repr(exc)}')
|
||||||
self._stream_remuxer.stop()
|
self._stream_remuxer.exception = exc
|
||||||
raise EOFError
|
raise EOFError(exc)
|
||||||
else:
|
else:
|
||||||
assert data is not None
|
assert data is not None
|
||||||
self._offset += len(data)
|
self._offset += len(data)
|
||||||
@ -157,4 +178,9 @@ class RemuxedStream(io.RawIOBase):
|
|||||||
return self._offset
|
return self._offset
|
||||||
|
|
||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
self._stream_remuxer.stop()
|
if self._stream_remuxer.stopped:
|
||||||
|
return
|
||||||
|
if self._stream_remuxer.exception:
|
||||||
|
return
|
||||||
|
logger.debug('Close remuxed stream')
|
||||||
|
self._stream_remuxer.exception = CloseRemuxedStream()
|
||||||
|
@ -55,6 +55,10 @@ class StreamRemuxer(StoppableMixin, SupportDebugMixin):
|
|||||||
def exception(self) -> Optional[Exception]:
|
def exception(self) -> Optional[Exception]:
|
||||||
return self._exception
|
return self._exception
|
||||||
|
|
||||||
|
@exception.setter
|
||||||
|
def exception(self, exc: Exception) -> None:
|
||||||
|
self._exception = exc
|
||||||
|
|
||||||
def __enter__(self): # type: ignore
|
def __enter__(self): # type: ignore
|
||||||
self.start()
|
self.start()
|
||||||
self.wait()
|
self.wait()
|
||||||
|
Loading…
Reference in New Issue
Block a user