Mercurial > piecrust2
diff foodtruck/pubutil.py @ 613:e2e955a3bb25
publish: Add publish command.
* Add `shell` publisher.
* Refactor admin panel's publishing backend to use that, along with the new
PID file support.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 04 Feb 2016 08:05:03 -0800 |
parents | 978d8bca9fb3 |
children | cbb170d9c894 |
line wrap: on
line diff
--- a/foodtruck/pubutil.py Thu Feb 04 08:03:52 2016 -0800 +++ b/foodtruck/pubutil.py Thu Feb 04 08:05:03 2016 -0800 @@ -1,6 +1,7 @@ import os import os.path import time +import errno import signal import logging from .web import app @@ -27,9 +28,37 @@ lambda *args: _shutdown_server_and_raise_sigint()) +def _pid_exists(pid): + try: + os.kill(pid, 0) + except OSError as ex: + if ex.errno == errno.ESRCH: + # No such process. + return False + elif ex.errno == errno.EPERM: + # No permission, so process exists. + return True + else: + raise + else: + return True + + +def _read_pid_file(pid_file): + logger.debug("Reading PID file: %s" % pid_file) + try: + with open(pid_file, 'r') as fp: + pid_str = fp.read() + + return int(pid_str.strip()) + except Exception: + logger.error("Error reading PID file.") + raise + + class PublishLogReader(object): _pub_max_time = 10 * 60 # Don't bother about pubs older than 10mins. - _poll_interval = 1 # Check the PID file every 1 seconds. + _poll_interval = 1 # Check the process every 1 seconds. _ping_interval = 30 # Send a ping message every 30 seconds. def __init__(self, pid_path, log_path): @@ -41,7 +70,8 @@ def run(self): logger.debug("Opening publish log...") - + pid = None + is_running = False try: while not server_shutdown: # PING! @@ -51,19 +81,38 @@ self._last_ping_time = time.time() yield bytes("event: ping\ndata: 1\n\n", 'utf8') - # Check pid file. - prev_mtime = self._pub_pid_mtime + # Check if the PID file has changed. try: - self._pub_pid_mtime = os.path.getmtime(self.pid_path) - if time.time() - self._pub_pid_mtime > \ - self._pub_max_time: - self._pub_pid_mtime = 0 + new_mtime = os.path.getmtime(self.pid_path) except OSError: - self._pub_pid_mtime = 0 + new_mtime = 0 + + if (new_mtime > 0 and + time.time() - new_mtime > self._pub_max_time): + new_mtime = 0 + + # Re-read the PID file. + prev_mtime = self._pub_pid_mtime + if new_mtime > 0 and new_mtime != prev_mtime: + self._pub_pid_mtime = new_mtime + pid = _read_pid_file(self.pid_path) + if pid: + logger.debug("Monitoring new process, PID: %d" % pid) + + was_running = is_running + if pid: + is_running = _pid_exists(pid) + logger.debug( + "Process %d is %s" % + (pid, 'running' if is_running else 'not running')) + if not is_running: + pid = None + else: + is_running = False # Send data. new_data = None - if self._pub_pid_mtime > 0 or prev_mtime > 0: + if is_running or was_running: if self._last_seek < 0: outstr = 'event: message\ndata: Publish started.\n\n' yield bytes(outstr, 'utf8') @@ -76,11 +125,11 @@ self._last_seek = fp.tell() except OSError: pass - if self._pub_pid_mtime == 0: + if not is_running: self._last_seek = 0 if new_data: - logger.debug("SSE: %s" % outstr) + logger.debug("SSE: %s" % new_data) for line in new_data.split('\n'): outstr = 'event: message\ndata: %s\n\n' % line yield bytes(outstr, 'utf8')