Skip to content

Custom packages

This page describes the building blocks of a custom KXS package.

A custom package brings together the pieces that KXS needs to run your code: the service classes that host your processes, the q code those processes load, and the .pkg metadata file that identifies the package itself. This page covers all three.

Service classes

There are two components to a service class in KX Sensors: the enumeration defined in svcClass.yaml, and the service class entity defined in process.yaml. The service class enumeration and entity should have the same name, following the case conventions in each file.

  1. Add an enumeration for your new service class. Refer to Override an existing enumeration, applying the q code file there to the enumeration file config/enum/svcClass.yaml.
  2. Make a copy of process.yaml in config/ and place it in the config/ directory of your custom package.
  3. Edit your new copy of process.yaml by deleting all fields that remain unchanged from a lower-level directory. Then add your new service class and define the libraries that it loads and the tables that it subscribes to and publishes to.
  4. Add your new service class to your manifest.yaml file for each node.

Add q code files and modules

q code is loaded from plain q files on disk in KX Sensors. q code files may contain one or more functions related to a certain functionality of the system. The code can be any valid q required to serve any purpose. Once a file is loaded into a process, all functions and variables defined in it are available to the process.

Add a q code file to a KX Sensors process

Suppose that you have created a q code file, src/core/sampInst.q, and inside this file you created a function called .samp.init. You now want to make use of this function for the purpose of initializing an RDB process.

  1. Create config/process.yaml in the appropriate override directory.
  2. Specify the rdb service class.
  3. In the libraries field of your process.yaml override, specify src/core/sampInst.q. Since libraries has an overlay method of merge, this is appended to the libraries already loaded for rdb.
  4. In the init field of your process.yaml override, append .samp.init to the list of initialization functions specified in a previous overlay for rdb. This is required as init uses the default overlay method, which is fill.
  5. If you are upgrading an existing version of the q module, it must be marked as reloadable using the .load.once[] or .load.dyn[] predicates.

The following example shows the resulting process.yaml, with rdb loading a new q code file and a new initialization function:

process:
   values:
      - svcClass: rdb
        libraries: src/core/sampInst.q
        init: [ .rdb.init, .samp.init ]

The .pkg file

Every package should contain a .pkg file that has key-value paired metadata about the package.

$ cat kxs-core-0.0.0/.pkg
pkg.name=kxs-core
pkg.version=0.0.0

build.tag=snapshot
build.hash=7051e13ec5a568c6f7b64161ba82fef6a8e4dc5c
build.time=2025.10.16D00:15:50.927822196

The build.* metadata is not critical but can be useful for auditing purposes.

The pkg.* metadata is used for:

  • Loading offline upgrade scripts.
  • Logging package versions on process startup.
  • Generating symbolic links in the package directory to the versioned packages during DU.

It is critical that a .pkg file exists in any kxs-core package that is being upgraded. Since binaries for kxsctl, qetcd, and RT reside in kxs-core, if a kxs-core package does not include a .pkg file, the symbolic link for kxs-core does not change during DU, and the older binaries are still used post-DU.

Next steps