Better error handling

This commit is contained in:
Neale Pickett 2022-09-02 17:04:07 -06:00
parent a559e92d3e
commit c15681a51c
5 changed files with 83 additions and 65 deletions

View File

@ -5,6 +5,7 @@ import time
import logging import logging
import re import re
import os import os
import shutil
SECOND = 1 SECOND = 1
MINUTE = 60 * SECOND MINUTE = 60 * SECOND
@ -154,7 +155,7 @@ def encode(state, directory):
def clean(state, directory): def clean(state, directory):
os.removedirs(directory) shutil.rmtree(directory)
if __name__ == "__main__": if __name__ == "__main__":
import pprint import pprint

View File

@ -12,30 +12,22 @@ import re
import logging import logging
import dvd import dvd
import cd import cd
import traceback
import worker import worker
class Encoder(worker.Worker): class Encoder(worker.Worker):
def __init__(self, directory=None): def __init__(self, directory=None):
self.status = {} self.status = {}
self.directory = directory self.directory = directory
self.loop_delay = 12
return super().__init__(directory) return super().__init__(directory)
def run(self): def once(self):
while True: wait = True
wait = True self.status["type"] = "encoder"
self.status = {"type": "encoder", "state": "idle"} for fn in glob.glob(self.workdir("*", "sucker.json")):
for fn in glob.glob(self.workdir("*", "sucker.json")): directory = os.path.dirname(fn)
directory = os.path.dirname(fn) state = self.read_state(directory)
state = self.read_state(directory) self.encode(directory, state)
try:
self.encode(directory, state)
except Exception as e:
logging.error("Error encoding %s: %s" % (directory, e))
logging.error(traceback.format_exc())
wait = False
if wait:
time.sleep(12)
def encode(self, directory, state): def encode(self, directory, state):
self.status["state"] = "encoding" self.status["state"] = "encoding"

View File

@ -5,7 +5,6 @@ import subprocess
import time import time
import re import re
import fcntl import fcntl
import traceback
import json import json
import logging import logging
import slugify import slugify
@ -29,58 +28,55 @@ CDS_DATA_2 = 102
CDROM_LOCKDOOR = 0x5329 CDROM_LOCKDOOR = 0x5329
CDROM_EJECT = 0x5309 CDROM_EJECT = 0x5309
SECOND = 1
MINUTE = 60 * SECOND
HOUR = 60 * MINUTE
class Reader(worker.Worker): class Reader(worker.Worker):
def __init__(self, device, directory): def __init__(self, device, directory):
super().__init__(directory) super().__init__(directory)
self.device = device self.device = device
self.status["type"] = "reader"
self.status["device"] = device
self.complete = 0
self.staleness = 0 self.staleness = 0
self.drive = None self.drive = None
logging.info("Starting reader on %s" % self.device) logging.info("Starting reader on %s" % self.device)
def reopen(self): def reopen(self):
if (self.staleness > 15) or not self.drive: if self.drive and (self.staleness < 15):
if self.drive:
os.close(self.drive)
self.drive = None
try:
self.drive = os.open(self.device, os.O_RDONLY | os.O_NONBLOCK)
logging.debug("Reopened %s" % self.device)
except FileNotFoundError:
pass
self.staleness = 0
else:
self.staleness += 1 self.staleness += 1
return True
self.staleness = 0
if self.drive:
os.close(self.drive)
self.drive = None
try:
self.drive = os.open(self.device, os.O_RDONLY | os.O_NONBLOCK)
logging.debug("Reopened %s" % self.device)
return True
except FileNotFoundError:
return False
def run(self): def once(self):
while True: self.status["type"] = "reader"
self.status["state"] = "idle" self.status["device"] = self.device
self.reopen() if not self.reopen():
if not self.drive: time.sleep(10 * SECOND)
time.sleep(30) return
continue rv = fcntl.ioctl(self.drive, CDROM_DRIVE_STATUS)
rv = fcntl.ioctl(self.drive, CDROM_DRIVE_STATUS) if rv == CDS_DISC_OK:
if rv == CDS_DISC_OK: rv = fcntl.ioctl(self.drive, CDROM_DISC_STATUS)
rv = fcntl.ioctl(self.drive, CDROM_DISC_STATUS) if rv == CDS_AUDIO:
try: self.handle(False)
if rv == CDS_AUDIO: elif rv in [CDS_DATA_1, CDS_DATA_2]:
self.handle(False) self.handle(True)
elif rv in [CDS_DATA_1, CDS_DATA_2]:
self.handle(True)
else:
logging.info("Can't handle disc type %d" % rv)
except Exception as e:
logging.error("Error in disc handler: %s" % e)
logging.error(traceback.format_exc())
self.eject()
elif rv in (CDS_TRAY_OPEN, CDS_NO_DISC, CDS_DRIVE_NOT_READ):
time.sleep(3)
else: else:
logging.info("CDROM_DRIVE_STATUS: %d (%s)" % (rv, CDS_STR[rv])) logging.info("Can't handle disc type %d" % rv)
time.sleep(3) self.eject()
elif rv in (CDS_TRAY_OPEN, CDS_NO_DISC, CDS_DRIVE_NOT_READ):
time.sleep(3 * SECOND)
else:
logging.info("CDROM_DRIVE_STATUS: %d (%s)" % (rv, CDS_STR[rv]))
time.sleep(3 * SECOND)
def eject(self): def eject(self):
for i in range(20): for i in range(20):
try: try:

