Jazz Services, APIs and Instantiation

Last updated: 2026-03-21: Applies to Jazz 1.26.x

Jazz is a single monolithic process. It allocates data and code (which is data) through some classes that only have one instance of each. This document describes the logic behind it.

Services

In Jazz, all the classes that define data and metadata neither have a configuration nor do they allocate RAM. They also don’t have a logger to write to.

These classes are:

StaticBlockHeader -> Block -> Tuple -> Snippet -> Space -> Concept
                       |                            +----> DataSpace -> SemSpace
                       +----> Kind

All the classes that do have configuration, a logger and can allocate memory are inherited from the Service class. While you will typically instantiate many objects of data and metadata classes, you will only have one instance of each service.

A Service is constructed by passing a ConfigFile (a key-value store that reads a file and exposes it as keys to the Service) and a Logger (Which exposes a variadic log_printf() function and automatically annotates time, level and thread info) to the Service descendant constructor.

Services are always inherited.

Services, ConfigFiles and Loggers are all defined in jazz_elements::utils.

Services also have a start() and shut_down() methods, typically run only once when the server starts and closes.

Containers

Service -> Container
   +-----> HttpServer
  1. Some Container descendant owns every Block, Kind and Tuple instances in Jazz (no exceptions). It wraps them in a Transaction object. Transactions have a common interface for both persistence StoredTransaction and memory VolatileTransaction. This continues to be true beyond jazz_elements, the Snippet, Space, Concept, DataSpace and SemSpace objects are just Tuple descendants and created by some Container (Core for Snippet, Bebop for Space, and ModelsAPI for Concept, DataSpace and SemSpace).

  2. Memory management is handled through custom allocation methods (malloc, block_malloc) that track allocated bytes and ensure proper alignment.

  3. Every Block, Tuple and Kind is created by one of the 8 forms of new_block() included in the parent class. This uses RAM from the Container’s memory pool. These methods allow for creating Tensors from raw data, filtering rows from other Tensors, selecting items from Tuples, and more. Beyond jazz_elements, the Core, the Compiler or the Model create their own and the classes have constructors that simplify its creation.

  4. Resources inside a container are identified through a Locator. Locators have a string form (///node//base/entity/key++) that is parsed into its components.

  5. Containers provide a CRUD interface: (get, header, put, new_entity, remove, copy). These methods exist as a high-level interface (the unparsed string form) and a locator-based interface (each component separately).

  6. Code execution is done via exec() (normal function calls) or modify() (external call made to services via Channels). At the level of jazz_elements, exec() is only declared but not implemented and modify() is used only in Channels. Code executed via exec() corresponds to the API apply codes predicates APPLY_ASSIGN_FUNCTION and APPLY_ASSIGN_FUNCT_CONST. It is the most basic functionality that is later extended in BaseAPI and its descendants. Beyond jazz_elements, exec() is connected to the calling mechanism of a Snippet, inherited all the descendants and managed by BaseAPI descendant which is a Container.

  7. The class also includes methods for locking and unlocking the container or entering and leaving read and write states (enter_read, enter_write, leave_read, leave_write), which are essential for managing concurrent access to the container. Also, two methods for transaction management (new_transaction, destroy_transaction).

  8. All the string parsing for both locators and constants supported by the different new_block() methods is done by the Container class.

  9. A method base_names() adds (keys and a pointer to itself) to a map passed by reference. This tells an API who manages what base. (A base is the part of a Locator that identifies a functionality).

Overall, the Container class is a robust and flexible component designed to manage complex data structures and transactions, providing a rich API for creating, modifying, and querying data while ensuring thread safety and efficient memory management.

Container descendants in jazz_elements

Service -> Container -> Channels
               +------> Volatile
               +------> Persisted

There are three of them:

Instantiation (and Uplifting)

How Services are instantiated

The Jazz server instantiates services, one instance of each, following these rules:

  Globals:    Used by:                     Uplifted:
  --------    --------                     ---------
  Channel     Core, Bebop, ModelsAPI, API  No
  Volatile    Core, Bebop, ModelsAPI, API  No
  Persisted   Core, Bebop, ModelsAPI, API  No
  Core        Bebop, ModelsAPI, API        No
  Bebop       ModelsAPI, API               Possibly
  ModelsAPI   API                          Possibly
  API         HttpServer                   Possibly
  HttpServer  -- the outside world --      No

Execution: BaseAPI, OpCodes Core

Service ----------> OpCodes          [ONNX language]
   +-> Container -> BaseAPI          [Manages petitions to Containers]
                      +----> Core    [Manages sessions, runs code and serves]
Block ------------> Tuple -> Snippet [Code snippet, parent of Space]

The namespace jazz_core has:

Core is the only object instantiated by the server’s instantiation mechanism. Core implements the exec() method. It inherits from BaseAPI which provides control over the containers in jazz_elements.

The BaseAPI class

BaseAPI handles everything that is neither http specific or requires code execution. It provides an interface that is on one side http oriented:

And on the other side defines a subset of Bop that provides control over the containers.

The subset of Bop that handles queries is defined by the use of the apply property in an ApiQueryState structure. There are 23 codes ranging from APPLY_NOTHING to APPLY_JAZZ_INFO. See jazz_elements::channel.h.

Code execution is done by the BaseAPI descendants (Core, Bebop and ModelsAPI).

Compilation: Space, NameSpace, Bebop

Service
   +-> Container -> BaseAPI         [Manages petitions to Containers]
                      +----> Bebop  [Compiles, runs using a Core and serves]
Block -> Tuple -> Snippet -> Space  [A hierarchical code element, parent of Concept]

The namespace jazz_bebop has:

Resolution: Concept, DataSpace, SemSpace, Model, ModelsAPI

Service ----------> Model                                 [Abstract class that defines models]
   |                  +----> MyModel                      [Models are always uplifted]
   +-> Container -> BaseAPI                               [Manages petitions to Containers]
                      +----> ModelsAPI                    [Serves, resolves, compiles and runs]
Block -> Tuple -> Snippet -> Space -> Concept             [A code element with resolution]
                               +   -> DataSpace           [A Space to organize data]
                                         +-----> SemSpace [A Space to organize Concepts]

The namespace jazz_models has:

The two flavors of Bebop

You can consider Bebop (Bop) a language with two “flavors”: a formal one that can be compiled and is defined by everything in this namespace and an informal natural language that is converted into compilable code by a Model in jazz_models.

At the level of jazz_bebop, we have a compiler that converts formal compilable Bebop code into formal object code. In this higher level of abstraction (jazz_models) we convert informal natural language into formal compilable Bebop code. This requires a Model.

API as a BaseAPI descendant

Service -> Container -> BaseAPI -> API  [Single http entry point aware of all Containers]

The API class

The API class is a BaseAPI aware of every other BaseAPI descendant. As a BaseAPI itself it manages: Channels, Volatile and Persisted. It routes its http put() and delete() methods to its parent and its get() method to either its parent, Core, Bebop or ModelAPI. API is called by the http_request_callback() callback function of the HttpServer class. Except for developing purposes it is typically uplifted to provide security and access control. Note that without restrictions, the API can execute any code on the server since it has access to the console via the Chanel container. The least harmful thing it can do is stop the server. This functionality can also be disabled via configuration, but uplifting provides total control over the server, not just disabling features.

jazz_main: The server itself

The jazz_main namespace, beyond the API class, includes the server instantiation, starting, stopping, etc. The mechanisms to customize the server are: uplifting, configuration and providing a static website (html, js, css) that the server will serve by default. You will typically not want to modify the server itself. In that case, the source code itself is the reference.