mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Retry only a fixed number of times in compiling RS fails
This commit is contained in:
parent
467f7a3273
commit
93004be1b6
@ -8,15 +8,19 @@ __copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
|
|
||||||
import os, sys, subprocess, signal, time, errno, socket
|
import os, sys, subprocess, signal, time, errno, socket
|
||||||
from threading import Thread, Lock
|
from threading import Thread, Lock
|
||||||
|
from Queue import Queue, Empty
|
||||||
|
|
||||||
from calibre.constants import islinux, iswindows, isosx
|
from calibre.constants import islinux, iswindows, isosx
|
||||||
from calibre.srv.http_response import create_http_handler
|
from calibre.srv.http_response import create_http_handler
|
||||||
from calibre.srv.loop import ServerLoop
|
from calibre.srv.loop import ServerLoop
|
||||||
from calibre.srv.opts import Options
|
from calibre.srv.opts import Options
|
||||||
from calibre.srv.standalone import create_option_parser
|
from calibre.srv.standalone import create_option_parser
|
||||||
|
from calibre.srv.utils import create_sock_pair
|
||||||
from calibre.srv.web_socket import DummyHandler
|
from calibre.srv.web_socket import DummyHandler
|
||||||
from calibre.utils.monotonic import monotonic
|
from calibre.utils.monotonic import monotonic
|
||||||
|
|
||||||
|
MAX_RETRIES = 10
|
||||||
|
|
||||||
class NoAutoReload(EnvironmentError):
|
class NoAutoReload(EnvironmentError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -45,6 +49,10 @@ class WatcherBase(object):
|
|||||||
self.worker.restart()
|
self.worker.restart()
|
||||||
self.last_restart_time = monotonic()
|
self.last_restart_time = monotonic()
|
||||||
|
|
||||||
|
def force_restart(self):
|
||||||
|
self.worker.restart(forced=True)
|
||||||
|
self.last_restart_time = monotonic()
|
||||||
|
|
||||||
def file_is_watched(self, fname):
|
def file_is_watched(self, fname):
|
||||||
return fname and fname.rpartition('.')[-1] in self.EXTENSIONS_TO_WATCH
|
return fname and fname.rpartition('.')[-1] in self.EXTENSIONS_TO_WATCH
|
||||||
|
|
||||||
@ -56,6 +64,7 @@ if islinux:
|
|||||||
|
|
||||||
def __init__(self, root_dirs, worker, log):
|
def __init__(self, root_dirs, worker, log):
|
||||||
WatcherBase.__init__(self, worker, log)
|
WatcherBase.__init__(self, worker, log)
|
||||||
|
self.client_sock, self.srv_sock = create_sock_pair()
|
||||||
self.fd_map = {}
|
self.fd_map = {}
|
||||||
for d in frozenset(root_dirs):
|
for d in frozenset(root_dirs):
|
||||||
w = INotifyTreeWatcher(d, self.ignore_event)
|
w = INotifyTreeWatcher(d, self.ignore_event)
|
||||||
@ -63,9 +72,13 @@ if islinux:
|
|||||||
|
|
||||||
def loop(self):
|
def loop(self):
|
||||||
while True:
|
while True:
|
||||||
r = select.select(list(self.fd_map.iterkeys()), [], [])[0]
|
r = select.select([self.srv_sock] + list(self.fd_map.iterkeys()), [], [])[0]
|
||||||
modified = set()
|
modified = set()
|
||||||
for fd in r:
|
for fd in r:
|
||||||
|
if fd is self.srv_sock:
|
||||||
|
self.srv_sock.recv(1000)
|
||||||
|
self.force_restart()
|
||||||
|
continue
|
||||||
w = self.fd_map[fd]
|
w = self.fd_map[fd]
|
||||||
modified |= w()
|
modified |= w()
|
||||||
self.handle_modified(modified)
|
self.handle_modified(modified)
|
||||||
@ -73,9 +86,11 @@ if islinux:
|
|||||||
def ignore_event(self, path, name):
|
def ignore_event(self, path, name):
|
||||||
return not self.file_is_watched(name)
|
return not self.file_is_watched(name)
|
||||||
|
|
||||||
|
def wakeup(self):
|
||||||
|
self.client_sock.sendall(b'w')
|
||||||
|
|
||||||
elif iswindows:
|
elif iswindows:
|
||||||
import win32file, win32con
|
import win32file, win32con
|
||||||
from Queue import Queue
|
|
||||||
FILE_LIST_DIRECTORY = 0x0001
|
FILE_LIST_DIRECTORY = 0x0001
|
||||||
from calibre.srv.utils import HandleInterrupt
|
from calibre.srv.utils import HandleInterrupt
|
||||||
|
|
||||||
@ -127,6 +142,9 @@ elif iswindows:
|
|||||||
for d in frozenset(root_dirs):
|
for d in frozenset(root_dirs):
|
||||||
self.watchers.append(TreeWatcher(d, self.modified_queue))
|
self.watchers.append(TreeWatcher(d, self.modified_queue))
|
||||||
|
|
||||||
|
def wakeup(self):
|
||||||
|
self.modified_queue.put(True)
|
||||||
|
|
||||||
def loop(self):
|
def loop(self):
|
||||||
for w in self.watchers:
|
for w in self.watchers:
|
||||||
w.start()
|
w.start()
|
||||||
@ -135,6 +153,9 @@ elif iswindows:
|
|||||||
path = self.modified_queue.get()
|
path = self.modified_queue.get()
|
||||||
if path is None:
|
if path is None:
|
||||||
break
|
break
|
||||||
|
if path is True:
|
||||||
|
self.force_restart()
|
||||||
|
else:
|
||||||
self.handle_modified({path})
|
self.handle_modified({path})
|
||||||
|
|
||||||
elif isosx:
|
elif isosx:
|
||||||
@ -145,6 +166,10 @@ elif isosx:
|
|||||||
def __init__(self, root_dirs, worker, log):
|
def __init__(self, root_dirs, worker, log):
|
||||||
WatcherBase.__init__(self, worker, log)
|
WatcherBase.__init__(self, worker, log)
|
||||||
self.stream = Stream(self.notify, *(x.encode('utf-8') for x in root_dirs), file_events=True)
|
self.stream = Stream(self.notify, *(x.encode('utf-8') for x in root_dirs), file_events=True)
|
||||||
|
self.wait_queue = Queue()
|
||||||
|
|
||||||
|
def wakeup(self):
|
||||||
|
self.wait_queue.put(True)
|
||||||
|
|
||||||
def loop(self):
|
def loop(self):
|
||||||
observer = Observer()
|
observer = Observer()
|
||||||
@ -153,9 +178,13 @@ elif isosx:
|
|||||||
observer.start()
|
observer.start()
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
# Cannot use observer.join() as it is not interrupted by
|
try:
|
||||||
|
# Cannot use blocking get() as it is not interrupted by
|
||||||
# Ctrl-C
|
# Ctrl-C
|
||||||
time.sleep(10000)
|
if self.wait_queue.get(10000) is True:
|
||||||
|
self.force_restart()
|
||||||
|
except Empty:
|
||||||
|
pass
|
||||||
finally:
|
finally:
|
||||||
observer.unschedule(self.stream)
|
observer.unschedule(self.stream)
|
||||||
observer.stop()
|
observer.stop()
|
||||||
@ -201,6 +230,7 @@ class Worker(object):
|
|||||||
self.log = log
|
self.log = log
|
||||||
self.server = server
|
self.server = server
|
||||||
self.p = None
|
self.p = None
|
||||||
|
self.wakeup = None
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
cmd = self.cmd
|
cmd = self.cmd
|
||||||
if 'calibre-debug' in cmd[0].lower():
|
if 'calibre-debug' in cmd[0].lower():
|
||||||
@ -214,6 +244,7 @@ class Worker(object):
|
|||||||
opts = create_option_parser().parse_args(cmd)[0]
|
opts = create_option_parser().parse_args(cmd)[0]
|
||||||
self.port = opts.port
|
self.port = opts.port
|
||||||
self.connection_timeout = opts.timeout
|
self.connection_timeout = opts.timeout
|
||||||
|
self.retry_count = 0
|
||||||
t = Thread(name='PingThread', target=self.ping_thread)
|
t = Thread(name='PingThread', target=self.ping_thread)
|
||||||
t.daemon = True
|
t.daemon = True
|
||||||
t.start()
|
t.start()
|
||||||
@ -241,10 +272,11 @@ class Worker(object):
|
|||||||
self.p.wait()
|
self.p.wait()
|
||||||
self.p = None
|
self.p = None
|
||||||
|
|
||||||
def restart(self):
|
def restart(self, forced=False):
|
||||||
from calibre.utils.rapydscript import compile_srv, CompileFailure
|
from calibre.utils.rapydscript import compile_srv, CompileFailure
|
||||||
self.clean_kill()
|
self.clean_kill()
|
||||||
while True:
|
if forced:
|
||||||
|
self.retry_count += 1
|
||||||
try:
|
try:
|
||||||
compile_srv()
|
compile_srv()
|
||||||
except EnvironmentError as e:
|
except EnvironmentError as e:
|
||||||
@ -257,11 +289,12 @@ class Worker(object):
|
|||||||
compile_srv()
|
compile_srv()
|
||||||
except CompileFailure as e:
|
except CompileFailure as e:
|
||||||
self.log.error(e.message)
|
self.log.error(e.message)
|
||||||
self.log('Retrying in one second')
|
time.sleep(0.1 * self.retry_count)
|
||||||
time.sleep(1)
|
if self.retry_count < MAX_RETRIES:
|
||||||
continue
|
self.wakeup() # Force a restart
|
||||||
break
|
return
|
||||||
|
|
||||||
|
self.retry_count = 0
|
||||||
self.p = subprocess.Popen(self.cmd, creationflags=getattr(subprocess, 'CREATE_NEW_PROCESS_GROUP', 0))
|
self.p = subprocess.Popen(self.cmd, creationflags=getattr(subprocess, 'CREATE_NEW_PROCESS_GROUP', 0))
|
||||||
self.wait_for_listen()
|
self.wait_for_listen()
|
||||||
self.server.notify_reload()
|
self.server.notify_reload()
|
||||||
@ -354,6 +387,7 @@ def auto_reload(log, dirs=frozenset(), cmd=None, add_default_dirs=True):
|
|||||||
log('Watching %d directory trees for changes' % len(dirs))
|
log('Watching %d directory trees for changes' % len(dirs))
|
||||||
with ReloadServer() as server, Worker(cmd, log, server) as worker:
|
with ReloadServer() as server, Worker(cmd, log, server) as worker:
|
||||||
w = Watcher(dirs, worker, log)
|
w = Watcher(dirs, worker, log)
|
||||||
|
worker.wakeup = w.wakeup
|
||||||
try:
|
try:
|
||||||
w.loop()
|
w.loop()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user