Multi-instance service-runner

So I just had a stab at this and whilst i have had a couple of issues, neither are directly related to implementing this as such.

  1. There is a problem with the process_settings.php file, when ever I try to include/require(_once) I get faults like these pop up momentarily in the emonpi update log window

it would seem require_once is the better option and that just spits out the 2 errors above, they relate to what appear to be the only 2 variables that are handled differently to the others

I messed around with this for a while before noticing they were different, and assuming that is for a reason and assuming it is handled better in other parts of emoncms, I tried everything to change the behavior within my code changes. Once I realised the differences I decided not to get sidetracked further and just hardcopied the redis settings array to my code so I could continue.

  1. Unbeknown to me, there is a “fudging” of the Redis prefix in the process_settings.php file, so by doing the above I also sidestepped this and spend a significant amount of time trying to determine why my prefixes and keys were concatenated without a colon.

Debugging the above took 10x longer than making the actual code changes.

I have had this up and running (using a hardcoded copy of the Redis settings array for now) and have produced 2 options so the code is a bit messy, but can be reduced and tidied once the setting issue is sort and a decision made about which option.

The changes to the existing code are minimal, just the 2 lines switched in emoncms/Modules/admin/admin_controller.php

                    require_once "Lib/service-runner-queue.php";
                    $result = issue_service_runner_flag("$update_script $argument>$update_logfile");
//                    $redis->rpush("service-runner","$update_script $argument>$update_logfile");
//                    $result = "service-runner trigger sent";

and the following added as `emoncms/Lib/service-runner-queue.php

<?php

/*

    All Emoncms code is released under the GNU Affero General Public License.
    See COPYRIGHT.txt and LICENSE.txt.

    ---------------------------------------------------------------------
    Emoncms - open source energy visualisation
    Part of the OpenEnergyMonitor project:
    http://openenergymonitor.org

*/

// no direct access
defined('EMONCMS_EXEC') or die('Restricted access');


function issue_service_runner_flag($flag_content) {
    //require_once "process_settings.php";
    //TEMPORARILY BORROWED SETTINGS AS ABOBE LINE ERRORS
    $redis_server = array('host'=>'localhost','port'=>6379,'auth'=>'','prefix' => 'emoncms');
    // fudging prefix ref https://github.com/emoncms/emoncms/blob/9.9.5/process_settings.php#L83
    if (!empty($redis_server['prefix'])) $redis_server['prefix'] = $redis_server['prefix'] . ":";

    $srq = new Redis();
    $srq_connected = $srq->connect($redis_server['host'], $redis_server['port']);
    if ($srq_connected) {
        if (!empty($redis_server['auth'])) {
            if (!$srq->auth($redis_server['auth'])) {
                return "service-runner failed auth";
            }
        }
        // opt1: No prefix just a common "emoncms-service-runner" key
        //       There is no way to identify the origin other than by the value
        //       The success message will indicate the position in global queue
//        $pos = $srq->rpush("emoncms-service-runner",$flag_content);


        // opt2: Prefixed "emoncms-service-runner" and instance redis prefix as key
        //       This allow the service-runner to identify origin (logs, user, paths???)
        //       The success message will indicate the instance specific position in queue
        $srq->setOption(Redis::OPT_PREFIX, 'emoncms-service-runner:'); // trailing colon on prefix required!!!
        // UNDO fudging prefix ref https://github.com/emoncms/emoncms/blob/9.9.5/process_settings.php#L83
        if (!empty($redis_server['prefix'])) $redis_server['prefix'] = rtrim($redis_server['prefix'], ':');
        $pos = $srq->rpush($redis_server['prefix'],$flag_content);

        return "service-runner trigger sent (queue position:$pos)";
    }
}

As it stands it will publish the exact same flag content to emoncms-service-runner:emoncms where emoncms is the Redis prefix, used as a sub-key so the service-runner can determine who set the flag, useful for log entries or if we want a different user etc. eg

pb66@test3:/var/www/test/emoncms$ sudo redis-cli keys emon*
1) "emoncms-service-runner:test"
pb66@test3:/var/www/test/emoncms$ sudo redis-cli lpop emoncms-service-runner:test
"/home/pi/emonpi/service-runner-update.sh emonpi>/home/pi/data/emonpiupdate.log"

I have changed the success message to include the position in the queue, if the Redis instance prefix is used as above, the queue will be instance specific.

There is also “opt2” which is to just have a single key for every instance to push flags to, this method will not inform the service-runner where the flag originated and the queue position is global.

pb66@test3:/var/www/test/emoncms$ sudo redis-cli keys emon*
1) "emoncms-service-runner"
pb66@test3:/var/www/test/emoncms$ sudo redis-cli lpop emoncms-service-runner
"/home/pi/emonpi/service-runner-update.sh emonpi>/home/pi/data/emonpiupdate.log"

to try opt1 just un-comment the last line of the “opt1” block and comment out all 3 lines used in the “opt2” block.

I think I prefer the former as it has more scope to use other users and paths etc and debugging might be easier. But it would involve some minor parsing in service-runner.py.

I can add this as a feature branch to try if you like but it’s a pretty simple edit, it would be good to get rid of the settings workaround and pick a option before I do. Any thoughts?

[edit - obviously the current SR code will need amending to which ever approach we settle on, I have just been working with the raw Redis values today, I still haven’t installed SR]

1 Like