View File

@ -10,14 +10,20 @@ import reader, encoder, statuser
class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler): class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def __init__(self, r, a, s, directory, statuser): def __init__(self, r, a, s, directory, statuser):
self.statuser = statuser self.statuser = statuser
self.quiet = False
super().__init__(r, a, s, directory=directory) super().__init__(r, a, s, directory=directory)
def log_request(self, code="-", size="-"):
if not self.quiet:
super().log_request(code, size)
def do_GET(self): def do_GET(self):
if self.path == "/status.json": if self.path == "/status.json":
return self.get_status() return self.get_status()
return super().do_GET() return super().do_GET()
def get_status(self): def get_status(self):
self.quiet = True
self.send_response(200) self.send_response(200)
self.end_headers() self.end_headers()
buf = self.statuser.json().encode("utf-8") buf = self.statuser.json().encode("utf-8")

View File

@ -2,17 +2,34 @@ import threading
import os import os
import json import json
import logging import logging
import time
import traceback
SECOND = 1
MINUTE = 60 * SECOND
HOUR = 60 * MINUTE
class Worker(threading.Thread): class Worker(threading.Thread):
def __init__(self, directory, **kwargs): def __init__(self, directory, **kwargs):
self.directory = directory self.directory = directory
self.status = { self.loop_delay = 2 * SECOND
"state": "idle", self.status = {}
}
kwargs["daemon"] = True kwargs["daemon"] = True
return super().__init__(**kwargs) return super().__init__(**kwargs)
def run(self):
while True:
self.status = {"state": "idle"}
try:
self.once()
except Exception as exc:
self.status["state"] = "error"
for line in traceback.format_exception(exc):
logging.error(line)
time.sleep(30 * SECOND)
time.sleep(self.loop_delay)
def workdir(self, *path): def workdir(self, *path):
return os.path.join(self.directory, *path) return os.path.join(self.directory, *path)
@ -25,8 +42,14 @@ class Worker(threading.Thread):
os.rename(newstatefn, statefn) os.rename(newstatefn, statefn)
def read_state(self, subdir): def read_state(self, subdir):
with open(self.workdir(subdir, "sucker.json")) as f: try:
return json.load(f) with open(self.workdir(subdir, "sucker.json")) as f:
return json.load(f)
except FileNotFoundError:
return {}
def clear_state(self, subdir): def clear_state(self, subdir):
os.unlink(self.workdir(subdir, "sucker.json")) try:
os.unlink(self.workdir(subdir, "sucker.json"))
except FileNotFoundError:
pass