Skip to content
Robert Hafner edited this page Oct 19, 2017 · 1 revision

Quorum uses the "Operating System Model" for its running code. This gives it the ability to adapt as load is put on the system while also letting systems run more overall by running less important or really expensive code less often.

The functional code in Quorum is divided up into programs. Each program manages a specific aspect of the system and is capable of launching its own children programs.

Hello World

Here we start with a simple program that prints Hello World to the console.

class HelloWorld extends kernel.process {
  main () {
    Logger.log('Hello World!')
  }
}

module.exports = HelloWorld

This program is as simple as it gets- the main function, which is called every time the program is run, uses the Logger library to print 'Hello World'. The program extends from the kernel.process class which makes sure this program has everything needed for the kernel to run it.

Persisting Data

Each process (which is an instance of a running program) has its own datastore that is unique and isolated from other processes. This datastore persists between ticks but gets cleared automatically when the process dies. Accessing this datastore is done through this.data.

class Counter extends kernel.process {
  main () {
    if (!this.data.count) {
      this.data.count = 1
    } else {
      this.data.count++
    }
    Logger.log(`I've been called ${this.data.count} times!`)
  }
}

module.exports = Counter

Ending

Once a program is finished it should be properly closed, which can be done using this.suicide.

class Countdown extends kernel.process {
  main () {
    if (typeof this.data.countdown === 'undefined') {
      this.data.countdown = 1
    } else {
      this.data.countdown--
    }
    if (this.data.countdown === 0) {
      return this.suicide()
    }
    Logger.log(`Shutdown in ${this.data.countdown} ticks!`)
  }
}

module.exports = Countdown

Launching

There are two main ways to launch new programs from inside other programs- launchProcess and launchChildProcess- although in almost all cases you will want launchChildProcess. Children processes are attached to their parents and will stop running if their parent process does, while programs created with launchProcess will run until they close themselves.

When launching processes a label, program name, and (optionally) data are passed to the launching function. Labels are used to keep track of which programs are already running and to prevent multiple copies of the same program from running every tick- if a launch process is called and the label already has a PID attached to it then a new process will not be launched until that first one finished. The name field is the name of the file itself, in all lowercase and with the folder delimiter converted to underscores (city/mine.js to city_mine).

The final field, data, gets passed to the new process and is used to populate its initial data object.

Putting this all together we can launch the above CountDown program and set it to run for 30 ticks instead of the default ten.

class Player extends kernel.process {
  main () {
    this.launchChildProcess('30 second countdown', 'countdown', {'countdown': 30})
  }
}
Clone this wiki locally