Better error handling
This commit is contained in:
parent
a559e92d3e
commit
c15681a51c
|
@ -5,6 +5,7 @@ import time
|
|||
import logging
|
||||
import re
|
||||
import os
|
||||
import shutil
|
||||
|
||||
SECOND = 1
|
||||
MINUTE = 60 * SECOND
|
||||
|
@ -154,7 +155,7 @@ def encode(state, directory):
|
|||
|
||||
|
||||
def clean(state, directory):
|
||||
os.removedirs(directory)
|
||||
shutil.rmtree(directory)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import pprint
|
||||
|
|
|
@ -12,30 +12,22 @@ import re
|
|||
import logging
|
||||
import dvd
|
||||
import cd
|
||||
import traceback
|
||||
import worker
|
||||
|
||||
class Encoder(worker.Worker):
|
||||
def __init__(self, directory=None):
|
||||
self.status = {}
|
||||
self.directory = directory
|
||||
self.loop_delay = 12
|
||||
return super().__init__(directory)
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
def once(self):
|
||||
wait = True
|
||||
self.status = {"type": "encoder", "state": "idle"}
|
||||
self.status["type"] = "encoder"
|
||||
for fn in glob.glob(self.workdir("*", "sucker.json")):
|
||||
directory = os.path.dirname(fn)
|
||||
state = self.read_state(directory)
|
||||
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):
|
||||
self.status["state"] = "encoding"
|
||||
|
|
|
@ -5,7 +5,6 @@ import subprocess
|
|||
import time
|
||||
import re
|
||||
import fcntl
|
||||
import traceback
|
||||
import json
|
||||
import logging
|
||||
import slugify
|
||||
|
@ -29,57 +28,54 @@ CDS_DATA_2 = 102
|
|||
CDROM_LOCKDOOR = 0x5329
|
||||
CDROM_EJECT = 0x5309
|
||||
|
||||
SECOND = 1
|
||||
MINUTE = 60 * SECOND
|
||||
HOUR = 60 * MINUTE
|
||||
|
||||
class Reader(worker.Worker):
|
||||
def __init__(self, device, directory):
|
||||
super().__init__(directory)
|
||||
self.device = device
|
||||
self.status["type"] = "reader"
|
||||
self.status["device"] = device
|
||||
self.complete = 0
|
||||
self.staleness = 0
|
||||
self.drive = None
|
||||
logging.info("Starting reader on %s" % self.device)
|
||||
|
||||
def reopen(self):
|
||||
if (self.staleness > 15) or not self.drive:
|
||||
if self.drive and (self.staleness < 15):
|
||||
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:
|
||||
pass
|
||||
self.staleness = 0
|
||||
else:
|
||||
self.staleness += 1
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
self.status["state"] = "idle"
|
||||
self.reopen()
|
||||
if not self.drive:
|
||||
time.sleep(30)
|
||||
continue
|
||||
def once(self):
|
||||
self.status["type"] = "reader"
|
||||
self.status["device"] = self.device
|
||||
if not self.reopen():
|
||||
time.sleep(10 * SECOND)
|
||||
return
|
||||
rv = fcntl.ioctl(self.drive, CDROM_DRIVE_STATUS)
|
||||
if rv == CDS_DISC_OK:
|
||||
rv = fcntl.ioctl(self.drive, CDROM_DISC_STATUS)
|
||||
try:
|
||||
if rv == CDS_AUDIO:
|
||||
self.handle(False)
|
||||
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)
|
||||
time.sleep(3 * SECOND)
|
||||
else:
|
||||
logging.info("CDROM_DRIVE_STATUS: %d (%s)" % (rv, CDS_STR[rv]))
|
||||
time.sleep(3)
|
||||
time.sleep(3 * SECOND)
|
||||
|
||||
def eject(self):
|
||||
for i in range(20):
|
||||
|
|
|
@ -10,14 +10,20 @@ import reader, encoder, statuser
|
|||
class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
|
||||
def __init__(self, r, a, s, directory, statuser):
|
||||
self.statuser = statuser
|
||||
self.quiet = False
|
||||
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):
|
||||
if self.path == "/status.json":
|
||||
return self.get_status()
|
||||
return super().do_GET()
|
||||
|
||||
def get_status(self):
|
||||
self.quiet = True
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
buf = self.statuser.json().encode("utf-8")
|
||||
|
|
|
@ -2,17 +2,34 @@ import threading
|
|||
import os
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
import traceback
|
||||
|
||||
SECOND = 1
|
||||
MINUTE = 60 * SECOND
|
||||
HOUR = 60 * MINUTE
|
||||
|
||||
class Worker(threading.Thread):
|
||||
def __init__(self, directory, **kwargs):
|
||||
self.directory = directory
|
||||
self.status = {
|
||||
"state": "idle",
|
||||
}
|
||||
self.loop_delay = 2 * SECOND
|
||||
self.status = {}
|
||||
|
||||
kwargs["daemon"] = True
|
||||
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):
|
||||
return os.path.join(self.directory, *path)
|
||||
|
||||
|
@ -25,8 +42,14 @@ class Worker(threading.Thread):
|
|||
os.rename(newstatefn, statefn)
|
||||
|
||||
def read_state(self, subdir):
|
||||
try:
|
||||
with open(self.workdir(subdir, "sucker.json")) as f:
|
||||
return json.load(f)
|
||||
except FileNotFoundError:
|
||||
return {}
|
||||
|
||||
def clear_state(self, subdir):
|
||||
try:
|
||||
os.unlink(self.workdir(subdir, "sucker.json"))
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue