From 6cf4297ab9caa0d2dd42ba3e91bdd08039cbc52e Mon Sep 17 00:00:00 2001 From: IndigoFox Date: Fri, 14 Apr 2023 11:17:41 -0700 Subject: [PATCH] reworked the extension init/de-init logic to be asynchronous --- .../addons/RangerMetrics/config.cpp | 12 +++-- .../callbackHandlers/fn_callbackHandler.sqf | 45 +++++++++++++++++ .../callbackHandlers/fn_loadSettings.sqf | 33 ++++++++++++ .../functions/core/fn_callbackHandler.sqf | 14 ------ .../functions/core/fn_postInit.sqf | 50 +++---------------- @RangerMetrics/settings.json.example | 17 +++++-- 6 files changed, 108 insertions(+), 63 deletions(-) create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/callbackHandlers/fn_callbackHandler.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/callbackHandlers/fn_loadSettings.sqf delete mode 100644 @RangerMetrics/addons/RangerMetrics/functions/core/fn_callbackHandler.sqf diff --git a/@RangerMetrics/addons/RangerMetrics/config.cpp b/@RangerMetrics/addons/RangerMetrics/config.cpp index 366f6ba..ced4b89 100644 --- a/@RangerMetrics/addons/RangerMetrics/config.cpp +++ b/@RangerMetrics/addons/RangerMetrics/config.cpp @@ -2,7 +2,7 @@ class CfgPatches { class RangerMetrics { units[] = {}; weapons[] = {}; - requiredVersion = 0.1; + requiredVersion = 2.10; requiredAddons[] = {}; author[] = {"EagleTrooper","Gary","IndigoFox"}; authorUrl = "http://example.com"; @@ -10,6 +10,13 @@ class CfgPatches { }; class CfgFunctions { + class RangerMetrics_callback { + class functions { + file = "\RangerMetrics\functions\callbackHandlers"; + class callbackHandler {}; + class loadSettings {}; + }; + }; class RangerMetrics_event { class functions { file = "\RangerMetrics\functions\capture\EHOnly"; @@ -23,7 +30,7 @@ class CfgFunctions { class MarkerUpdated {}; class milsim_serverEfficiency {}; }; - } + }; class RangerMetrics_cDefinitions { class functions { file = "\RangerMetrics\functions\captureDefinitions"; @@ -62,7 +69,6 @@ class CfgFunctions { class log {}; class queue {}; class send {}; - class callbackHandler {}; class sendClientPoll {}; class startServerPoll {}; class classHandlers {}; diff --git a/@RangerMetrics/addons/RangerMetrics/functions/callbackHandlers/fn_callbackHandler.sqf b/@RangerMetrics/addons/RangerMetrics/functions/callbackHandlers/fn_callbackHandler.sqf new file mode 100644 index 0000000..6cafb32 --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/callbackHandlers/fn_callbackHandler.sqf @@ -0,0 +1,45 @@ +params ["_name", "_function", "_data"]; +if !(_name == "RangerMetrics") exitWith {}; + +// Validate data param +if (isNil "_data") then {_data = ""}; + +if (_data isEqualTo "") exitWith { + [ + format ["Callback empty data: %1", _function], + "WARN" + ] call RangerMetrics_fnc_log; + false; +}; + +// Parse response from string array +private "_response"; +try { + diag_log format ["Raw callback: %1: %2", _function, _data]; + _response = parseSimpleArray _data; +} catch { + [ + format ["Callback invalid data: %1: %2", _function, _data], + "WARN" + ] call RangerMetrics_fnc_log; +}; + + +switch (_function) do { + case "deinitExtension": { + diag_log format ["RangerMetrics: deinitExtension: %1", _response]; + // Our first call is deinitExtension. When we received a single "true" value, we can then run init processes for the extension connections. + if ((_response select 0) isEqualTo true) then { + "RangerMetrics" callExtension "initExtension"; + } else { + _response call RangerMetrics_fnc_log; + }; + }; + case "loadSettings": { + // Load settings + _response call RangerMetrics_callback_fnc_loadSettings; + }; + default { + _response call RangerMetrics_fnc_log; + } +} diff --git a/@RangerMetrics/addons/RangerMetrics/functions/callbackHandlers/fn_loadSettings.sqf b/@RangerMetrics/addons/RangerMetrics/functions/callbackHandlers/fn_loadSettings.sqf new file mode 100644 index 0000000..23eadb4 --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/callbackHandlers/fn_loadSettings.sqf @@ -0,0 +1,33 @@ +private _data = _this; + +switch (_data select 0) do { + case "CREATED SETTINGS": { + [ + "settings.json did not exist and has been created - you will need to update it with your own settings before the addon will initialize further.", + "ERROR" + ] call RangerMetrics_fnc_log; + }; + case "SETTINGS LOADED": { + + RangerMetrics_settings = createHashMapFromArray (_data # 1); + [ + format [ + "Settings loaded successfully from JSON. %1", + RangerMetrics_settings + ], + "INFO" + ] call RangerMetrics_fnc_log; + + // send server profile name to all clients with JIP, so HC or player reporting knows what server it's connected to + if (isServer) then { + ["RangerMetrics_serverProfileName", profileName] remoteExecCall ["setVariable", 0, true]; + RangerMetrics_serverProfileName = profileName; + }; + }; + default { + [ + _data select 0, + "INFO" + ] call RangerMetrics_fnc_log; + }; +}; \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/core/fn_callbackHandler.sqf b/@RangerMetrics/addons/RangerMetrics/functions/core/fn_callbackHandler.sqf deleted file mode 100644 index 35a5331..0000000 --- a/@RangerMetrics/addons/RangerMetrics/functions/core/fn_callbackHandler.sqf +++ /dev/null @@ -1,14 +0,0 @@ -params ["_name", "_function", "_data"]; -if (_name == "RangerMetrics") then { - if (isNil "_data") then {_data = ""}; - try { - if (_data isEqualType "") exitWith { - _data = parseSimpleArray _data; - _data call RangerMetrics_fnc_log; - }; - - diag_log format ["Callback unsupported type: %1: %2", _function, _data]; - } catch { - _data = format ["%1", _data]; - }; -}; \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/core/fn_postInit.sqf b/@RangerMetrics/addons/RangerMetrics/functions/core/fn_postInit.sqf index 6986bcf..8b2e1d8 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/core/fn_postInit.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/core/fn_postInit.sqf @@ -19,49 +19,18 @@ RangerMetrics_sendBatchHandle = scriptNull; [format ["CBA detected: %1", RangerMetrics_cbaPresent]] call RangerMetrics_fnc_log; ["Initializing v0.1"] call RangerMetrics_fnc_log; - -// load settings from extension / settings.json -private _settingsLoaded = "RangerMetrics" callExtension "loadSettings"; -// if (isNil "_settingsLoaded") exitWith { -// ["Extension not found, disabling"] call RangerMetrics_fnc_log; -// RangerMetrics_run = false; -// }; -if (_settingsLoaded isEqualTo [] || _settingsLoaded isEqualTo "") exitWith { - ["Failed to load settings, exiting", "ERROR"] call RangerMetrics_fnc_log; -}; -_settingsLoaded = parseSimpleArray (_settingsLoaded); -[format["Settings loaded: %1", _settingsLoaded]] call RangerMetrics_fnc_log; -RangerMetrics_settings = createHashMap; -RangerMetrics_settings set [ - "influxDB", - createHashMapFromArray [ - ["host", _settingsLoaded#1], - ["org", _settingsLoaded#2] - ] -]; -RangerMetrics_settings set [ - "arma3", - createHashMapFromArray [ - ["refreshRateMs", _settingsLoaded#3] - ] +// Create listener - extension calls are async, so we need to listen for the response +addMissionEventHandler [ + "ExtensionCallback", + RangerMetrics_callback_fnc_callbackHandler ]; +// Deinit to start fresh. See callback handler for the remainder of async init code +"RangerMetrics" callExtension "deinitExtension"; -// connect to DB, extension is now ready -private _dbConnection = "RangerMetrics" callExtension "connectToInflux"; -if (_dbConnection isEqualTo "") exitWith { - ["Failed to connect to InfluxDB, disabling"] call RangerMetrics_fnc_log; -}; -_response = parseSimpleArray _dbConnection; -(_response) call RangerMetrics_fnc_log; -systemChat str _response; -// send server profile name to all clients with JIP, so HC or player reporting knows what server it's connected to -if (isServer) then { - ["RangerMetrics_serverProfileName", profileName] remoteExecCall ["setVariable", 0, true]; - RangerMetrics_serverProfileName = profileName; -}; +if (true) exitWith {}; // define the metrics to capture by sideloading definition files @@ -158,10 +127,7 @@ RangerMetrics_captureDefinitions = createHashMapFromArray [ [] spawn { sleep 1; isNil { - addMissionEventHandler [ - "ExtensionCallback", - RangerMetrics_fnc_callbackHandler - ]; + // set up CBA class inits if CBA loaded call RangerMetrics_fnc_classHandlers; diff --git a/@RangerMetrics/settings.json.example b/@RangerMetrics/settings.json.example index 4a3c403..854191b 100644 --- a/@RangerMetrics/settings.json.example +++ b/@RangerMetrics/settings.json.example @@ -1,6 +1,15 @@ { - "host" : "http://INFLUX_URL:8086", - "token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXX_AUTH_TOKEN_XXXXXXXXXXXXXXXXXXXXXXXXXXX", - "org" : "ORG_NAME", - "bucket" : "BUCKET_NAME", + "influxdb": { + "host": "http://host:8086", + "token": "my-token", + "org": "ranger-metrics" + }, + "timescaledb": { + "connectionUrl": "postgresql://postgres:password@host:5432", + "databaseName": "ranger_metrics", + "description": "TimescaleDB is an open-source time-series database built on Postgres. Please leave the final section of the connection URL as 'postgres' as this is the maintenance database name. The extension will connect here first and create the database with desired name, then shift connections to the newly created database to create the schema and conduct write operations." + }, + "arma3": { + "refreshRateMs": 1000 + } } \ No newline at end of file