From 9663a1360dab7149cb518cc00ab2a29d1ab5d6eb Mon Sep 17 00:00:00 2001 From: root Date: Thu, 4 Dec 2025 09:20:05 +0000 Subject: [PATCH] IMPROVEMENT: new use-cases for InputArgs_json --- DbContinuousIntegration.php | 2 +- plt/getSupportFunctionsDefinition.inc.php | 79 ++++++++++++++++++++ plt/index.php | 91 ++++++++++++++++++++--- 3 files changed, 162 insertions(+), 10 deletions(-) create mode 100644 plt/getSupportFunctionsDefinition.inc.php diff --git a/DbContinuousIntegration.php b/DbContinuousIntegration.php index 09a198b..9d6a231 100755 --- a/DbContinuousIntegration.php +++ b/DbContinuousIntegration.php @@ -4,7 +4,7 @@ require_once __DIR__."/.env.php"; require __DIR__."/app.php"; require __DIR__."/plt/index.php"; -require __DIR__."/sys.php"; +require __DIR__."/sys/sys.php"; main(); diff --git a/plt/getSupportFunctionsDefinition.inc.php b/plt/getSupportFunctionsDefinition.inc.php new file mode 100644 index 0000000..55a4102 --- /dev/null +++ b/plt/getSupportFunctionsDefinition.inc.php @@ -0,0 +1,79 @@ +function getSupportFunctionsDefinition() { + + // EXAMPLE of InputArgs_json + // { + // "simpleArg": "string", + // "argWithDefault": { + // "type": "int", + // "default": 10 + // }, + // "argByReference": { + // "type": "array", + // "reference": true + // }, + // "optionalComplex": { + // "type": "?string", + // "default": null + // } + // } + + + + + $supportFunctions = ""; + + foreach (sql("SELECT Name, InputArgs_json, PhpCode FROM SYS_PRD_BND.SupportFunctions WHERE PhpCode IS NOT NULL") as $f) { + + $inputArgs = json_decode($f["InputArgs_json"], true); + $compiledArgs = []; + + if (is_array($inputArgs)) { + foreach ($inputArgs as $name => $config) { + $parts = [ + 'type' => '', + 'ref' => '', + 'name' => '$' . $name, + 'default' => '' + ]; + + // Case A: Expanded Object Configuration + if (is_array($config)) { + // 1. Type Hinting (e.g., "string", "?int", "MyClass") + if (!empty($config['type'])) { + $parts['type'] = $config['type'] . ' '; + } + + // 2. Pass by Reference + if (!empty($config['reference']) && $config['reference'] === true) { + $parts['ref'] = '&'; + } + + // 3. Variadic Arguments (...$args) + if (!empty($config['variadic']) && $config['variadic'] === true) { + $parts['ref'] = '...'; + } + + // 4. Default Values + // We use array_key_exists so we can detect if the default is actually NULL + if (array_key_exists('default', $config)) { + // var_export converts the value to parsable PHP code (adds quotes to strings, preserves arrays) + $parts['default'] = ' = ' . var_export($config['default'], true); + } + } + // Case B: Simple Key-Value pair (Backward Compatibility / Simple Type) + // Example: "endpoint": "string" + elseif (is_string($config) && !empty($config)) { + $parts['type'] = $config . ' '; + } + + // Assemble definition: "string &$name = 'value'" + $compiledArgs[] = "{$parts['type']}{$parts['ref']}{$parts['name']}{$parts['default']}"; + } + } + + $argsString = implode(", ", $compiledArgs); + $supportFunctions .= "function {$f['Name']}($argsString) {\n{$f['PhpCode']}\n}\n"; + } + + return $supportFunctions; +} diff --git a/plt/index.php b/plt/index.php index 37d2a68..061da66 100755 --- a/plt/index.php +++ b/plt/index.php @@ -96,6 +96,66 @@ function processActiveTable($activeTable) { } } +/** + * Processes all cron jobs that match the current time. + * Uses a temp file to ensure jobs run only once per minute, + * even if the script crashes and restarts. + */ +function processCronJobs() { + $lockFile = '/tmp/cron_last_run.json'; + $currentTimeKey = date("Y-m-d H:i"); // Unique ID for this specific minute + + // 1. CHECK PREVIOUS RUN (File Persistence) + if (file_exists($lockFile)) { + $data = json_decode(file_get_contents($lockFile), true); + + // If the stored time matches right now, we already ran. + if (($data['last_run'] ?? '') === $currentTimeKey) { + return; + } + } + + // 2. UPDATE TRACKER IMMEDIATELY + // We write to the file now to "claim" this minute. + file_put_contents($lockFile, json_encode(['last_run' => $currentTimeKey])); + + echo "Scanning all the cron jobs that need to be run...\n"; + + // 3. FETCH JOBS + // We check for an exact match OR a wildcard (-1) + $sql = "SELECT id, PhpCode + FROM SYS_PRD_BND.CronJobs + WHERE + (Minute = MINUTE(NOW()) OR Minute = -1) + AND (Hour = HOUR(NOW()) OR Hour = -1) + AND (DayOfMonth = DAY(NOW()) OR DayOfMonth = -1) + AND (Month = MONTH(NOW()) OR Month = -1) + AND (DayOfWeek = DAYOFWEEK(NOW()) OR DayOfWeek = -1)"; + + // 4. EXECUTION LOOP + $jobs = sql($sql); + + if ($jobs) { + foreach ($jobs as $cronJob) { + if (!empty($cronJob["PhpCode"])) { + // Pass a unique identifier (cronJob_ID) to the sandbox runner + runPHPCronCode("cronJob_" . $cronJob["id"], $cronJob["PhpCode"], $cronJob["id"]); + } + } + } +} +/** + * Executes database-level dynamic PHP trigger code. + */ +function runPHPCronCode($functionName,$code,$cronJobId) { + echo "Running PHP CRON code for cronJobId $cronJobId...\n"; + $phpCode = generatePHPCronCode($functionName, $code,$cronJobId); + $result = runSandboxedPHP($phpCode,$stdout,$stderr); + + handleCronJobExecutionResult($result, $stdout,$stderr,$cronJobId); +} + + /** * Ensures the 'LastUpdated' column exists, adding it if missing. */ @@ -237,6 +297,28 @@ function updateTriggerError($tableName, $error) { function clearTriggerError($tableName) { sql("UPDATE SYS_PRD_BND.Tables SET LastError = '', LastUpdated = NOW() WHERE Name = '$tableName'"); } +function updateCronError($cronJobId, $error) { + // Sanitize single quotes to prevent SQL breakage + $safeError = str_replace("'", '"', $error); + + // Update the CronJobs table with the error + sql("UPDATE SYS_PRD_BND.CronJobs + SET LastError = '$safeError', + LastUpdated = NOW() + WHERE id = '$cronJobId'"); // Ensure 'id' matches your actual primary key column name + + // Send the alert + sendTelegramMessage("*ERROR* on Cron Job #$cronJobId : " . $error, "DatabaseGroup"); +} + +function clearCronError($cronJobId) { + // Clear the error field + sql("UPDATE SYS_PRD_BND.CronJobs + SET LastError = '', + LastUpdated = NOW() + WHERE id = '$cronJobId'"); +} + function getConstantsDefinition() { $constants = ""; @@ -247,15 +329,6 @@ function getConstantsDefinition() { return $constants; } -function getSupportFunctionsDefinition() { - $supportFunctions = ""; - foreach (sql("SELECT Name, InputArgs_json, PhpCode FROM SYS_PRD_BND.SupportFunctions WHERE PhpCode IS NOT NULL") as $f) { - $args = implode(", ", array_map(fn($s) => "\$$s", array_keys(json_decode($f["InputArgs_json"], true)))); - $supportFunctions .= "function {$f['Name']}($args) {\n{$f['PhpCode']}\n}\n"; - } - return $supportFunctions; -} - function getPythonImports() { $imports = ""; foreach (sql("SELECT LibName, AliasName FROM SYS_PRD_BND.PyPi") as $module) {