GraphQl 0.124 - Running server check

This commit is contained in:
jokob-sk
2024-11-15 20:13:03 +11:00
parent 7fae6a8cce
commit 44b18e131c
5 changed files with 83 additions and 31 deletions

View File

@@ -1260,35 +1260,66 @@ async function handleFirstLoad(callback) {
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Execute callback once app initialized // Execute callback once the app is initialized and GraphQL server is running
function callAfterAppInitialized(callback) { async function callAfterAppInitialized(callback) {
if (!isAppInitialized()) { if (!isAppInitialized() || !(await isGraphQLServerRunning())) {
setTimeout(() => { setTimeout(() => {
callAfterAppInitialized(callback) callAfterAppInitialized(callback);
}, 500); }, 500);
} else } else {
{
callback(); callback();
} }
} }
// -----------------------------------------------------------------------------
// Polling function to repeatedly check if the server is running
async function waitForGraphQLServer() {
const pollInterval = 2000; // 2 seconds between each check
let serverRunning = false;
while (!serverRunning) {
serverRunning = await isGraphQLServerRunning();
if (!serverRunning) {
console.log("GraphQL server not running, retrying in 2 seconds...");
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
}
console.log("GraphQL server is now running.");
}
// -----------------------------------------------------------------------------
// Returns 1 if running, 0 otherwise
async function isGraphQLServerRunning() {
try {
const response = await $.get('api/app_state.json?nocache=' + Date.now());
console.log("graphQLServerStarted: " + response["graphQLServerStarted"]);
setCache("graphQLServerStarted", response["graphQLServerStarted"]);
return response["graphQLServerStarted"];
} catch (error) {
console.error("Failed to check GraphQL server status:", error);
return false;
}
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Check if the code has been executed before by checking sessionStorage // Check if the code has been executed before by checking sessionStorage
function isAppInitialized() { function isAppInitialized() {
// return arraysContainSameValues(getCache("completedCalls").split(',').filter(Boolean), completedCalls_final); const completedCallsCount_final = getLangCode() == 'en_us' ? 3 : 4;
return (
// loading settings + 1 (or 2 language files if not english) + device cache. parseInt(getCache("completedCallsCount")) >= completedCallsCount_final
completedCallsCount_final = getLangCode() == 'en_us' ? 3 : 4 ; );
return (parseInt(getCache("completedCallsCount")) >= completedCallsCount_final);
} }
// Define a function that will execute the code only once // -----------------------------------------------------------------------------
// Main execution logic
async function executeOnce() { async function executeOnce() {
showSpinner(); showSpinner();
if (!isAppInitialized()) { if (!isAppInitialized()) {
try { try {
await waitForGraphQLServer(); // Wait for the server to start
await cacheDevices(); await cacheDevices();
await cacheSettings(); await cacheSettings();
await cacheStrings(); await cacheStrings();
@@ -1301,6 +1332,7 @@ async function executeOnce() {
} }
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Function to handle successful completion of an AJAX call // Function to handle successful completion of an AJAX call
const handleSuccess = (callName) => { const handleSuccess = (callName) => {

View File

@@ -66,6 +66,9 @@ def main ():
# check file permissions and fix if required # check file permissions and fix if required
filePermissions() filePermissions()
# Header + init app state
updateState("Initializing", None, None, None, 0)
# Open DB once and keep open # Open DB once and keep open
# Opening / closing DB frequently actually casues more issues # Opening / closing DB frequently actually casues more issues
db = DB() # instance of class DB db = DB() # instance of class DB
@@ -81,8 +84,7 @@ def main ():
mylog('debug', '[MAIN] Starting loop') mylog('debug', '[MAIN] Starting loop')
# Header + init app state
updateState("Initializing")
all_plugins = None all_plugins = None

View File

@@ -12,7 +12,7 @@ INSTALL_PATH="/app"
sys.path.extend([f"{INSTALL_PATH}/server"]) sys.path.extend([f"{INSTALL_PATH}/server"])
from logger import mylog from logger import mylog
from helper import get_setting_value, timeNowTZ from helper import get_setting_value, timeNowTZ, updateState
from notification import write_notification from notification import write_notification
app = Flask(__name__) app = Flask(__name__)
@@ -43,7 +43,15 @@ def start_server():
"""Function to start the GraphQL server in a background thread.""" """Function to start the GraphQL server in a background thread."""
mylog('verbose', [f'[graphql_server] Starting on port: {GRAPHQL_PORT}']) mylog('verbose', [f'[graphql_server] Starting on port: {GRAPHQL_PORT}'])
# Start the Flask app in a separate thread state = updateState("GraphQL: Starting", None, None, None, None)
thread = threading.Thread(target=lambda: app.run(host="0.0.0.0", port=GRAPHQL_PORT, debug=True, use_reloader=False))
thread.start() if state.graphQLServerStarted == 0:
# Start the Flask app in a separate thread
thread = threading.Thread(target=lambda: app.run(host="0.0.0.0", port=GRAPHQL_PORT, debug=True, use_reloader=False))
thread.start()
# updateState(newState, settingsSaved = None (timestamp), settingsImported = None (timestamp), showSpinner = False (1/0), graphQLServerStarted = False (1/0))
# update GraphQL = started
state = updateState("Process: Wait", None, None, None, 1)

View File

@@ -57,8 +57,9 @@ def get_timezone_offset():
# App state # App state
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# A class to manage the application state and to provide a frontend accessible API point # A class to manage the application state and to provide a frontend accessible API point
# To keep an existing value pass None
class app_state_class: class app_state_class:
def __init__(self, currentState, settingsSaved=None, settingsImported=None, showSpinner=False): def __init__(self, currentState, settingsSaved=None, settingsImported=None, showSpinner=False, graphQLServerStarted=0):
# json file containing the state to communicate with the frontend # json file containing the state to communicate with the frontend
stateFile = apiPath + '/app_state.json' stateFile = apiPath + '/app_state.json'
previousState = "" previousState = ""
@@ -78,19 +79,21 @@ class app_state_class:
mylog('none', [f'[app_state_class] Failed to handle app_state.json: {e}']) mylog('none', [f'[app_state_class] Failed to handle app_state.json: {e}'])
# Check if the file exists and init values # Check if the file exists and recover previous values
if previousState != "": if previousState != "":
self.settingsSaved = previousState.get("settingsSaved", 0) self.settingsSaved = previousState.get("settingsSaved", 0)
self.settingsImported = previousState.get("settingsImported", 0) self.settingsImported = previousState.get("settingsImported", 0)
self.showSpinner = previousState.get("showSpinner", False) self.showSpinner = previousState.get("showSpinner", False)
self.isNewVersion = previousState.get("isNewVersion", False) self.isNewVersion = previousState.get("isNewVersion", False)
self.isNewVersionChecked = previousState.get("isNewVersionChecked", 0) self.isNewVersionChecked = previousState.get("isNewVersionChecked", 0)
else: self.graphQLServerStarted = previousState.get("graphQLServerStarted", 0)
else: # init first time values
self.settingsSaved = 0 self.settingsSaved = 0
self.settingsImported = 0 self.settingsImported = 0
self.showSpinner = False self.showSpinner = False
self.isNewVersion = checkNewVersion() self.isNewVersion = checkNewVersion()
self.isNewVersionChecked = int(timeNow().timestamp()) self.isNewVersionChecked = int(timeNow().timestamp())
self.graphQLServerStarted = 0
# Overwrite with provided parameters if supplied # Overwrite with provided parameters if supplied
if settingsSaved is not None: if settingsSaved is not None:
@@ -99,6 +102,8 @@ class app_state_class:
self.settingsImported = settingsImported self.settingsImported = settingsImported
if showSpinner is not None: if showSpinner is not None:
self.showSpinner = showSpinner self.showSpinner = showSpinner
if graphQLServerStarted is not None:
self.graphQLServerStarted = graphQLServerStarted
# check for new version every hour and if currently not running new version # check for new version every hour and if currently not running new version
if self.isNewVersion is False and self.isNewVersionChecked + 3600 < int(timeNow().timestamp()): if self.isNewVersion is False and self.isNewVersionChecked + 3600 < int(timeNow().timestamp()):
@@ -131,9 +136,9 @@ class app_state_class:
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# method to update the state # method to update the state
def updateState(newState, settingsSaved = None, settingsImported = None, showSpinner = False): def updateState(newState, settingsSaved = None, settingsImported = None, showSpinner = False, graphQLServerStarted = None):
state = app_state_class(newState, settingsSaved, settingsImported, showSpinner) return app_state_class(newState, settingsSaved, settingsImported, showSpinner, graphQLServerStarted)
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------

View File

@@ -374,7 +374,12 @@ def importConfigs (db, all_plugins):
# Used to determine the next import # Used to determine the next import
conf.lastImportedConfFile = os.path.getmtime(config_file) conf.lastImportedConfFile = os.path.getmtime(config_file)
updateState("Config imported", conf.lastImportedConfFile, conf.lastImportedConfFile, False) # updateState(newState (text),
# settingsSaved = None (timestamp),
# settingsImported = None (timestamp),
# showSpinner = False (1/0),
# graphQLServerStarted = 1 (1/0))
updateState("Config imported", conf.lastImportedConfFile, conf.lastImportedConfFile, False, 1)
msg = '[Config] Imported new settings config' msg = '[Config] Imported new settings config'
mylog('minimal', msg) mylog('minimal', msg)