Skip to content

weberdaniel/reactive-cpp

Repository files navigation

C++ Actor Framework Supervisor

This project shall demonstrate the capabilities of a reactive software design with the C++ Actor Framework (CAF) on the example of a lightweight C++ supervisor process that monitors another lightweight C++ process and restarts it in case of an error.


Child process is being restarted by the supervisor

Build & Run:

# 1. Optional: define proxy
$> export http_proxy=
$> export https_proxy=

# 2. Recommended: define number of threads (not more than cpus!) and do parallel build
$> export number_of_build_jobs=
$> export DOCKER_BUILDKIT=1

# 3. get it
$> git clone https://github.com/weberdaniel/reactive-cpp

# 4. build & run it
$> cd caf-supervisor
$> docker compose build
$> docker compose up

afterwards you can login to the Grafana dashboard in your browser via (this is not yet fully functional)

http://localhost:3000

Actor Frameworks and Reactive Design

Actor Frameworks are a crucial building block for Artificial Intelligence. Actor Frameworks have been first introduced by Carl Hewitt, Peter Bishop und Richard Steiger in 1973.

The C++ Actor Framework

A notable modern implementation of an Actor Framework in C++ is CAF, the C++ Actor Framework (https://www.actor-framework.org). In contrary to programming middleware like CORBA or ACE, it uses modern C++ to improve memory management, performance and type safety.

Some highlights:

  • leverage on C++ high performance
  • low memory footprint
  • native bindings to Prometheus DB for high-performance data science in real-time
  • Resilience due to Reactive Design
  • Scalability
  • Tight memory control
  • modern c++
  • used for high-performance network analysis (Zeek)
  • Actors blend into Qt Widgets seamlessly by deriving from caf::mixin::actor_widget

Reactive Software Design: Make your software fault tolerant!

The principle of reactive software design patterns reaches back to the 1970s. A famous example of a reactive software design is the AXD301 Ericsson switch, which provides a nine-nines reliability (99.9999999%), which is basically a millisecond of downtime per year. Since highly distributed software architectures are very common today - reactive design patterns have been rediscovered (see Docker Swarm) but can also become relevant on hardware related software domains as well (performance): Examples for this is the IoT. Multi-core CPUs can be regarded as distributed systems as well.. Since today any kind of software can be regarded as a part of a distributed architecture, reactive design patterns can be applied to almost any software on any OSI layer. This is reflected in the creation of the Reactive Manifesto in order to spread word about the design concepts: https://www.reactivemanifesto.org (Book Cover: Reactive Design Patterns, Roland Kuhn)

An example design pattern: "Crash me if you can"

The 'Let it crash'/'Crash me if you can' pattern is one of the elementary design patterns of the domain. In order to build fault-tolerant software, a common design pattern is to only code for the application usecase - in any other usecase - the process will just crash and be restarted. There are various restart strategies, which can be looked up at the definition in Erlang which is given here: https://www.erlang.org/doc/man/supervisor.html

One for One Strategy




One for All Strategy




Rest for One Strategy




Aims and Goals

The goal of this project is to implement a supervision hierarchy inside a C++ high performance application.

Limitations

simple_one_for_one strategy is missing. Only works with function object based actors.

Contribution

Stick to Google Coding Stylguide and C++ Core Guidelines!

Definition of Done / Agile

Use a proper Definition of Done, like

  • 80% Code Coverage in Unit Tests
  • 1 Person must review the code before commit
  • Full C++ Core Guidelines compatibility
  • Full C++ Google Coding Styleguide compatibility
  • Only fully operational builds into the master branch
  • Use feature branches
  • Check for Memory Leaks with Valgrind