space_engineers/Mixins/FailoverManager/readme.md

3.1 KiB

Failover Manager for SE scripts

This mixin allows multiple Programmable Blocks to coordinate with each other so only one copy of the script is running at a time; all but one block act as backup nodes that will be automatically activated (in priority order) in the event the active node goes offline.

Prerequisites

  • Everything assumes you're using MDK2. Using this without MDK is possible, but is outside the scope of this documentation. (You probably just need to copy everything inside the partial class Program block for each mixin you're using into your own script, but I can't guarantee support for problems you encounter)
  • This requires my Console mixin as well. If you don't want to use that mixin's full functionality, you can use an EchoConsole (example below).
  • If you aren't using MyIni to configure your script's blocks, you can also just pass new MyIni() and avoid instantiating an entire property

Usage

This code is designed to be as drop-in as possible once you meet the prerequisites above. Usage should look something like this:

    public partial class Program : MyGridProgram
        public MyIni Ini { get; } = new MyIni();
        public IConsole Console { get; private set; }

        private FailoverManager _failover;

        public Program() {
            Console = new MainConsole(this, "Script Name");
            _failover = new FailoverManager(this, Console, Ini);

            // alternate instantiation with Stub Console and fresh MyIni instance.
            // If you do it this way, you don't need the `Ini` or `Console` properties above.
            // _failover = new FailoverManager(this, new EchoConsole(this), new MyIni());

            // The script *must* start out with periodic updates, even if it is
            // a script that's only triggered conditionally (though in that case),
            // see caveats.
            Runtime.UpdateFrequency = UpdateFrequency.Update100;

            // ... script initialization happens here
        }

        public void Main(string argument, UpdateType updateSource) {
            // This basically instructs the script to "go back to sleep"
            // if it isn't the active node.
            if (_failover.ActiveCheck == FailoverState.Standby) return;

            // If you need more complicated "warm-up" logic when your script
            // becomes active, (for example, changing the update frequency) you can use this.
            // This statement will only be true once, when the script first takes over control.
            //
            // This is optional and depends on your use case.
            if (_failover.ActiveCheck.HasFlag(FailoverState.Failover)) {
                // Code that should run once when this script becomes the active node goes here
            }

            // ... your script logic goes here
        }

Scripts that are using failover also need configuration in their Programmable Blocks' Custom Data. That should look something like this:

[failover]
id=scriptName # This must match for all running copies of the script.
rank=0 # The lowest ranked copy of the script will be the primary node, and they will failover in ascending rank order