This Month in Reactive Graph! September 2024

Hello and welcome to another issue of This Month in Reactive Graph! Reactive Graph is a runtime empowering everyone to build reliable and efficient software. This is a monthly summary of its progress and community. Want something mentioned? Send us a pull request. Want to get involved? We love contributions.

This Month in Reactive Graph is openly developed on GitHub and archives can be viewed at this-month-in.reactive-graph.io. If you find any errors in this month's issue, please submit a PR.


Table of Contents


Build

Stable Rust

The biggest news this month is that we got managed to compile Reactive Graph with Stable Rust.

What has changed?
  • Implemented DashMap as container for subscribers of Stream and removed usage of the unstable feature unsized_tuple_coercion
  • Inlined implementation of feature path_file_prefix which will be stabilized soon, so that this is not a blocker
  • Removed usage of the unstable feature test and migrated to criterion (see Benchmarking with Criterion)
  • Removed usage of the unstable feature register_tool and make tarpaulin work again without this feature
  • Detect if the compiler is nightly and only if so, make use of the unstable features unboxed_closures and fn_traits

Support for musl builds

We introduced support MUSL builds.

What is musl?

musl is an implementation of the C standard library built on top of the Linux system call API, including interfaces defined in the base language standard, POSIX, and widely agreed-upon extensions. musl is lightweight, fast, simple, free, and strives to be correct in the sense of standards-conformance and safety.

https://musl.libc.org/

Setup and Compile using musl

In order to successfully compile, you also have to install the package musl-tools. For example for Debian / Ubuntu, you can install it like so:

$ apt install musl-tools

Next you have to add the musl target using rustup:

$ rustup target add x86_64-unknown-linux-musl

Finally you can compile reactive-graph for the target x86_64-unknown-linux-musl:

$ cargo build --target x86_64-unknown-linux-musl

rustls

We've finished work on replacing OpenSSL with rustls. OpenSSL is no more needed to build Reactive Graph.


Benchmarking with Criterion

