Commit 8b650902 authored by David Trattnig's avatar David Trattnig
Browse files

Synchronized boot and graceful shutdown.

parent e7c2495c
......@@ -25,20 +25,19 @@
import os
import sys
import meta
import signal
import logging
import unittest
import meta
import subprocess
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
# from sqlalchemy.ext.declarative import declarative_base
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from modules.base.logger import AuraLogger
from modules.base.config import AuraConfig
from modules.base.utils import EngineUtil
from modules.base.utils import SimpleUtil
# from modules.monitoring.diskspace_watcher import DiskSpaceWatcher
config = AuraConfig()
def configure_flask():
......@@ -50,13 +49,16 @@ def configure_flask():
app = Flask(__name__)
configure_flask()
DB = SQLAlchemy(app)
# Base = declarative_base()
class Aura:
class AuraEngine:
"""
Aura Class
AuraEngine does the following:
1. Initialize the soundsystem and scheduler
2. Initialize Redis
3. Start Liquidsoap in a separate thread which connects to the engine
The core of Aura Engine.
"""
logger = None
config = None
......@@ -64,11 +66,12 @@ class Aura:
messenger = None
controller = None
scheduler = None
lqs = None
def __init__(self):
"""
Initializes the Engine Core.
Initializes Engine Core.
"""
self.config = config
AuraLogger(self.config)
......@@ -77,7 +80,7 @@ class Aura:
def startup(self):
"""
Starts the Engine Core.
Starts Engine Core.
"""
from modules.scheduling.scheduler import AuraScheduler
from modules.core.engine import SoundSystem
......@@ -85,38 +88,58 @@ class Aura:
# Check if the database has to be re-created
if self.config.get("recreate_db") is not None:
AuraScheduler(self.config, None)
AuraScheduler(self.config, None, None)
# Create scheduler and Liquidsoap communicator
self.soundsystem = SoundSystem(self.config)
self.scheduler = AuraScheduler(self.config, self.soundsystem)
self.scheduler = AuraScheduler(self.config, self.soundsystem, self.on_initialized)
# Create the Redis adapter
self.messenger = ServerRedisAdapter(self.config)
self.messenger.scheduler = self.scheduler
self.messenger.soundsystem = self.soundsystem
# TODO Check if it's working / needed.
#self.diskspace_watcher = DiskSpaceWatcher(self.config, self.logger, self.soundsystem)
#self.diskspace_watcher.start()
# And finally wait for redis message / start listener thread
self.messenger.start()
def on_initialized(self):
"""
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)
def exit_gracefully(self, signum, frame):
"""
Shutdown of the engine. Also terminates the liquidsoap thread.
"""
self.lqs.terminate()
self.logger.info("Gracefully terminated Aura Engine!" + str(self.lqs))
#
# START THE ENGINE
#
if __name__ == "__main__":
aura = Aura()
if __name__ == "__main__":
engine = AuraEngine()
signal.signal(signal.SIGINT, engine.exit_gracefully)
signal.signal(signal.SIGTERM, engine.exit_gracefully)
if len(sys.argv) >= 2:
if "--use-test-data" in sys.argv:
aura.config.set("use_test_data", True)
engine.config.set("use_test_data", True)
if "--recreate-database" in sys.argv:
aura.config.set("recreate_db", True)
engine.config.set("recreate_db", True)
aura.startup()
engine.startup()
......@@ -121,7 +121,7 @@ class SoundSystem(ExceptionLogger):
def is_ready(self):
"""
Returns `True` if the soundsystem is ready to be used.
Returns `True` if the soundsystem is connected to Liquidsoap and is ready to be used.
"""
return self.is_liquidsoap_running
......
......@@ -90,15 +90,17 @@ class AuraScheduler(ExceptionLogger, threading.Thread):
message_timer = []
fallback_manager = None
client = None
is_initialized = None
def __init__(self, config, soundsystem):
def __init__(self, config, soundsystem, func_on_init):
"""
Constructor
Args:
config (AuraConfig): Reads the engine configuration
config (AuraConfig): Reads the engine configuration
soundsystem (SoundSystem): The soundsystem to play the schedule on
func_on_init (Function): The function to be called when the scheduler is initialized
"""
self.config = config
self.logger = logging.getLogger("AuraEngine")
......@@ -109,7 +111,11 @@ class AuraScheduler(ExceptionLogger, threading.Thread):
self.redismessenger = RedisMessenger(config)
self.soundsystem = soundsystem
self.soundsystem.scheduler = self
# Scheduler Initialization
self.is_initialized = False
self.func_on_initialized = func_on_init
# init threading
threading.Thread.__init__(self)
......@@ -138,6 +144,13 @@ class AuraScheduler(ExceptionLogger, threading.Thread):
self.logger.info("Fetch new programmes every %ss. Next fetching in %ss." % (str(seconds_to_wait), str(next_time)))
self.fetch_new_programme()
# The Scheduler is ready
if not self.is_initialized:
self.is_initialized = True
if self.func_on_initialized:
self.func_on_initialized()
# The SoundSystem is ready
if self.soundsystem.is_ready():
self.queue_programme()
......@@ -146,6 +159,7 @@ class AuraScheduler(ExceptionLogger, threading.Thread):
#
# PUBLIC METHODS
#
......
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