Utilities for the Syndicated Actor Model
Go to file
Emery Hemingway 79a156715b Use new dataspace patterns 2024-04-22 14:49:14 +02:00
src Use new dataspace patterns 2024-04-22 14:49:14 +02:00
.envrc syndesizer: absorb sqlite_actor 2024-01-09 14:01:38 +02:00
.gitignore Preserves: #! is now #: 2024-02-08 15:50:19 +00:00
README.md SQL: decompose SQL statements and assert errors 2024-04-09 10:14:38 +01:00
Tupfile Add http_driver from syndicate-nim 2024-04-07 18:17:18 +01:00
Tuprules.tup syndesizer: absorb sqlite_actor 2024-01-09 14:01:38 +02:00
assertions.prs Add XSLT processor 2024-02-09 15:24:45 +00:00
base64.prs Add base64 decoder 2024-04-07 18:15:28 +01:00
config.prs Add http_driver from syndicate-nim 2024-04-07 18:17:18 +01:00
inotify_actor.prs Add inotify_actor 2023-10-10 19:37:30 +01:00
lock.json Update syndicate library 2024-04-09 10:14:58 +01:00
mountpoints.prs Refactor for Syndicate API update 2024-01-09 13:30:00 +02:00
mpv.config-example.pr Adjust to Syndicate-nim changes 2023-05-18 12:41:52 +01:00
net_mapper.prs Add lost net_mapper code 2023-07-01 16:06:16 +01:00
rofi.prs Add rofi_script_actor 2023-10-26 17:20:43 +01:00
shell.nix Do not specify "src" in Direnv Nix expression 2024-04-07 18:17:18 +01:00
sql.prs SQL: decompose SQL statements and assert errors 2024-04-09 10:14:38 +01:00
syndicate_utils.nimble Use new dataspace patterns 2024-04-22 14:49:14 +02:00

README.md

Syndicate utils

Syndesizer

A Syndicate multitool that includes a number of different actors that become active via configuration.

Think of it as a Busybox for Syndicate, if Busybox was created before POSIX.

Whether you use a single instance for many protocols or many specialized instances is up to you.

Cache

Observes patterns and reässert the values captured for a given lifetime. Takes the argument <cache { dataspace: #!any lifetime: float }>. The lifetime of a cache counts down from moment a value is asserted.

Example configuration:

? <nixspace ?nixspace> [
  ; Require the nix_actor during observations.
  ?nixspace> ? <Observe <rec eval _> _> [
    $config <require-service <daemon nix_actor>> ]
  ?nixspace> ? <Observe <rec realise _> _> [
    $config <require-service <daemon nix_actor>> ]

  ; Cache anything captured by observers in the $nixspace for an hour.
  ; The nix_actor is not required during caching.
  $config <require-service <daemon syndesizer>>
  $config ? <service-object <daemon syndesizer> ?cap> [
    $cap <cache { dataspace: $nixspace lifetime: 3600.0 }> ]
]

File System Usage

Summarize the size of file-system directory. Equivalent to du -s -b. Query the size of a directory in bytes by observing <file-system-usage "/SOME/PATH" ?size>.

# Configuration example

? <exposed-dataspace ?ds> [

  <require-service <daemon syndesizer>>
  ? <service-object <daemon syndesizer> ?cap> [
    $cap <file-system-usage { dataspace: $ds }>
  ]

]

HTTP driver

Experimental HTTP server that services requests using some version of the http Syndicate protocol schema.

# Configuration example

let ?not-found = dataspace
$not-found ? <request _ ?res> [
  $res ! <status 503 "Service unavailable">
  $res ! <done "No binding here.">
]

let ?greeting = dataspace
$greeting ? <request _ ?res> [
  $res ! <status 200 "ok">
  $res ! <chunk "Hello world">
  $res ! <done "!">
]

let ?http = dataspace
$http [
  <http-bind #f 80 get [ ] $not-found>
  <http-bind #f 80 get [|...|] $not-found>
  <http-bind #f 80 get ["hello"] $greeting>
]

? <service-object <daemon http-driver> ?cap> [
  $cap <http-driver { dataspace: $http }>
]

<daemon http-driver {
  argv: [ "/bin/syndesizer" ]
  clearEnv: #t
  protocol: application/syndicate
}>

<require-service <daemon http-driver>>

JSON Socket Translator

Communicate with sockets that send and receive lines of JSON using <send …> and <recv …> messages.

Do not send messages into the dataspace configure with <json-socket-translator …> until <connected @socketPath string> is asserted.

# MPV configuration example
<require-service <daemon mpv-server>>

<daemon mpv-server {
  argv: [
    "/run/current-system/sw/bin/mpv"
    "--really-quiet"
    "--idle=yes"
    "--no-audio-display"
    "--input-ipc-server=/run/user/1000/mpv.sock"
    "--volume=75"
  ]
  protocol: none
}>

let ?mpvSpace = dataspace

? <service-state <daemon mpv-server> ready> [
  <require-service <daemon syndesizer>>
  ? <service-object <daemon syndesizer> ?cap> [
    $cap <json-socket-translator {
      dataspace: $mpvSpace
      socket: <unix "/run/user/1000/mpv.sock">
    }>
  ]
]

$mpvSpace [

  # announce the dataspace when the translator is connected
  ? <connected $socketPath> [
    $config <mpv $mpvSpace>
    $config <bind <ref { oid: "mpv" key: #x"" }> $mpvSpace #f>
  ]

  # translate <play-file …> to an MPV command
  ?? <play-file ?file> [
    ! <send { "command": ["loadfile" $file "append-play"] }>
  ]

  # clear the playlist on idle so it doesn't grow indefinitely
  ?? <recv {"event": "idle"}> [
    ! <send { "command": ["playlist-clear"] }>
  ]
]

JSON Stdio Translator

Executes a command, parses its JSON output, converts to record <recv @jsonData any>, and publishes and messages it to a dataspace.

# Configuration example
<require-service <daemon syndesizer>>

let ?ds = dataspace
<bind <ref {oid: "syndicate" key: #x""}> $ds #f>

? <service-object <daemon syndesizer> ?cap> [
  $cap <json-stdio-translator {
    argv: [
      "yt-dlp"
      "--dump-json"
      "https://youtu.be/RR9GkEXDvog"
    ]
    dataspace: $ds
  }>
]

Pulse proxy

A proxy actor that passes assertions and messages to a configured capability but only asserts observations on a a periodic pulse. This can be used to implement polling behavior.

# Example config
let ?ds = dataspace

<require-service <daemon syndesizer>>
? <service-object <daemon syndesizer> ?cap> [
  $cap <pulse {dataspace: $ds}>
]

$ds ? <pulse 3600.0 ?proxy> [
  $proxy ? <assertion-updated-hourly ?value> [
    $log ! <log "-" {assertion-updated-hourly: $value}>
  ]
]

SQLite

Readonly access to SQLite databases. Asserts rows as records in response to SQL query assertions. Dynamic updates are not implemented.

Can be disabled by passing --define:withSqlite=no to the Nim compiler.

# Configuration example
<require-service <daemon syndesizer>>

let ?sqlspace = dataspace

? <service-object <daemon syndesizer> ?cap> [
  $cap <sqlite {
    dataspace: $sqlspace
    database: "/var/db/example.db"
  }>
]

let ?tuplespace = dataspace

$sqlspace <query "SELECT id, name FROM stuff" $tuplespace>

$tuplespace [
  ? [?id ?name] [
    $log ! <log "-" { row: <example-row $id $name> }>
  ]
  ? <sqlite-error ?msg ?ctx> [
    $log ! <log "-" { msg: $msg ctx: $ctx }>
  ]
]

XML translator

Translates between Preserves and XML according to the Conventions for Common Data Types.

Examples:

  • <xml-translation "<foo a=\"1\"> <bar>hello world!</bar></foo>" <foo {"a": 1}<bar "hello world!">>>
  • <xml-translation "" [#t #f]>
  • <xml-translation "<<</>>" #f>
# Configuration example
? <sharedspace ?ds> [
  $ds ? <Observe <rec xml-translation _> _> $config [
    $config <require-service <daemon syndesizer>>
    $config ? <service-object <daemon syndesizer> ?cap> [
      $cap <xml-translator { dataspace: $ds }>
    ]
  ]
]

mintsturdyref

A utility for minting Sturdyrefs.

mount_actor

Actor for mounting filesystems on Linux.

Sample Syndicate server script:

# Assert a file-system we want to mount.
<mount "/dev/sda3" "/boot" "vfat">

# Transform mount assertions into mount status observations.
? <mount ?source ?target ?fs> [
  ? <mount $source $target $fs _> [ ]
]

# Assert mounting succeded.
? <mount _ ?target _ #t> [
  <service-state <mountpoint $target> ready>
]
# Assert mount failed.
? <mount _ ?target _ <failure _>> [
  <service-state <mountpoint $target> failed>
]

# Assert the details into the machine dataspace.
? <machine-dataspace ?machine> [
  $config ? <mount ?source ?target ?fs ?status> [
    $machine <mount $source $target $fs $status>
  ]
]

# Require the mount_actor daemon.
<require-service <daemon mount_actor>>
<daemon mount_actor {
  argv: ["/home/emery/src/bin/mount_actor"]
  protocol: application/syndicate
}>

# Pass the daemon the config dataspace.
? <service-object <daemon mount_actor> ?cap> [
  $cap { dataspace: $config }
]

msg

A utility that parses its command-line arguments as Preserves and send them as messages to $SYNDICATE_ROUTE. When called as assert (by a symlink or a rename) it will make assertions instead.

PostgreSQL

Readonly access to PostgreSQL databases. Asserts rows as records in response to SQL query assertions. Dynamic updates are not implemented.

Can be disabled by passing --define:withPostgre=no to the Nim compiler.

# Configuration example
<require-service <daemon postgre_actor>>

let ?sqlspace = dataspace

? <service-object <daemon postgre_actor> ?cap> [
  $cap <postgre {
     dataspace: $sqlspace
     connection: [
       ["host" "example.com"]
       ["dbname" "foobar"]
       ["user" "hackme"]
     ]
   }>
]

let ?tuplespace = dataspace

$sqlspace <query "SELECT id, name FROM stuff" $tuplespace>

$tuplespace ? [?id ?name] [
  $log ! <log "-" { row: <example-row $id $name> }>
]

preserve_process_environment

This utility serializes it's process environment to Preserves and prints it to stdout. It can be used to feed the environment variables of a nested child of the Syndicate server back to the server. For example, to retreive the environmental variables that a desktop manager passed on to its children.

SQLite

Readonly access to SQLite databases. Asserts rows as records in response to SQL query assertions. Dynamic updates are not implemented.

Can be disabled by passing --define:withSqlite=no to the Nim compiler.

# Configuration example
<require-service <daemon sqlite_actor>>

let ?sqlspace = dataspace

? <service-object <daemon sqlite_actor> ?cap> [
  $cap <sqlite {
    dataspace: $sqlspace
    database: "/var/db/example.db"
  }>
]

let ?tuplespace = dataspace

$sqlspace <query "SELECT id, name FROM stuff" $tuplespace>

$tuplespace ? [?id ?name] [
  $log ! <log "-" { row: <example-row $id $name> }>
]

syndump

Utility for printing assertions and messages. Parses the command-line arguments as a pattern, connects a dataspace via $SYNDICATE_ROUTE, and writes observations to standard-output. Published assertions are prefixed by the + character, retractions by -, and messages by !.

Example

# Print patterns in use, filter down with AWK to only the published patterns.
$ FS=':' syndump '<Observe ? _>' | awk -F : '/^+/ { print $2 }'

XSLT processor

Perform XML stylesheet transformations. For a given textual XSLT stylesheet and a textual XML document generate an abstract XML document in Preserves form. Inputs may be XML text or paths to XML files.

# Configuration example
let ?ds = dataspace
$ds [
  ? <xslt-transform "/stylesheet.xls" "/doc.xml" ?output> [
    ? <xml-translation ?text $output> [
      $log ! <log "-" { xslt-output: $text }>
    ]
  ]
]

<require-service <daemon xslt_actor>>
? <service-object <daemon xslt_actor> ?cap> $cap [
  <xml-translator { dataspace: $ds }>
  <xslt { dataspace: $ds }>
]