Now the benchmark tests are run with criterion (which doesn't need Nightly Rust). Furthermore, the benchmarks has been moved into its own benches/ folders.

Features of Criterion
  • Statistics: Statistical analysis detects if, and by how much, performance has changed since the last benchmark run
  • Charts: Uses gnuplot to generate detailed graphs of benchmark results
  • Stable-compatible: Benchmark your code without installing nightly Rust

A future task would be to write more benchmark tests and to execute benchmarking in the CI.


Continuous Integration

Upgrade Workflows and Improve CI performance

We've upgraded the workflow actions to recent versions. Furthermore, we made some changes to speed up the CI. We've merge workflow files and made build jobs and test jobs dependent on the formatting check job and linting jobs. With this change, no build time is wasted if linting and formatting doesn't meet the requirements. Furthermore, we're run linting and test suite on Linux GNU and Linux musl for Rust stable and Rust nightly. But we don't run the complete test suite on Windows and macOS anymore. This is because running the test suite on Windows is 2x slower and on macOS is 6x slower compared to running on Linux. At a later point we may reintroduce a smaller subset of the test suite to run on Windows and macOS.


New Checks

  • Minimal Supported Rust Version (MSRV)
  • Dependabot now checks for outdated dependencies
  • Checks that the CHANGELOG was edited

Command Line Interface

Managing the Instance System

We finished the implementation of managing the instance system via CLI (entity instances and relation instances). Furthermore, the CLI lists the applied components of the reactive instances.

Documented Command Line Interface

The book now contains a section about the Command Line Interface. We've added a section about the interactive mode and a section about the command reference. For the command reference we make use of a new option to automatically generate the help in Markdown format:

$ reactive-graph --markdown-help

TODO: Insert output here

Output Format Count

We've added a new output format that simply prints the count instead of a table with the results. The purpose of the new feature is similar to count(*) in SQL and is also useful for shell automation.

$ reactive-graph client components list --output-format count
$ reactive-graph client entity-types list --output-format count
$ reactive-graph client relation-types list --output-format count
$ reactive-graph client entity-instances list --output-format count
$ reactive-graph client relation-instances list --output-format count
Examples

Print the count of components

$ reactive-graph client components list --output-format count
34 result(s)

Example: Print the count of entity-instances

$ reactive-graph client entity-instances list --output-format count
1554 result(s)

Example: Print the count of entity-instances that having the component core__action

$ reactive-graph client entity-instances list --components core__action --output-format count
2 result(s)

Output Format HTML

We have added a new option to output the result as HTML table. This applies to all type system and instance system operations.

Output Format HTML

List types and instances as HTML table

$ reactive-graph client components list --output-format html-table
$ reactive-graph client entity-types list --output-format html-table
$ reactive-graph client relation-types list --output-format html-table
$ reactive-graph client entity-instances list --output-format html-table
$ reactive-graph client relation-instances list --output-format html-table

List all components as HTML table

$ reactive-graph client components list --output-format html-table

namespace name description properties extensions
state state_object State of type object
name data_type socket_type mutability
state Object None Immutable
set_state Object Input Mutable
value value_debugger_trace
arithmetic arithmetic_operation Arithmetic operation with one input and one result
name data_type socket_type mutability
result Number Output Immutable
lhs Number Input Mutable
Namespace TypeName Description Extension
core component_category "math"
base named The entity or relation has a name.
name data_type socket_type mutability
name String None Mutable
Namespace TypeName Description Extension
core component_category "base"
value value_object Value of type object
name data_type socket_type mutability
value Object Output Mutable
result result_boolean The entity returns a boolean
name data_type socket_type mutability
result Bool Output Immutable
Namespace TypeName Description Extension
core component_category "result"

Output a single type or a single instance as HTML table

$ reactive-graph client components get <namespace> <type_name> --output-format html-table
$ reactive-graph client entity-types get <namespace> <type_name> --output-format html-table
$ reactive-graph client relation-types get <namespace> <type_name> --output-format html-table
$ reactive-graph client entity-instances get <namespace> <type_name> --output-format html-table
$ reactive-graph client relation-instances get <namespace> <type_name> --output-format html-table

Output a single component as HTML table

$ reactive-graph client components get value value_number --output-format html-table
namespace name description properties extensions
value value_number Value of type number
namedata_typesocket_typemutability
valueNumberOutputMutable

Output Format Markdown

Similar to the Output Format HTML, the Output Format Markdown prints the result as Markdown Table.

Output Format Markdown

List types and instances as Markdown table

$ reactive-graph client components list --output-format markdown-table
$ reactive-graph client entity-types list --output-format markdown-table
$ reactive-graph client relation-types list --output-format markdown-table
$ reactive-graph client entity-instances list --output-format markdown-table
$ reactive-graph client relation-instances list --output-format markdown-table

List all components as Markdown table

$ reactive-graph client components list --output-format markdown-table
namespacenamedescriptionpropertiesextensions
statestate_objectState of type object

name

data_type

socket_type

mutability

set_state

Object

Input

Mutable

state

Object

None

Immutable

valuevalue_debugger_trace
arithmeticarithmetic_operationArithmetic operation with one input and one result

name

data_type

socket_type

mutability

result

Number

Output

Immutable

lhs

Number

Input

Mutable

Namespace

TypeName

Description

Extension

core

component_category

"math"

basenamedThe entity or relation has a name.

name

data_type

socket_type

mutability

name

String

None

Mutable

Namespace

TypeName

Description

Extension

core

component_category

"base"

valuevalue_objectValue of type object

name

data_type

socket_type

mutability

value

Object

Output

Mutable

resultresult_booleanThe entity returns a boolean

name

data_type

socket_type

mutability

result

Bool

Output

Immutable

Namespace

TypeName

Description

Extension

core

component_category

"result"

Output a single type or a single instance as Markdown table

$ reactive-graph client components get <namespace> <type_name> --output-format markdown-table
$ reactive-graph client entity-types get <namespace> <type_name> --output-format markdown-table
$ reactive-graph client relation-types get <namespace> <type_name> --output-format markdown-table
$ reactive-graph client entity-instances get <namespace> <type_name> --output-format markdown-table
$ reactive-graph client relation-instances get <namespace> <type_name> --output-format markdown-table

Output a single component as Markdown table

$ reactive-graph client components get value value_number --output-format markdown-table
namespacenamedescriptionpropertiesextensions
valuevalue_numberValue of type number

name

data_type

socket_type

mutability

value

Number

Output

Mutable


Shell Completions

In order to further improve the user experience with the command line interface we've implemented the feature to generate shell completions.

List of Supported Shells
  • bash
  • elvish
  • fish
  • powershell
  • zsh

On linux it's possible to install the shell completions for the given shell by executing:

$ reactive-graph --install-shell-completions bash|fish|zsh

Then you have to restart the shell, for example:

$ zsh

Profit!

$ reactive-graph -- TAB
--daemon-group               -- If set will drop privileges to the specified group. Note: Both must be given: user and group
--daemon                     -- If true, the process will run as daemon
--daemon-name                -- Sets the name of the daemon
--daemon-pid                 -- The location of the daemon PID file. By default, no PID file will be created
--daemon-stderr              -- Stderr will be written into this file
--daemon-stdout              -- Stdout will be written into this file
--daemon-user                -- If set will drop privileges to the specified user. Note: Both must be given: user and group
--daemon-working-directory   -- The working directory of the daemon
--default-context-path       -- The default context path which redirects the root context to a web resource provider
--disable-all-plugins        -- If true, all plugins will be disabled
--disabled-plugins           -- The list of plugins to disable
--disable-hot-deploy         -- If true, hot deployment will be disabled
--enabled-plugins            -- The list of plugins to enable
--graphql-config             -- The GraphQL config location
--help                       -- Print help
--hostname                   -- The hostname to bind the GraphQL HTTP server
--hot-deploy-location        -- The folder which is watched for hot deployment
--install-location           -- The folder which plugins are installed permanently
--install-man-pages          -- If true, installs man pages
--install-shell-completions  -- If true, installs shell completions
--instance-config            -- The instance config location
--instance-description       -- The description of the instance
--instance-name              -- The name of the instance
--logging-config             -- The logging config location
--markdown-help              -- If true, generates command line documentation
--plugins-config             -- The plugins config location
--port                       -- The port to bind the GraphQL HTTP server
--print-man-pages            -- If true, generates man pages
--print-shell-completions    -- If true, prints shell completions
--quiet                      -- If true, logging is disabled completely
--secure                     -- If true, HTTPS is enabled
--shutdown-timeout           -- Timeout for graceful workers shutdown in seconds. After receiving a stop signal, workers have this much time to finish serving requests. Workers still alive after the timeout are force dropped. By default, shutdown timeout sets to 30 seconds
--ssl-certificate-path       -- The location of the certificate
--ssl-private-key-path       -- The location of the private key
--stop-immediately           -- If true, the runtime does not wait before exiting
--version                    -- Print version
--workers                    -- The number of workers to start. The default worker count is the number of physical CPU cores available

Man Pages (Linux only)

Similarly to shell completions, the command line interface can generate, print and install man pages.

What is a man page?

A man page (short for manual page) is a form of software documentation usually found on a Unix or Unix-like operating system. Topics covered include computer programs (including library and system calls), formal standards and conventions, and even abstract concepts. A user may invoke a man page by issuing the man command.

Wikipedia

First, you can install man pages:

$ reactive-graph --install-man-pages

Then you can use the man command:

$ man reactive-graph
reactive-graph(1)                                                                                                                                          General Commands Manual                                                                                                                                          reactive-graph(1)

NAME
       reactive-graph - Reactive Graph is a reactive runtime based on a graph database, empowering everyone to build reliable and efficient software.

SYNOPSIS
       reactive-graph  [--logging-config] [--instance-config] [--graphql-config] [--plugins-config] [-n|--instance-name] [-d|--instance-description] [--hostname] [--port] [--secure] [--ssl-certificate-path] [--ssl-private-key-path] [--shutdown-timeout] [-w|--workers] [-c|--default-context-path] [-x|--disable-all-plugins] [-p|--dis‐
       abled-plugins] [-P|--enabled-plugins] [--disable-hot-deploy] [--hot-deploy-location] [--install-location] [--stop-immediately] [-q|--quiet] [--print-man-pages] [--install-man-pages] [--print-shell-completions] [--install-shell-completions]  [-D|--daemon]  [--daemon-name]  [--daemon-pid]  [--daemon-working-directory]  [--dae‐
       mon-stdout] [--daemon-stderr] [--daemon-user] [--daemon-group] [-h|--help] [-V|--version] [subcommands]

DESCRIPTION
       Reactive Graph is a reactive runtime based on a graph database, empowering everyone to build reliable and efficient software.

OPTIONS
       --logging-config=LOGGING_CONFIG
              The logging config location
              May also be specified with the REACTIVE_GRAPH_LOGGING_CONFIG environment variable.

       --instance-config=INSTANCE_CONFIG
              The instance config location
              May also be specified with the REACTIVE_GRAPH_INSTANCE_CONFIG environment variable.

...

Dedicated client binary

We follow the approach to have one binary for all use cases (server & client).

Additionally, we now provide a second binary that only contains the client.

$ ls -lah target/debug/reactive-graph*
-rwxrwxr-x 2 rust rust 81M reactive-graph
-rwxrwxr-x 2 rust rust 29M reactive-graph-client
$ reactive-graph-client relation-instances list --output-format count
9366 result(s)

Daemonize

On Linux, it's now possible to start the process and run it in the background. Because the daemon has no stdout and stderr, a file can be given as output. Also, the process can drop privileges to a given user+group. Optionally, a PID and name can be specified.

$ reactive-graph --help
  -D, --daemon
          If true, the process will run as daemon [env: REACTIVE_GRAPH_DAEMON=]
      --daemon-name <DAEMON_NAME>
          Sets the name of the daemon [env: REACTIVE_GRAPH_DAEMON_NAME=]
      --daemon-pid <DAEMON_PID>
          The location of the daemon PID file. By default, no PID file will be created [env: REACTIVE_GRAPH_DAEMON_PID=]
      --daemon-working-directory <DAEMON_WORKING_DIRECTORY>
          The working directory of the daemon [env: REACTIVE_GRAPH_DAEMON_WORKING_DIRECTORY=]
      --daemon-stdout <DAEMON_STDOUT>
          Stdout will be written into this file [env: REACTIVE_GRAPH_DAEMON_STDOUT=]
      --daemon-stderr <DAEMON_STDERR>
          Stderr will be written into this file [env: REACTIVE_GRAPH_DAEMON_STDERR=]
      --daemon-user <DAEMON_USER>
          If set will drop privileges to the specified user. Note: Both must be given: user and group [env: REACTIVE_GRAPH_DAEMON_USER=]
      --daemon-group <DAEMON_GROUP>
          If set will drop privileges to the specified group. Note: Both must be given: user and group [env: REACTIVE_GRAPH_DAEMON_GROUP=]

In order to start Reactive Graph as a daemon, you have to pass the parameter -D or set the environment variable REACTIVE_GRAPH_DAEMON=true:

$ reactive-graph --daemon

Refactoring

Extracted table model

The table model has been refactored into its own crate. This allows to print tables in other command line applications.

The examples are now using the table model. The printed tables look better than before. Thanks to the table model, it is no more necessary to render tables manually.


GraphQL Schema

There are some changes to the GraphQL schema:

List of Changes
  • edgeKey has been renamed to relationInstanceId for consistency
  • EdgeKeyDefinition has been renamed to RelationInstanceIdDefinition for consistency
  • Extended mutation instances -> relations -> update() with the new parameters addProperties and removeProperties in order to add or remove one or multiple properties

Design System Enhancements

Circle Logos

We added a new set of logos with a circle around the inner graph symbol:

Black/White Malachite Selective Yellow Celestial Blue Mexican Pink Chartreuse

Horizontal Rules

Nothing special, but useful: horizontal rules


Project Maintenance

Social Media

We created a YouTube channel, a facebook profile and a mastodon account. We will start social media activities in near future.


Contribution Guidelines & Security Policy

We've extended the Contribution Guidelines and added a Security Policy.