Handle OSErrors reading playlist, give reasons for offline

このコミットが含まれているのは:
n9k 2022-06-11 22:24:58 +00:00
コミット 667e35bf16
1個のファイルの変更32行の追加17行の削除

ファイルの表示

@ -25,11 +25,12 @@ class UnsafePath(Exception):
def get_mtime(): def get_mtime():
try: try:
mtime = os.path.getmtime(CONFIG['SEGMENT_PLAYLIST']) mtime = os.path.getmtime(CONFIG['SEGMENT_PLAYLIST'])
except FileNotFoundError as e: except OSError as e:
raise Stale from e raise Stale(f"couldn't stat playlist: {e}") from e
else: else:
if time.time() - mtime >= CONFIG['SEGMENT_PLAYLIST_STALE_THRESHOLD']: mtime_ago = time.time() - mtime
raise Stale if mtime_ago >= CONFIG['SEGMENT_PLAYLIST_STALE_THRESHOLD']:
raise Stale(f'last modified {mtime_ago:.1f}s ago')
return mtime return mtime
@ttl_cache(CONFIG['SEGMENT_PLAYLIST_CACHE_LIFETIME']) @ttl_cache(CONFIG['SEGMENT_PLAYLIST_CACHE_LIFETIME'])
@ -38,13 +39,18 @@ def get_playlist():
try: try:
mtime = get_mtime() mtime = get_mtime()
except Stale as e: except Stale as e:
raise Offline from e reason, *_ = e.args
raise Offline(f'stale playlist: {reason}') from e
else: else:
playlist = m3u8._load_from_file(CONFIG['SEGMENT_PLAYLIST']) try:
if playlist.is_endlist: playlist = m3u8._load_from_file(CONFIG['SEGMENT_PLAYLIST'])
raise Offline except OSError:
if len(playlist.segments) == 0: raise Offline(f"couldn't read playlist: {e}") from e
raise Offline else:
if playlist.is_endlist:
raise Offline('playlist ended')
if len(playlist.segments) == 0:
raise Offline('empty playlist')
return playlist, mtime return playlist, mtime
@ -79,10 +85,11 @@ def get_next_segment(uri):
async def get_segment_uris(token): async def get_segment_uris(token):
try: try:
segment = get_starting_segment() segment = get_starting_segment()
except Offline: except Offline as e:
reason, *_ = e.args
print( print(
f'[debug @ {time.time():.3f}: {token=}] ' f'[debug @ {time.time():.3f}: {token=}] '
f'stream went offline before we could find any segments' f'stream went offline before we could find any segments ({reason})'
) )
return return
@ -96,11 +103,12 @@ async def get_segment_uris(token):
while True: while True:
try: try:
next_segment = get_next_segment(segment.uri) next_segment = get_next_segment(segment.uri)
except Offline: except Offline as e:
reason, *_ = e.args
print( print(
f'[debug @ {time.time():.3f}: {token=}] ' f'[debug @ {time.time():.3f}: {token=}] '
f'stream went offline while looking for the segment ' f'stream went offline while looking for the '
f'following {uri=}' f'segment following {segment.uri!r} ({reason})'
) )
return return
else: else:
@ -110,7 +118,8 @@ async def get_segment_uris(token):
elif time.monotonic() - t0 >= CONFIG['SEGMENT_SEARCH_TIMEOUT']: elif time.monotonic() - t0 >= CONFIG['SEGMENT_SEARCH_TIMEOUT']:
print( print(
f'[debug @ {time.time():.3f}: {token=}] ' f'[debug @ {time.time():.3f}: {token=}] '
f'timed out looking for the segment following {uri=}' f'timed out looking for the segment following '
f'{segment.uri!r} '
f'(timeout={CONFIG["SEGMENT_SEARCH_TIMEOUT"]}s)' f'(timeout={CONFIG["SEGMENT_SEARCH_TIMEOUT"]}s)'
) )
return return
@ -135,7 +144,7 @@ async def segments(segment_read_hook=lambda uri: None, token=None):
unsafe_path, *_ = e.args unsafe_path, *_ = e.args
print( print(
f'[debug @ {time.time():.3f}: {token=}] ' f'[debug @ {time.time():.3f}: {token=}] '
f'segment {uri=} has unsafe {path=}' f'segment {uri=} has {unsafe_path=}'
) )
break break
@ -150,4 +159,10 @@ async def segments(segment_read_hook=lambda uri: None, token=None):
f'segment {uri=} at {path=} unexpectedly does not exist' f'segment {uri=} at {path=} unexpectedly does not exist'
) )
break break
except OSError as e:
print(
f'[debug @ {time.time():.3f}: {token=}] '
f'segment {uri=} at {path=} cannot be read: {e}'
)
break
print(f'[debug @ {time.time():.3f}: {token=}] exiting segment generator') print(f'[debug @ {time.time():.3f}: {token=}] exiting segment generator')