{"id":37099802,"url":"https://github.com/vctlabs/redis-ipc","last_synced_at":"2026-04-14T00:07:57.068Z","repository":{"id":17364083,"uuid":"20135821","full_name":"VCTLabs/redis-ipc","owner":"VCTLabs","description":"convenience library for using redis server and JSON as IPC mechanism (command queues, broadcast events)","archived":false,"fork":false,"pushed_at":"2025-12-05T21:26:19.000Z","size":1147,"stargazers_count":28,"open_issues_count":4,"forks_count":5,"subscribers_count":4,"default_branch":"develop","last_synced_at":"2025-12-08T08:57:32.533Z","etag":null,"topics":["ipc","json","redis"],"latest_commit_sha":null,"homepage":"https://vctlabs.github.io/redis-ipc/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/VCTLabs.png","metadata":{"files":{"readme":"README.rst","changelog":"ChangeLog.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2014-05-24T17:51:46.000Z","updated_at":"2025-12-05T18:55:21.000Z","dependencies_parsed_at":"2026-01-06T15:06:54.021Z","dependency_job_id":null,"html_url":"https://github.com/VCTLabs/redis-ipc","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/VCTLabs/redis-ipc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VCTLabs%2Fredis-ipc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VCTLabs%2Fredis-ipc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VCTLabs%2Fredis-ipc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VCTLabs%2Fredis-ipc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/VCTLabs","download_url":"https://codeload.github.com/VCTLabs/redis-ipc/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VCTLabs%2Fredis-ipc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28419557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ipc","json","redis"],"created_at":"2026-01-14T12:10:19.082Z","updated_at":"2026-04-14T00:07:57.061Z","avatar_url":"https://github.com/VCTLabs.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"===========\n redis-ipc\n===========\n\nredis-ipc is an example of how redis_ can be used as an advanced IPC\nmechanism on an embedded Linux system, for instance as a substitute for\nthe more common choice of dbus.\n\n|ci| |conda-dev| |codeql| |cpplint| |coverage|\n\n|pre| |cov|\n\n|tag| |license| |std|\n\nredis-ipc is intended to make communication among different logical\ncomponents of a system convenient. It is not intended to replace shared\nmemory for high data-rate transfers between processes, where lowest\npossible overhead is key, but to provide a convenient and reliable way\nto implement the following IPC mechanisms:\n\n* command queues\n* settings\n* status\n* state\n* event channels\n\n\"But, but... redis for *embedded* applications??\"\n\n\nQuick Start Package Install\n===========================\n\nredis-ipc comes in 2 flavors, a python class module and a lightweight C\nlibrary implementation (this repo). The python module has moved to a\n`new home`_.\n\n.. _new home: https://github.com/VCTLabs/redis-ipc-py\n\nPackages are available for Ubuntu_, and the latest can be installed on\nGentoo using the ebuilds in `this portage overlay`_. To build from\nsource, see `Building redis-ipc`_ below.\n\n\n.. _Ubuntu: https://launchpad.net/~nerdboy/+archive/ubuntu/embedded\n.. _this portage overlay: https://github.com/VCTLabs/embedded-overlay/\n\n\nMaking Changes \u0026 Contributing\n=============================\n\nThis repo is now pre-commit_ enabled for various linting and format\nchecks.  The checks run automatically on commit and will fail the\ncommit (if not clean) with some checks performing simple file corrections.\n\nIf other checks fail on commit, the failure display should explain the error\ntypes and line numbers. Note you must fix any fatal errors for the\ncommit to succeed; some errors should be fixed automatically (use\n``git status`` and `` git diff`` to review any changes).\n\nSee the pre-commit docs under ``docs/dev/`` for more information:\n\n* pre-commit-config_\n* pre-commit-usage_\n\nYou will need to install pre-commit before contributing any changes;\ninstalling it using your system's package manager is recommended,\notherwise install with pip into your usual virtual environment using\nsomething like::\n\n  $ sudo emerge pre-commit  --or--\n  $ pip install pre-commit\n\nthen install it into the repo you just cloned::\n\n  $ git clone https://github.com/VCTLabs/redis-ipc\n  $ cd redis-ipc/\n  $ pre-commit install\n\nIt's usually a good idea to update the hooks to the latest version::\n\n    pre-commit autoupdate\n\n\n.. _pre-commit: http://pre-commit.com/\n.. _cpplint: https://github.com/cpplint/cpplint\n.. _pre-commit-config: docs/dev/pre-commit-config.rst\n.. _pre-commit-usage: docs/dev/pre-commit-usage.rst\n\n\nPrerequisites\n-------------\n\nA supported linux distribution, mainly something that uses either\n``.ebuilds`` (eg, Gentoo or funtoo) or ``.deb`` packages, starting with at\nleast Ubuntu bionic or Debian stretch (see the above PPA package repo\non Launchpad).\n\nMake sure you have the ``add-apt-repository`` command installed and\nthen add the PPA:\n\n::\n\n  $ sudo apt-get install software-properties-common\n  $ sudo add-apt-repository -y -s ppa:nerdboy/embedded\n  $ sudo apt-get install libredis-ipc-dev redis-tools redis-server\n\n\n.. note:: Since the package series currently published are for bionic/focal,\n          building from source is recommended if installing on Debian.\n\n\nIf you get a key error you will also need to manually import the PPA\nsigning key like so:\n\n::\n\n  $ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys \u003cPPA_KEY\u003e\n\nwhere \u003cPPA_KEY\u003e is the key shown in the launchpad PPA page under \"Adding\nthis PPA to your system\", eg, ``41113ed57774ed19`` for `Embedded device ppa`_.\n\n\n.. _Embedded device ppa: https://launchpad.net/~nerdboy/+archive/ubuntu/embedded\n\n\nBuild and test with Tox\n-----------------------\n\nAs long as you have git and at least Python 3.6, then the \"easy\" dev\ninstall is to clone this repository and install `tox`_.\n\nAfter cloning the repository, you can run the current tests using either\ncmake or autotools with the ``tox`` command.  It will build a virtual\npython environment with most of the build dependencies (except the shared\nlibraries above and the autotools bits) and then run the tests. For cmake\nplus test coverage, you would first install your toolchain, the required\njson-c and hiredis libraries, redis-server, and tox, then run the following\ncommands:\n\n::\n\n  $ git clone https://github.com/VCTLabs/redis-ipc\n  $ cd redis-ipc\n  $ tox -e ctest\n\nThe above will start the redis server, build and run the tests with coverage\ndisplay, and stop the redis server. Alternatively, you can manipulate the\nserver manually and use ``tox -e tests`` instead.  To run the autotools\nbuild, you may need most or all of the following packages installed; for\nexample on Ubuntu you might need:\n\n* build-essential, make, libjson-c-dev, libhiredis-dev, redis-server\n  (from above)\n* autoconf, autoconf-archive, automake, pkg-config, libtool\n\n.. note:: The default libjson-c version (0.13) on Ubuntu focal is broken,\n  so you should add the PPA and install the 0.15 package instead.\n\nThere are several ``tox -e`` environment commands available:\n\n* ``ctest`` - build/run tests using ctest (**with** redis-server handling)\n* ``tests`` - build/run tests using cmake (**without** redis-server handling)\n* ``bionic`` - build/run tests using cmake (**with** redis-server handling)\n* ``grind`` - build/run using cmake and valgrind (**with** redis-server handling)\n* ``clean`` - clean the cmake build/ directory/files\n* ``auto`` - build/run tests using autotools (**with** redis-server handling)\n* ``autoclean`` - clean all the autotools cruft\n* ``lint`` - run the cpplint style checks\n\nWith the additional dependencies of LLVM/Clang \u003e= 12 you can try the LLVM\nsource-based coverage alternative to gcov/lcov-based coverage.  First install\nthe above toolchain, then run the following::\n\n  $ CC=clang CXX=clang++ tox -e clang\n\nIf you installed a newer version than 12, eg, 13, then prepend the version\nusing ``ENV_LLVM_VER=13`` to the above command.\n\n.. note:: Without the PPA, Bionic has an older GTest package and needs an\n          extra cmake arg.\n\nSee the `Github workflow files`_ for more details on the packages installed\nfor each runner OS environment.\n\n\n.. _tox: https://github.com/tox-dev/tox\n.. _Github workflow files: https://github.com/VCTLabs/redis-ipc/tree/develop/.github/workflows\n\n\nQuick Start Dev Environment\n===========================\n\nPackages should eventually be available in `Conda Forge`_ but you can\nalways use Conda's ``devenv`` support to build/install locally inside a\nConda environment. This is the recommended method if you can't use the\nPPA or Gentoo overlay. Set your default shell to ``bash`` if not already\nset.\n\nPrerequisites\n-------------\n\nInstall either Anaconda_ or Miniconda_ (we recommend miniconda) and add\nthe ``conda-forge`` channel, then install the ``conda-devenv`` package.\n\n* Download the miniconda linux-64 installer and run it\n* Let the installer add the conda init bits to your ``.bashrc``\n* Source your shell environment: ``source ~/.bashrc``\n* Install ``conda-devenv``::\n\n    conda config --append channels conda-forge\n    conda install -n base conda-devenv\n\n* Clone this repository::\n\n    git clone https://github.com/VCTLabs/redis-ipc.git\n\n* Create a new conda devenv environment::\n\n    cd redis-ipc/\n    conda devenv\n\nThis command will create the conda environment called ``redis-ipc-test``,\nwhich can take a few minutes to complete the first time. This will install\nthe conda toolchain and all required dependencies to build from source\n(see the contents of the ``environment.devenv.yml`` file for details).\n\n* Activate the environment::\n\n    conda activate redis-ipc-test\n\nNow you can use the usual ``cmake`` configure and build steps (see the\n`Cmake build`_ section below) or you can run the following one-liner\nfor a quick build-and-test::\n\n  ctest --build-config RelWithDebInfo --build-generator \"Ninja\" \\\n    --build-and-test . build --build-options -DRIPC_DISABLE_SOCK_TESTS=1 \\\n    -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX -DCMAKE_INSTALL_LIBDIR=lib \\\n    --test-command ctest -V --build-config RelWithDebInfo\n\n.. note:: The above command will omit running the socket tests, but if\n    already have a running ``redis`` server available, you can set the\n    ``RIPC_DISABLE_SOCK_TESTS`` argument to ``0`` instead.\n\nWhenever the above dependencies change or you alter your local conda\nenvironment, rebuild your ``devenv``::\n\n    conda devenv\n\nWhen finished, deactivate the environment::\n\n    conda deactivate\n\n\n.. _Conda Forge: https://anaconda.org/conda-forge/repo\n.. _Anaconda: https://www.anaconda.com/download\n.. _Miniconda: https://conda.io/miniconda.html\n\n\nDigression into the wonders of redis\n====================================\n\nredis_ is a powerful communications protocol that has been undeservedly\ntypecast, in the entertainment industry sense, as a backend service (database\nreplacement / database caching layer) for web applications. Many non-web\ndevelopers have not even heard of redis, and if they have, it was probably in\nthe context of peeking at some no-sql discussions to see what those crazy\nbig-server/cloud web-service developers are up to nowadays -- without the\nrealization that they have just stumbled across a general-purpose technology\nthat could likely be put to good use in one of their own non-webcentric\nprojects someday.\n\nMany of the features that make redis_ appealing for web applications are still\nrelevant for IPC among local applications:\n\n* `low overhead`_ -- maxes out at thousands of operations per second on\n  a 1GHz ARM and 10s of thousands of operations per second on a desktop-class CPU,\n  so system load is low for practical usage (even hundreds of operations per second)\n* wide variety of `language bindings`_ -- name your favorite non-toy language,\n  and there is a good chance the redis binding already exists\n* `convenient monitoring for troubleshooting`_ -- snoop all the incoming commands as a\n  human-readable stream of text, rather than needing specialized debugging tools to decode\n  binary messages in order to make *any* sense of them (and having to update said tools\n  every time a new custom message is defined)\n* atomic operations -- along with the ability to turn on monitoring, can make developing\n  multi-threaded and multi-process applications so much easier\n\nand finally one more which is specifically relevant for embedded software:\n\n* portable -- cross-compiles nicely, available as `openembedded recipe`_\n\n\nImportant caveat regarding redis security\n=========================================\n\nAfter covering the many attractions of redis_, it is only fair to point\nout an important limitation: the `lack of security features`_ (toy\nauthentication and no ability to restrict capabilities of connected\nclients) makes it highly unsuitable for access by untrusted users.\n\nSecurity-wise (and performance-wise, for that matter) it is better to\nuse unix sockets than a locally-bound tcp socket, so that filesystem\npermissions can be used to restrict socket access to a certain user or\ngroup. However always keep in mind that a rogue process running as that\nauthorized user or group gains full admin powers over the server,\nincluding snooping of all redis_ activity and making runtime changes to\nthe config.\n\nFor that reason, **never** use redis_ in security-sensitive environments\nunless there are solid external mechanisms for restricting  access (sandboxing,\ncustom SELinux policy limiting redis connections to specific trusted\napplications), and for security-critical tasks the  principle of layered\ndefense calls for a more secure store as an additional line of defense,\neg, credit card info cached in an unencrypted redis store would be such\na juicy target for any attackers who made it onto the server!\n\nExample of sensible scenarios for redis deployment:\n\n* Use redis to coordinate processes in regression test framework for assessing\n  current development status of an embedded device. Connections are limited to\n  localhost, and the only other users with accounts on the workstation are\n  trusted fellow teammates on the project.\n\n* Use redis to maintain settings and status for an embedded device. Connections\n  are again limited to localhost, and in normal operations (i.e. not development mode)\n  there are NO network logins enabled to the device.\n\n\nBuilding redis-ipc\n==================\n\nNow back to the star of this show, namely redis-ipc, starting with how to\nbuild and install it on your Linux development box (redis-ipc now supports\nboth autotools and CMake build systems, so in the following steps choose\none or the other).\n\n* Install build dependencies\n\n  * C/C++ toolchain\n  * pkg-config\n  * make\n  * cmake --or-- automake/autoconf/libtool\n  * hiredis_\n  * json-c_\n\n  On a development system with Debian/Ubuntu/Mint, this generally amounts to::\n\n    apt-get install libhiredis-dev libjson0-dev\n\n  with Gentoo::\n\n    emerge dev-libs/hiredis dev-libs/json-c\n\n  with Fedora (or CentOS/RHEL using EPEL_)::\n\n    yum install hiredis-devel json-c-devel\n\n* Check out redis-ipc source code (no tarball releases yet)::\n\n    git clone https://github.com/VCTLabs/redis-ipc.git\n    cd redis-ipc/\n\n\nCMake build\n-----------\n\nThe cmake tools can be run in several ways, and follow the standard set\nof (cmake) out-of-tree build steps.\n\n* Create the build directory::\n\n    mkdir build \u0026\u0026 cd build/\n\n* Configure the build::\n\n    cmake -DCMAKE_BUILD_TYPE=Debug ..\n\n* Build it::\n\n    make\n\n* Run the tests::\n\n    make check\n\n\nAutotools build\n---------------\n\nThe autotools build will create the standard set of Makefiles and the\n``configure`` script.\n\n* Generate and run configure::\n\n    ./autogen.sh \u0026\u0026 ./configure\n\n* Run the compile\n\n  * native build::\n\n      # also builds the library, in addition to some simple example apps\n      make\n\n  * cross-compile build::\n\n      # also builds the library, in addition to some simple example apps\n      make CROSS_COMPILE=\u003ctoolchain prefix\u003e SYSROOT=\u003ccross-compile staging area\u003e\n\n    * **CROSS_COMPILE** is everything up to (and including) the last '-' in the\n      tool names, e.g. if the C compiler is arm-none-linux-gnueabi-gcc then\n\n        **CROSS_COMPILE=arm-none-linux-gnueabi-**\n\n    * **SYSROOT** is the base path of your staging area that has cross-compiled\n      versions of the dependency libraries, e.g. if the cross-compiled hiredis\n      library is under\n\n        /home/sjl/yocto/build/tmp/sysroots/armv5te-poky-linux-gnueabi/usr/lib\n\n      then\n\n        **SYSROOT=/home/sjl/yocto/build/tmp/sysroots/armv5te-poky-linux-gnueabi/**\n\nRunning redis-ipc\n=================\n\nAfter building redis-ipc for the desired platform, try running it against a redis server.\nThe redis server needs to be configured to use a unix socket, the path of which\ndefaults to $RPC_RUNTIME_DIR/socket, where RPC_RUNTIME_DIR defaults to /tmp/redis-ipc\nbut may be overridden at compile time. The socket path may also be overridden at\nruntime with the environment variable ``RIPC_SERVER_PATH``.\n\nredis.conf excerpt::\n\n  # Accept connections on the specified port, default is 6379.\n  # If port 0 is specified Redis will not listen on a TCP socket.\n  port 0\n\n  # Specify the path for the unix socket that will be used to listen for\n  # incoming connections. There is no default, so Redis will not listen\n  # on a unix socket when not specified.\n\n  unixsocket /tmp/redis-ipc/socket\n  # this allows connections by the user who starts the server (or by root, of course)\n  unixsocketperm 500\n  # alternatively, allow connections from the group under which server was started\n  #unixsocketperm 550\n\nNext verify the combination of redis-server and redis-ipc library are working together\nby running the simple example programs, which each end in *_test*. Use LD_LIBRARY_PATH\nto run the programs from the build directory (or, if cross-compiling, a copy of build\ndirectory loaded on the embedded target) prior to a system-wide install ::\n\n  LD_LIBRARY_PATH=. ./command_result_test\n\nExpected output for each example app has been provided in files ending in *_test.out*.\n\nDeveloping with redis-ipc\n=========================\n\nAs mentioned in the intro, redis-ipc implements the following mechanisms:\n\n* command queues\n* settings\n* status\n* state\n* event channels\n\n**Command queues** are a method for any component to request an action from\nanother component, and receive a result after the command has been processed.\nEach component that exports actions to other components would own one or\nmore command queues. When sending a command, the queue is specified by\ncomponent and \"subqueue\" to allow components to manage multiple queues\nthat are processed with different priorities.\n\n**Settings** are hashes representing the current configuration of each component.\nThe settings for a single component can all be read atomically and written\natomically, to avoid bugs where one component gets into an inconsistent state\nby reading settings when partially updates by another component. Note that\nsettings changes across multiple components are *not* atomic, so complicated\ndesigns where settings consistency depends on updating multiple components at\nthe same time would need to implement that separately, e.g. with some form of\nlocking.\n\n**Status** are also hashes, but represent a component's current runtime state\ninstead of representing how a component has been configured. While settings\nare likely written by a single component, each component maintains its own\nstatus with any state info that is of interest to one or more other components.\n\n**State** is a single string value representing the currently active state of a\ncomponent that incorporates a state machine.\n\nEvent channels are an efficient way to broadcast events from one component to\nany others that might be interested (i.e. \"subscribers). At the toplevel,\nevent channels are grouped into normal channels and debug channels that are\naccessed by a separate set of calls. This segregation of normal events from\ndebug messages makes it obvious in the code which messages are only meant for\ndebugging the component, and makes it easy to log/observe detailed debug info\nwhile normal subscribers can listen to normal events without having to discard\na flood of debug events when debugging is enabled (by runtime configuration or\nspecial debug compile).\n\nMost data handled by redis-ipc (commands, command replies, settings, status,\nand events) is formatted into `JSON objects`_, meaning associative arrays\ncontaining key/value pairs. The only exception is that\nan individual field within a setting or status object can be accessed as\na cstring. json-c library is used as the JSON implementation. Actually,\ndebug events are another exception, being specified with a numeric priority\nlevel and a message with printf-style format + arguments.\n\nAs typical for a C library dealing with dynamically created objects, reference\ncounting is used to ensure memory is released at the proper time. redis-ipc\nreturns new JSON objects with one reference that the caller is responsible for\nfreeing with json_object_put(). C++ applications can make use of the json.hh\nwrapper supplied in redis-ipc that takes and drops references on the underlying\njson-c json_object when appropriate ::\n\n  #include \"json.hh\"\n\n  ...\n\n  void monitor_printer()\n  {\n    redis_ipc_subscribe_events(\"printer\", NULL);\n    // does not take a new reference on json_object being wrapped\n    // because redis_ipc_get_message_blocking() already took one\n    json next_printer_event(redis_ipc_get_message_blocking());\n    cout \u003c\u003c \"Event priority:\" \u003c\u003c next_printer_event.get_field(\"priority\");\n  }\n  // reference to  json_object dropped when next_printer_event goes out of scope\n\n**Common API**\n\nEvery thread and process using redis-ipc must individually call the\ninit function prior to any of the other calls ::\n\n  int redis_ipc_init(const char *this_component, const char *this_thread);\n\nExample::\n\n  // monitor process (or thread) of printer software component\n  redis_ipc_init(\"printer\", \"monitor\");\n\nWhen redis-ipc is no longer needed, there is a corresponding function to\nfree resources ::\n\n  int redis_ipc_cleanup(pid_t tid);\n\nExamples::\n\n  // single process closing down\n  redis_ipc_cleanup(getpid());\n\n  // one thread of multi-thread process closing down\n  // see gettid() definition in redis_ipc.c if your libc lacks it\n  redis_ipc_cleanup(gettid());\n\n**Command queue API**\n\nCommand queues currently have a blocking implementation.\n\nThe JSON object for a command automatically gets 2 attributes added\nas a part of submission\n\n* command_id : unique ID for command, including component name and thread id\n  of the submitter\n* results_queue : name of queue on which the result object should be pushed\n  when command has been processes, also based on component name and thread id\n  (each thread submitting commands has its own queue to wait on)\n\nThe JSON object for reporting back a command result to the submitter\nautomatically gets the command_id added, to ensure commands and their\nresults can be reliably associated.\n\n**Important note**: To avoid memory leaks, callers of command queue API must\ndrop references to command objects and result objects when finished with them.\n\nProcesses/threads that execute commands block until a command arrives ::\n\n  json_object * redis_ipc_receive_command_blocking(const char *subqueue,\n                                              unsigned int timeout);\n\nthen when another process/thread submits a command, it will block until the\ncommand has been completed (or timeout for waiting has expired) ::\n\n  json_object * redis_ipc_send_command_blocking(const char *dest_component,\n                                              const char *subqueue,\n                                              json_object *command,\n                                              unsigned int timeout);\n\nwhich happens when the executing process/thread reports back the command\nresults with ::\n\n  int redis_ipc_send_result(const json_object *completed_command, json_object *result);\n\nExample::\n\n  // printer component has 2 queues, \"print\" and \"cancel\"\n  // because cancel commands need a separate queue that is checked even\n  // while printing or else an in-progress job can't be canceled\n\n  // non-printer component requests printing of file\n  json_object *command = json_object_new_object();\n  json_object_object_add(command, \"pagesize\",\n                         json_object_new_string(\"A4\"));\n  json_object_object_add(command, \"file\",\n                         json_object_new_string(\"/tmp/job1231.pdf\"));\n  json_object *result = redis_ipc_send_command_blocking(\"printer\", \"print\", command, timeout);\n  json_object *job_id_obj = json_object_object_get(result, \"job-id\");\n  char *job_id_str = json_object_get_string(job_id_obj);\n  json_object_put(command);\n  json_object_put(result);\n  json_object_put(job_id_obj);\n\n  // non-printer component later decides to cancel print job\n  command = json_object_new_object();\n  json_object_object_add(command, \"job-id\",\n                         json_object_new_string(job_id_str));\n  json_object *result = redis_ipc_send_command_blocking(\"printer\", \"cancel\", command, timeout);\n  json_object_put(command);\n  json_object_put(result);\n\n\n**Settings API**\n\nMultiple settings for a single component can be updated atomically\nas multiple key/value pairs in a JSON object ::\n\n  int redis_ipc_write_setting(const char *owner_component, const json_object *fields);\n\nor a single setting can be updated by name, with both name and value supplied\nas strings ::\n\n  int redis_ipc_write_setting_field(const char *owner_component, const char *field_name,\n                                    const char *field_value);\n\nSimilarly, all settings belonging to a single component can be read as\nJSON object containing key/value pairs ::\n\n  json_object * redis_ipc_read_setting(const char *owner_component);\n\nor a single setting can be requested by name, with both name and returned value\nas strings ::\n\n  char * redis_ipc_read_setting_field(const char *owner_component, const char *field_name);\n\n**Status API**\n\nMultiple status for a single component can be updated atomically\nas multiple key/value pairs in a JSON object ::\n\n  int redis_ipc_write_status(const json_object *fields);\n\nor a single status can be updated by name, with both name and value supplied\nas strings ::\n\n  int redis_ipc_write_status_field(const char *field_name, const char *field_value);\n\nSimilarly, all settings belonging to a single component can be read as\nJSON object containing key/value pairs ::\n\n  json_object * redis_ipc_read_status(const char *owner_component);\n\nor a single setting can be requested by name, with both name and returned value\nas strings ::\n\n  char * redis_ipc_read_status_field(const char *owner_component, const char *field_name);\n\n**Event API**\n\nEvent channels currently have a blocking implementation for event listeners.\n\nChannels for normal events are grouped according to component that\ngenerates the event. When a component sends a normal message it must also\nsupply a \"subchannel\" as the most specific part of this addressing scheme, with\neach subchannel hopefully given a meaningful name to indicate what sort of\nmessages subscribers should expect.\n\nWhen a component sends a debug message, it supplies a debug level, so that the\ndebug channels can skip sending debug messages that are higher than the\ncurrently configured debug verbosity (although, at the moment verbosity happens\nto be hard-coded to the value 5, meaning everything 5 and under gets\nbroadcast...)\n\nListeners must sign up ahead of time to get the events of interest;\nthere is no backlog for catching up on events posted to a channel before\na listener subscribed. Event channels of interest are specified by\nthe component generating the events and a subchannel name, where subchannel\nname may represent a topic that applies to multiple components.\n\n**Important note**: To avoid memory leaks, callers of event API must drop\nreferences to event objects when finished with them.\n\nListeners can subscribe to channels with normal events ::\n\n  int redis_ipc_subscribe_events(const char *component, const char *subchannel)\n\nand/or channels with debug events ::\n\n  int redis_ipc_subscribe_debug(const char *component);\n\nExamples::\n\n  // subscribe to all printer-related events\n  redis_ipc_subscribe_events(\"printer\", NULL);\n\n  // subscribe to all warnings that should be displayed to user\n  redis_ipc_subscribe_events(NULL, \"warnings\");\n\n  // subscribe specifically to warnings from printer component\n  redis_ipc_subscribe_events(\"printer\", \"warnings\");\n\n  // subscribe to debug messages from printer component\n  redis_ipc_subscribe_debug(\"printer\");\n\nA component generates a normal event with one or more named attributes\ncontained in a JSON object, and broadcasts it on one of its subchannels ::\n\n  int redis_ipc_send_event(const char *subchannel, json_object *message)\n\nExample::\n\n  // printer component sends a low-on-paper event to its warning subchannel\n  json_object *event = json_object_new_object();\n  json_object_object_add(event, \"severity\",\n                         json_object_new_string(\"2\"));\n  json_object_object_add(event, \"type\",\n                         json_object_new_string(\"LOW-ON-PAPER\"));\n  redis_ipc_send_event(\"warnings\", event);\n\n\nor broadcasts a debug event with a debug level and printf-formatted message\nthat then get turned into a JSON object ::\n\n  int redis_ipc_send_debug(unsigned int debug_level, const char *format, ...)\n\nExample::\n\n  // completely hypothetical example, ahem...\n  redis_ipc_send_debug(RIPC_DBG_ERROR, \"redis_ipc_send_command_blocking(): invalid result\");\n\nListening components can retrieve the next normal/debug event ::\n\n  json_object * redis_ipc_get_message_blocking(void)\n\nExample::\n\n  json object *message = redis_ipc_get_message_blocking();\n  // do stuff with message\n  json_object_put(message);\n\nTesting/troubleshooting with redis-ipc\n======================================\n\nOne of the great features of using redis for system-wide IPC is the ability\nto watch the interactions between components using the **monitor** command\nfrom redis-cli utility. Another great use is in unit testing of a single\ncomponent, where a test script can push commands, update settings, check\nstatus and so forth. For both reasons it is useful to understand how each\nfeature is implemented as redis data structures.\n\n@@@TODO\n\nSince redis-ipc requires the redis server to use a unix socket rather than tcp,\nremember to specify the socket path when running redis-cli ::\n\n  redis-cli -s /tmp/redis-ipc/socket\n\n.. _redis: http://redis.io/\n.. _low overhead: http://www.bango29.com/squeezing-cubieboard-for-performance/\n.. _language bindings: http://redis.io/clients\n.. _convenient monitoring for troubleshooting: http://redis.io/commands/MONITOR\n.. _openembedded recipe: http://cgit.openembedded.org/cgit.cgi/meta-openembedded/tree/meta-oe/recipes-extended/redis/redis_2.6.9.bb?h=master\n.. _lack of security features: http://redis.io/topics/security\n.. _hiredis: https://github.com/redis/hiredis\n.. _json-c: https://github.com/json-c/json-c/wiki\n.. _EPEL: https://fedoraproject.org/wiki/EPEL\n.. _JSON objects: https://en.wikipedia.org/wiki/Json\n\n.. |ci| image:: https://github.com/VCTLabs/redis-ipc/actions/workflows/smoke.yml/badge.svg\n    :target: https://github.com/VCTLabs/redis-ipc/actions/workflows/smoke.yml\n    :alt: GitHub CI Smoke Test Status\n\n.. |codeql| image:: https://github.com/VCTLabs/redis-ipc/actions/workflows/codeql.yml/badge.svg\n    :target: https://github.com/VCTLabs/redis-ipc/actions/workflows/codeql.yml\n    :alt: GitHub CI CodeQL Status\n\n.. |conda-dev| image:: https://github.com/VCTLabs/redis-ipc/actions/workflows/conda-dev.yml/badge.svg\n    :target: https://github.com/VCTLabs/redis-ipc/actions/workflows/conda-dev.yml\n    :alt: GitHub CI Conda-dev Status\n\n.. |cpplint| image:: https://github.com/VCTLabs/redis-ipc/actions/workflows/cpplint.yml/badge.svg\n    :target: https://github.com/VCTLabs/redis-ipc/actions/workflows/cpplint.yml\n    :alt: GitHub CI Cpplint Status\n\n.. |coverage| image:: https://github.com/VCTLabs/redis-ipc/actions/workflows/coverage.yml/badge.svg\n    :target: https://github.com/VCTLabs/redis-ipc/actions/workflows/coverage.yml\n    :alt: Coverage workflow\n\n.. |pre| image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit\u0026logoColor=white\n   :target: https://github.com/pre-commit/pre-commit\n   :alt: pre-commit\n\n.. |cov| image:: https://raw.githubusercontent.com/VCTLabs/redis-ipc/badges/develop/test-coverage.svg\n    :target: https://github.com/VCTLabs/redis-ipc/\n    :alt: Test coverage\n\n.. |license| image:: https://badges.frapsoft.com/os/gpl/gpl.png?v=103\n    :target: https://opensource.org/licenses/GPL-2.0/\n    :alt: License\n\n.. |tag| image:: https://img.shields.io/github/v/tag/VCTLabs/redis-ipc?color=green\u0026include_prereleases\u0026label=latest%20release\n    :target: https://github.com/VCTLabs/redis-ipc/releases\n    :alt: GitHub tag (latest SemVer, including pre-release)\n\n.. |std| image:: https://img.shields.io/badge/Standards-C++17%20%20C17-00000.svg\n    :target: https://en.cppreference.com/w/cpp/compiler_support/17.html\n    :alt: Other standards\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvctlabs%2Fredis-ipc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvctlabs%2Fredis-ipc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvctlabs%2Fredis-ipc/lists"}