Commit 201f61d1 authored by David Trattnig's avatar David Trattnig
Browse files

Improved startup and shutdown.

parent 6446305c
......@@ -5,14 +5,34 @@
"version": "0.2.0",
"configurations": [
{
"name": "Aura Engine - Run",
"name": "Start Aura Engine",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/engine-core.py",
"console": "integratedTerminal"
},
{
"name": "Aura Engine API - Run",
"name": "Start Engine Core Only",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/engine-core.py",
"args": [
"--without-lqs"
],
"console": "integratedTerminal"
},
{
"name": "Start Engine LQS Only",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/engine-core.py",
"args": [
"--lqs-only"
],
"console": "integratedTerminal"
},
{
"name": "Start Engine API",
"type": "python",
"request": "launch",
"stopOnEntry": false,
......@@ -23,9 +43,6 @@
},
"args": [
"run"
],
"debugOptions": [
"RedirectOutput"
]
},
{
......
......@@ -75,7 +75,11 @@ fade_out_time="2.5"
# all these settings from here to the bottom require a restart of the liquidsoap server
# Liquidsoap execution delay; Crucial to keep things in sync
[lqs]
liquidsoap_path="/home/david/.opam/4.08.0/bin/liquidsoap"
liquidsoap_working_dir="modules/liquidsoap/"
# Liquidsoap execution delay in seconds; Crucial to keep things in sync
lqs_delay_offset=1
[user]
......
......@@ -2,7 +2,7 @@
[program:aura-engine-api]
user = engineuser
directory = /opt/aura/engine
command = /opt/aura/engine/run.sh api-prod
command = /opt/aura/engine/run.sh api
priority = 999
autostart = true
......
;/etc/supervisor/conf.d/aura-engine-lqs.conf
[program:aura-engine-lqs]
user = engineuser
directory = /opt/aura/engine
command = /opt/aura/engine/run.sh lqs
priority = 666
autostart = false
autorestart = false
stopsignal = TERM
redirect_stderr = true
stdout_logfile = /var/log/aura/engine-lqs-stdout.log
stderr_logfile = /var/log/aura/engine-lqs-error.log
\ No newline at end of file
......@@ -4,7 +4,7 @@ user = engineuser
directory = /opt/aura/engine
command = /opt/aura/engine/run.sh engine
priority = 333
priority = 666
autostart = true
autorestart = true
stopsignal = TERM
......
......@@ -6,8 +6,7 @@ After=network.target
Type=simple
User=engineuser
WorkingDirectory=/opt/Code/aura/engine
ExecStart=/opt/aura/engine/run.sh api-prod
ExecStop=/opt/aura/engine/guru.py --shutdown --quiet
ExecStart=/opt/aura/engine/run.sh api
Restart=always
[Install]
......
[Unit]
Description=Aura Engine - Liquidsoap Server
After=network.target aura-engine.service
Wants=aura-engine.service
[Service]
Type=simple
User=engineuser
ExecStart=/usr/bin/liquidsoap /opt/aura/engine/modules/liquidsoap/engine.liq
Restart=always
[Install]
WantedBy=multi-user.target
#!/usr/bin/python3.7
#!/usr/bin/env python3.7
#
# Aura Engine
......
#!/usr/bin/python3.7
#!/usr/bin/env python3.7
#
# Aura Engine
......@@ -67,6 +67,8 @@ class AuraEngine:
controller = None
scheduler = None
lqs = None
lqs_startup = None
def __init__(self):
......@@ -74,18 +76,23 @@ class AuraEngine:
Initializes Engine Core.
"""
self.config = config
AuraLogger(self.config)
self.logger = logging.getLogger("AuraEngine")
def startup(self):
def startup(self, lqs_startup):
"""
Starts Engine Core.
"""
AuraLogger(self.config)
self.logger = logging.getLogger("AuraEngine")
from modules.scheduling.scheduler import AuraScheduler
from modules.core.engine import SoundSystem
from modules.communication.redis.adapter import ServerRedisAdapter
# If Liquidsoap should be started automatically
self.lqs_startup = lqs_startup
# Check if the database has to be re-created
if self.config.get("recreate_db") is not None:
AuraScheduler(self.config, None, None)
......@@ -109,19 +116,66 @@ class AuraEngine:
Called when the engine is initialized, before the Liquidsoap connection is established."
"""
self.logger.info(SimpleUtil.green("Engine Core initialized - Waiting for Liquidsoap connection ..."))
cwd = os.getcwd()
cwd += "/modules/liquidsoap/"
command = "/home/david/.opam/4.08.0/bin/liquidsoap"
self.lqs = subprocess.Popen([command, "engine.liq"], cwd=cwd, stdout=subprocess.PIPE, shell=False)
if self.lqs_startup:
self.start_lqs(False, False)
else:
self.logger.info(SimpleUtil.yellow("Please note, Liquidsoap needs to be started manually."))
def start_lqs(self, debug_output, verbose_output):
"""
Starts Liquidsoap.
"""
lqs_path = self.config.get("liquidsoap_path")
lqs_cwd = os.getcwd() + "/" + self.config.get("liquidsoap_working_dir")
lqs_output = ""
lqs_output = self.get_debug_flags(debug_output, verbose_output)
self.lqs = subprocess.Popen([lqs_path, lqs_output, "engine.liq"], \
cwd=lqs_cwd, \
stdout=subprocess.PIPE, \
shell=False)
def get_lqs_cmd(self, debug_output, verbose_output):
"""
Returns a shell command string to start Liquidsoap
"""
lqs_path = self.config.get("liquidsoap_path")
lqs_cwd = os.getcwd() + "/" + self.config.get("liquidsoap_working_dir")
lqs_output = self.get_debug_flags(debug_output, verbose_output)
return "(cd %s && %s %s ./engine.liq)" % (lqs_cwd, lqs_path, lqs_output)
def get_debug_flags(self, debug_output, verbose_output):
"""
Build Liquidssoap debug parameters.
"""
output = ""
if debug_output:
output += "--debug "
if verbose_output:
output += "--verbose "
return output
def exit_gracefully(self, signum, frame):
"""
Shutdown of the engine. Also terminates the liquidsoap thread.
Shutdown of the engine. Also terminates the Liquidsoap thread.
"""
self.lqs.terminate()
if self.lqs:
self.lqs.terminate()
self.logger.info("Terminated Liquidsoap")
if self.messenger:
self.messenger.terminate()
self.logger.info("Gracefully terminated Aura Engine!" + str(self.lqs))
sys.exit(0)
......@@ -131,15 +185,25 @@ class AuraEngine:
if __name__ == "__main__":
engine = AuraEngine()
lqs_startup = True
lqs_cmd = False
signal.signal(signal.SIGINT, engine.exit_gracefully)
signal.signal(signal.SIGTERM, engine.exit_gracefully)
if len(sys.argv) >= 2:
if "--without-lqs" in sys.argv:
lqs_startup = False
if "--get-lqs-command" in sys.argv:
lqs_cmd = True
if "--use-test-data" in sys.argv:
engine.config.set("use_test_data", True)
if "--recreate-database" in sys.argv:
engine.config.set("recreate_db", True)
engine.startup()
if lqs_cmd:
print(engine.get_lqs_cmd(True, True))
else:
engine.startup(lqs_startup)
#!/usr/bin/python3.7
#!/usr/bin/env python3.7
#
# engine
......
......@@ -148,10 +148,7 @@ class ServerRedisAdapter(threading.Thread, RedisMessenger):
self.execute(RedisChannel.FNP_REPLY.value, self.scheduler.get_act_programme_as_string)
elif item["data"] == "shutdown":
self.shutdown_event.set()
self.scheduler.stop()
self.pubsub.close()
self.logger.info("shutdown event received. Bye bye...")
self.terminate()
elif item["data"] == "init_player":
self.execute(RedisChannel.IP_REPLY.value, self.soundsystem.init_player)
......@@ -259,6 +256,17 @@ class ServerRedisAdapter(threading.Thread, RedisMessenger):
self.logger.warning("cannot send message via REDIS: "+str(message))
def terminate(self):
"""
Called when thread is stopped or a signal to terminate is received.
"""
self.shutdown_event.set()
self.scheduler.terminate()
self.pubsub.close()
self.logger.info("Shutdown event received. Bye bye ...")
# ------------------------------------------------------------------------------------------ #
class ClientRedisAdapter(RedisMessenger):
......
......@@ -64,7 +64,7 @@ class StartupThread(threading.Thread):
except NoActiveScheduleException as e:
self.logger.info("Nothing scheduled at startup time. Please check if there are follow-up schedules.")
except Exception as e:
self.logger.error("Error while initializing the soundsystem: " + str(e))
self.logger.error(SimpleUtil.red("Error while initializing the sound-system: " + str(e)))
......@@ -798,11 +798,12 @@ class AuraScheduler(ExceptionLogger, threading.Thread):
def stop(self):
def terminate(self):
"""
Called when thread is stopped.
Called when thread is stopped or a signal to terminate is received.
"""
self.exit_event.set()
self.logger.info("Shutting down scheduler ...")
# ------------------------------------------------------------------------------------------ #
......
#/usr/bin/bash
#!/bin/bash
mode="engine"
debug="--debug"
#debug="--debug --verbose"
if [ -n "$1" ]; then
if [[ $1 =~ ^(engine|lqs|api|api-prod)$ ]]; then
mode=$1
fi
if [[ $* =~ ^(engine|core|lqs|api-dev|api)$ ]]; then
mode=$1
fi
echo "[ Run mode=$mode ]"
if [ $mode == "engine" ]; then
/usr/bin/python3.7 aura.py
### Runs Engine Core & Liquidsoap ###
if [[ $mode == "engine" ]]; then
/usr/bin/env python3.7 engine-core.py
fi
### Runs Engine Core only ###
if [[ $mode == "core" ]]; then
/usr/bin/env python3.7 engine-core.py --without-lqs
fi
if [ $mode == "lqs" ]; then
(cd modules/liquidsoap/ && liquidsoap $debug ./engine.liq)
### Runs Liquidsoap only ###
if [[ $mode == "lqs" ]]; then
lqs=$(/usr/bin/env python3.7 engine-core.py --get-lqs-command)
eval "$lqs"
fi
if [ $mode == "api" ]; then
### Runs the API Server (Development) ###
if [[ $mode == "api-dev" ]]; then
echo "Building Web Applications"
sh ./script/build-web.sh
echo "Starting API Server"
/usr/bin/python3.7 api.py
/usr/bin/env python3.7 engine-api.py
fi
if [ $mode == "api-prod" ]; then
### Runs the API Server (Production) ###
if [[ $mode == "api" ]]; then
echo "Building Web Applications"
sh ./script/build-web.sh
echo "Starting API Server"
gunicorn -c configuration/gunicorn.conf.py api:app
gunicorn -c configuration/gunicorn.conf.py engine-api:app
fi
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment