Refactored WSGIServer handling
Restart of gevent server now working
This commit is contained in:
parent
a298470479
commit
404b29b979
44
cps.py
44
cps.py
|
@ -10,44 +10,12 @@ sys.path.append(base_path)
|
||||||
sys.path.append(os.path.join(base_path, 'cps'))
|
sys.path.append(os.path.join(base_path, 'cps'))
|
||||||
sys.path.append(os.path.join(base_path, 'vendor'))
|
sys.path.append(os.path.join(base_path, 'vendor'))
|
||||||
|
|
||||||
from cps import web
|
from cps.server import Server
|
||||||
try:
|
|
||||||
from gevent.pywsgi import WSGIServer
|
|
||||||
gevent_present = True
|
|
||||||
except ImportError:
|
|
||||||
from tornado.wsgi import WSGIContainer
|
|
||||||
from tornado.httpserver import HTTPServer
|
|
||||||
from tornado.ioloop import IOLoop
|
|
||||||
gevent_present = False
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if gevent_present:
|
Server.startServer()
|
||||||
web.app.logger.info('Attempting to start gevent')
|
|
||||||
web.start_gevent()
|
|
||||||
else:
|
|
||||||
web.app.logger.info('Starting Tornado webserver')
|
|
||||||
# Max Buffersize set to 200MB
|
|
||||||
if web.ub.config.get_config_certfile() and web.ub.config.get_config_keyfile():
|
|
||||||
ssl={"certfile": web.ub.config.get_config_certfile(),
|
|
||||||
"keyfile": web.ub.config.get_config_keyfile()}
|
|
||||||
else:
|
|
||||||
ssl=None
|
|
||||||
http_server = HTTPServer(WSGIContainer(web.app),
|
|
||||||
max_buffer_size = 209700000,
|
|
||||||
ssl_options=ssl)
|
|
||||||
http_server.listen(web.ub.config.config_port)
|
|
||||||
IOLoop.instance().start()
|
|
||||||
IOLoop.instance().close(True)
|
|
||||||
|
|
||||||
if web.helper.global_task == 0:
|
|
||||||
web.app.logger.info("Performing restart of Calibre-web")
|
|
||||||
if os.name == 'nt':
|
|
||||||
arguments = ["\"" + sys.executable + "\""]
|
|
||||||
for e in sys.argv:
|
|
||||||
arguments.append("\"" + e + "\"")
|
|
||||||
os.execv(sys.executable, arguments)
|
|
||||||
else:
|
|
||||||
os.execl(sys.executable, sys.executable, *sys.argv)
|
|
||||||
else:
|
|
||||||
web.app.logger.info("Performing shutdown of Calibre-web")
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
|
@ -36,12 +36,12 @@ import threading
|
||||||
import shutil
|
import shutil
|
||||||
import requests
|
import requests
|
||||||
import zipfile
|
import zipfile
|
||||||
from tornado.ioloop import IOLoop
|
|
||||||
try:
|
try:
|
||||||
import gdriveutils as gd
|
import gdriveutils as gd
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
import web
|
import web
|
||||||
|
import server
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import unidecode
|
import unidecode
|
||||||
|
@ -50,7 +50,6 @@ except ImportError:
|
||||||
use_unidecode = False
|
use_unidecode = False
|
||||||
|
|
||||||
# Global variables
|
# Global variables
|
||||||
global_task = None
|
|
||||||
updater_thread = None
|
updater_thread = None
|
||||||
|
|
||||||
RET_SUCCESS = 1
|
RET_SUCCESS = 1
|
||||||
|
@ -388,7 +387,6 @@ class Updater(threading.Thread):
|
||||||
self.status = 0
|
self.status = 0
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
global global_task
|
|
||||||
self.status = 1
|
self.status = 1
|
||||||
r = requests.get('https://api.github.com/repos/janeczku/calibre-web/zipball/master', stream=True)
|
r = requests.get('https://api.github.com/repos/janeczku/calibre-web/zipball/master', stream=True)
|
||||||
fname = re.findall("filename=(.+)", r.headers['content-disposition'])[0]
|
fname = re.findall("filename=(.+)", r.headers['content-disposition'])[0]
|
||||||
|
@ -400,19 +398,13 @@ class Updater(threading.Thread):
|
||||||
self.status = 4
|
self.status = 4
|
||||||
self.update_source(os.path.join(tmp_dir, os.path.splitext(fname)[0]), ub.config.get_main_dir)
|
self.update_source(os.path.join(tmp_dir, os.path.splitext(fname)[0]), ub.config.get_main_dir)
|
||||||
self.status = 5
|
self.status = 5
|
||||||
global_task = 0
|
|
||||||
db.session.close()
|
db.session.close()
|
||||||
db.engine.dispose()
|
db.engine.dispose()
|
||||||
ub.session.close()
|
ub.session.close()
|
||||||
ub.engine.dispose()
|
ub.engine.dispose()
|
||||||
self.status = 6
|
self.status = 6
|
||||||
|
server.Server.setRestartTyp(True)
|
||||||
if web.gevent_server:
|
server.Server.stopServer()
|
||||||
web.gevent_server.stop()
|
|
||||||
else:
|
|
||||||
# stop tornado server
|
|
||||||
server = IOLoop.instance()
|
|
||||||
server.add_callback(server.stop)
|
|
||||||
self.status = 7
|
self.status = 7
|
||||||
|
|
||||||
def get_update_status(self):
|
def get_update_status(self):
|
||||||
|
|
103
cps/server.py
Normal file
103
cps/server.py
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
from socket import error as SocketError
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
try:
|
||||||
|
from gevent.pywsgi import WSGIServer
|
||||||
|
from gevent import monkey
|
||||||
|
from gevent.pool import Pool
|
||||||
|
from gevent import __version__ as geventVersion
|
||||||
|
gevent_present = True
|
||||||
|
except ImportError:
|
||||||
|
from tornado.wsgi import WSGIContainer
|
||||||
|
from tornado.httpserver import HTTPServer
|
||||||
|
from tornado.ioloop import IOLoop
|
||||||
|
from tornado import version as tornadoVersion
|
||||||
|
gevent_present = False
|
||||||
|
|
||||||
|
import web
|
||||||
|
|
||||||
|
|
||||||
|
class server:
|
||||||
|
|
||||||
|
wsgiserver = None
|
||||||
|
restart= False
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def start_gevent(self):
|
||||||
|
try:
|
||||||
|
ssl_args = dict()
|
||||||
|
if web.ub.config.get_config_certfile() and web.ub.config.get_config_keyfile():
|
||||||
|
ssl_args = {"certfile": web.ub.config.get_config_certfile(),
|
||||||
|
"keyfile": web.ub.config.get_config_keyfile()}
|
||||||
|
if os.name == 'nt':
|
||||||
|
self.wsgiserver= WSGIServer(('0.0.0.0', web.ub.config.config_port), web.app, spawn=Pool(), **ssl_args)
|
||||||
|
else:
|
||||||
|
self.wsgiserver = WSGIServer(('', web.ub.config.config_port), web.app, spawn=Pool(), **ssl_args)
|
||||||
|
self.wsgiserver.serve_forever()
|
||||||
|
|
||||||
|
except SocketError:
|
||||||
|
web.app.logger.info('Unable to listen on \'\', trying on IPv4 only...')
|
||||||
|
self.wsgiserver = WSGIServer(('0.0.0.0', web.ub.config.config_port), web.app, spawn=Pool(), **ssl_args)
|
||||||
|
self.wsgiserver.serve_forever()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def startServer(self):
|
||||||
|
if gevent_present:
|
||||||
|
web.app.logger.info('Starting Gevent server')
|
||||||
|
# leave subprocess out to allow forking for fetchers and processors
|
||||||
|
monkey.patch_all(subprocess=False)
|
||||||
|
self.start_gevent()
|
||||||
|
else:
|
||||||
|
web.app.logger.info('Starting Tornado server')
|
||||||
|
if web.ub.config.get_config_certfile() and web.ub.config.get_config_keyfile():
|
||||||
|
ssl={"certfile": web.ub.config.get_config_certfile(),
|
||||||
|
"keyfile": web.ub.config.get_config_keyfile()}
|
||||||
|
else:
|
||||||
|
ssl=None
|
||||||
|
# Max Buffersize set to 200MB
|
||||||
|
http_server = HTTPServer(WSGIContainer(web.app),
|
||||||
|
max_buffer_size = 209700000,
|
||||||
|
ssl_options=ssl)
|
||||||
|
http_server.listen(web.ub.config.config_port)
|
||||||
|
self.wsgiserver=IOLoop.instance()
|
||||||
|
self.wsgiserver.start() # wait for stop signal
|
||||||
|
self.wsgiserver.close(True)
|
||||||
|
|
||||||
|
if self.restart == True:
|
||||||
|
web.app.logger.info("Performing restart of Calibre-web")
|
||||||
|
if os.name == 'nt':
|
||||||
|
arguments = ["\"" + sys.executable + "\""]
|
||||||
|
for e in sys.argv:
|
||||||
|
arguments.append("\"" + e + "\"")
|
||||||
|
os.execv(sys.executable, arguments)
|
||||||
|
else:
|
||||||
|
os.execl(sys.executable, sys.executable, *sys.argv)
|
||||||
|
else:
|
||||||
|
web.app.logger.info("Performing shutdown of Calibre-web")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def setRestartTyp(self,starttyp):
|
||||||
|
self.restart=starttyp
|
||||||
|
|
||||||
|
def stopServer(self):
|
||||||
|
if gevent_present:
|
||||||
|
self.wsgiserver.close()
|
||||||
|
else:
|
||||||
|
self.wsgiserver.add_callback(self.wsgiserver.stop)
|
||||||
|
|
||||||
|
def getNameVersion(self):
|
||||||
|
if gevent_present:
|
||||||
|
return {'gevent':geventVersion}
|
||||||
|
else:
|
||||||
|
return {'tornado':tornadoVersion}
|
||||||
|
|
||||||
|
|
||||||
|
# Start Instance of Server
|
||||||
|
Server=server()
|
|
@ -38,6 +38,18 @@
|
||||||
<th>Python</th>
|
<th>Python</th>
|
||||||
<td>{{versions['PythonVersion']}}</td>
|
<td>{{versions['PythonVersion']}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% if 'tornado' in versions %}
|
||||||
|
<tr>
|
||||||
|
<th>Tornado web server</th>
|
||||||
|
<td>v{{versions['tornado']}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'gevent' in versions %}
|
||||||
|
<tr>
|
||||||
|
<th>Gevent web server</th>
|
||||||
|
<td>v{{versions['gevent']}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<th>Kindlegen</th>
|
<th>Kindlegen</th>
|
||||||
<td>{{versions['KindlegenVersion']}}</td>
|
<td>{{versions['KindlegenVersion']}}</td>
|
||||||
|
@ -70,10 +82,6 @@
|
||||||
<th>Flask Principal</th>
|
<th>Flask Principal</th>
|
||||||
<td>v{{versions['flask_principal']}}</td>
|
<td>v{{versions['flask_principal']}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<th>Tornado web server</th>
|
|
||||||
<td>v{{versions['tornado']}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>ISO639 Languages</th>
|
<th>ISO639 Languages</th>
|
||||||
<td>v{{versions['iso639']}}</td>
|
<td>v{{versions['iso639']}}</td>
|
||||||
|
|
47
cps/web.py
47
cps/web.py
|
@ -71,15 +71,12 @@ import subprocess
|
||||||
import re
|
import re
|
||||||
import db
|
import db
|
||||||
from shutil import move, copyfile
|
from shutil import move, copyfile
|
||||||
from tornado.ioloop import IOLoop
|
|
||||||
import shutil
|
import shutil
|
||||||
import gdriveutils
|
import gdriveutils
|
||||||
import tempfile
|
import tempfile
|
||||||
import hashlib
|
import hashlib
|
||||||
from redirect import redirect_back, is_safe_url
|
from redirect import redirect_back, is_safe_url
|
||||||
|
|
||||||
from tornado import version as tornadoVersion
|
|
||||||
from socket import error as SocketError
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
|
@ -93,13 +90,13 @@ except ImportError:
|
||||||
from flask_login.__about__ import __version__ as flask_loginVersion
|
from flask_login.__about__ import __version__ as flask_loginVersion
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
import server
|
||||||
|
|
||||||
current_milli_time = lambda: int(round(time.time() * 1000))
|
current_milli_time = lambda: int(round(time.time() * 1000))
|
||||||
|
|
||||||
|
|
||||||
# Global variables
|
# Global variables
|
||||||
gdrive_watch_callback_token = 'target=calibreweb-watch_files'
|
gdrive_watch_callback_token = 'target=calibreweb-watch_files'
|
||||||
global_task = None
|
|
||||||
|
|
||||||
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'epub', 'mobi', 'azw', 'azw3', 'cbr', 'cbz', 'cbt', 'djvu', 'prc', 'doc', 'docx', 'fb2'])
|
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'epub', 'mobi', 'azw', 'azw3', 'cbr', 'cbz', 'cbt', 'djvu', 'prc', 'doc', 'docx', 'fb2'])
|
||||||
|
|
||||||
|
@ -218,8 +215,6 @@ app = (Flask(__name__))
|
||||||
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
||||||
cache_buster.init_cache_busting(app)
|
cache_buster.init_cache_busting(app)
|
||||||
|
|
||||||
gevent_server = None
|
|
||||||
|
|
||||||
formatter = logging.Formatter(
|
formatter = logging.Formatter(
|
||||||
"[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s")
|
"[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s")
|
||||||
file_handler = RotatingFileHandler(config.get_config_logfile(), maxBytes=50000, backupCount=2)
|
file_handler = RotatingFileHandler(config.get_config_logfile(), maxBytes=50000, backupCount=2)
|
||||||
|
@ -1471,7 +1466,8 @@ def stats():
|
||||||
versions['flask'] = flaskVersion
|
versions['flask'] = flaskVersion
|
||||||
versions['flasklogin'] = flask_loginVersion
|
versions['flasklogin'] = flask_loginVersion
|
||||||
versions['flask_principal'] = flask_principalVersion
|
versions['flask_principal'] = flask_principalVersion
|
||||||
versions['tornado'] = tornadoVersion
|
versions.update(server.Server.getNameVersion())
|
||||||
|
# versions['tornado'] = tornadoVersion
|
||||||
versions['iso639'] = iso639Version
|
versions['iso639'] = iso639Version
|
||||||
versions['requests'] = requests.__version__
|
versions['requests'] = requests.__version__
|
||||||
versions['pysqlite'] = db.engine.dialect.dbapi.version
|
versions['pysqlite'] = db.engine.dialect.dbapi.version
|
||||||
|
@ -1640,9 +1636,7 @@ def on_received_watch_confirmation():
|
||||||
@login_required
|
@login_required
|
||||||
@admin_required
|
@admin_required
|
||||||
def shutdown():
|
def shutdown():
|
||||||
# global global_task
|
|
||||||
task = int(request.args.get("parameter").strip())
|
task = int(request.args.get("parameter").strip())
|
||||||
helper.global_task = task
|
|
||||||
if task == 1 or task == 0: # valid commandos received
|
if task == 1 or task == 0: # valid commandos received
|
||||||
# close all database connections
|
# close all database connections
|
||||||
db.session.close()
|
db.session.close()
|
||||||
|
@ -1650,15 +1644,15 @@ def shutdown():
|
||||||
ub.session.close()
|
ub.session.close()
|
||||||
ub.engine.dispose()
|
ub.engine.dispose()
|
||||||
# stop gevent server
|
# stop gevent server
|
||||||
# gevent_server.stop()
|
|
||||||
# stop tornado server
|
|
||||||
server = IOLoop.instance()
|
|
||||||
server.add_callback(server.stop)
|
|
||||||
showtext = {}
|
showtext = {}
|
||||||
if task == 0:
|
if task == 0:
|
||||||
showtext['text'] = _(u'Server restarted, please reload page')
|
showtext['text'] = _(u'Server restarted, please reload page')
|
||||||
|
server.Server.setRestartTyp(True)
|
||||||
else:
|
else:
|
||||||
showtext['text'] = _(u'Performing shutdown of server, please close window')
|
showtext['text'] = _(u'Performing shutdown of server, please close window')
|
||||||
|
server.Server.setRestartTyp(False)
|
||||||
|
server.Server.stopServer()
|
||||||
return json.dumps(showtext)
|
return json.dumps(showtext)
|
||||||
else:
|
else:
|
||||||
if task == 2:
|
if task == 2:
|
||||||
|
@ -2498,7 +2492,6 @@ def basic_configuration():
|
||||||
|
|
||||||
|
|
||||||
def configuration_helper(origin):
|
def configuration_helper(origin):
|
||||||
# global global_task
|
|
||||||
reboot_required = False
|
reboot_required = False
|
||||||
gdriveError=None
|
gdriveError=None
|
||||||
db_change = False
|
db_change = False
|
||||||
|
@ -2705,10 +2698,9 @@ def configuration_helper(origin):
|
||||||
# db.engine.dispose() # ToDo verify correct
|
# db.engine.dispose() # ToDo verify correct
|
||||||
ub.session.close()
|
ub.session.close()
|
||||||
ub.engine.dispose()
|
ub.engine.dispose()
|
||||||
# stop tornado server
|
# stop Server
|
||||||
server = IOLoop.instance()
|
server.Server.setRestartTyp(True)
|
||||||
server.add_callback(server.stop)
|
server.Server.stopServer()
|
||||||
helper.global_task = 0
|
|
||||||
app.logger.info('Reboot required, restarting')
|
app.logger.info('Reboot required, restarting')
|
||||||
if origin:
|
if origin:
|
||||||
success = True
|
success = True
|
||||||
|
@ -3386,22 +3378,3 @@ def upload():
|
||||||
else:
|
else:
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
def start_gevent():
|
|
||||||
from gevent.pywsgi import WSGIServer
|
|
||||||
global gevent_server
|
|
||||||
try:
|
|
||||||
ssl_args=dict()
|
|
||||||
if ub.config.get_config_certfile() and ub.config.get_config_keyfile():
|
|
||||||
ssl_args = {"certfile": ub.config.get_config_certfile(),
|
|
||||||
"keyfile": ub.config.get_config_keyfile()}
|
|
||||||
if os.name == 'nt':
|
|
||||||
gevent_server = WSGIServer(('0.0.0.0', ub.config.config_port), app, **ssl_args)
|
|
||||||
else:
|
|
||||||
gevent_server = WSGIServer(('', ub.config.config_port), app, **ssl_args)
|
|
||||||
gevent_server.serve_forever()
|
|
||||||
except SocketError:
|
|
||||||
app.logger.info('Unable to listen on \'\', trying on IPv4 only...')
|
|
||||||
gevent_server = WSGIServer(('0.0.0.0', ub.config.config_port), app, **ssl_args)
|
|
||||||
gevent_server.serve_forever()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user