Absorbed by the Syndesizer
https://git.syndicate-lang.org/ehmry/syndicate_utils
This commit is contained in:
parent
11af5d9422
commit
4f27d03815
|
@ -1 +0,0 @@
|
||||||
/nim.cfg
|
|
36
README.md
36
README.md
|
@ -1,37 +1,3 @@
|
||||||
# websocket_actor
|
# websocket_actor
|
||||||
|
|
||||||
A [syndicated actor](https://syndicate-lang.org/) for communicating JSON to websocket servers.
|
Absorbed by the [Syndesizer](https://git.syndicate-lang.org/ehmry/syndicate_utils).
|
||||||
|
|
||||||
The actor observes `{dataspace: #!any url: string }` assertions and connects to a websocket endpoint. During the lifetime of the connection a `<connected $URL>` assertion is made. Messages recieved from the server are sent to the dataspace wrapped in `<recv …>` records and messages observed as `<send …>` are sent to the server.
|
|
||||||
|
|
||||||
Unfortunately this utility is only as useful and reasonable as the websocket server it is connected to.
|
|
||||||
|
|
||||||
## Example:
|
|
||||||
|
|
||||||
### Syndicate server configuration:
|
|
||||||
```
|
|
||||||
<require-service <daemon websocket_actor>>
|
|
||||||
<daemon websocket_actor {
|
|
||||||
argv: ["/bin/websocket_actor"]
|
|
||||||
protocol: application/syndicate
|
|
||||||
env: { BUILD_SUM: $sum }
|
|
||||||
}>
|
|
||||||
|
|
||||||
let ?exported-dataspace = dataspace
|
|
||||||
<service-object <daemon websocket_actor> ?cap> [
|
|
||||||
$cap { dataspace: $exported-dataspace url: "ws://127.0.0.1:5225/" }
|
|
||||||
]
|
|
||||||
|
|
||||||
<bind <ref { oid: "syndicate" key: #x"" }> $exported-dataspace #f>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Shell
|
|
||||||
```
|
|
||||||
# Use the "syndump" utility to log '<recv …>' records from the background.
|
|
||||||
syndump '<recv ?>' &
|
|
||||||
|
|
||||||
# Use the "msg" utilite to send '<send …>' records.
|
|
||||||
# The message command wraps its arguments in a record with a label set to argv[0].
|
|
||||||
cp $(which msg) send
|
|
||||||
send '{ type: "command" body: { type: "body" text: "fuck off webdevs"} }'
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
include ../syndicate-nim/depends.tup
|
|
||||||
NIM_FLAGS += --path:$(TUP_CWD)/../syndicate-nim/src
|
|
||||||
NIM_FLAGS += --path:$(TUP_CWD)/../nimble/ws/src
|
|
||||||
NIM_GROUPS += $(TUP_CWD)/<lock>
|
|
|
@ -1 +0,0 @@
|
||||||
{"depends":[{"method":"fetchzip","packages":["hashlib"],"path":"/nix/store/v03nzlpdgbfxd2zhcnkfbkq01d5kqxcl-source","rev":"84e0247555e4488594975900401baaf5bbbfb53","sha256":"1pfczsv8kl36qpv543f93d2y2vgz2acckssfap7l51s2x62m6qwx","srcDir":"","url":"https://github.com/khchen/hashlib/archive/84e0247555e4488594975900401baaf5bbbfb53.tar.gz"},{"method":"fetchzip","packages":["nimcrypto"],"path":"/nix/store/zyr8zwh7vaiycn1s4r8cxwc71f2k5l0h-source","ref":"traditional-api","rev":"602c5d20c69c76137201b5d41f788f72afb95aa8","sha256":"1dmdmgb6b9m5f8dyxk781nnd61dsk3hdxqks7idk9ncnpj9fng65","srcDir":"","url":"https://github.com/cheatfate/nimcrypto/archive/602c5d20c69c76137201b5d41f788f72afb95aa8.tar.gz"},{"method":"fetchzip","packages":["npeg"],"path":"/nix/store/ffkxmjmigfs7zhhiiqm0iw2c34smyciy-source","ref":"1.2.1","rev":"26d62fdc40feb84c6533956dc11d5ee9ea9b6c09","sha256":"0xpzifjkfp49w76qmaylan8q181bs45anmp46l4bwr3lkrr7bpwh","srcDir":"src","url":"https://github.com/zevv/npeg/archive/26d62fdc40feb84c6533956dc11d5ee9ea9b6c09.tar.gz"},{"method":"fetchzip","packages":["preserves"],"path":"/nix/store/nrxd0z8mxmdphw49c6p4n9lmmq0iq5pq-source","ref":"20231019","rev":"a2dc5becc0596d52ab205d869b7c167c0b562fb4","sha256":"09jygr7ynzh6vp2p54dgq2qz651d3lgvypkjwjp74zzp3jgwz7g5","srcDir":"src","url":"https://git.syndicate-lang.org/ehmry/preserves-nim/archive/a2dc5becc0596d52ab205d869b7c167c0b562fb4.tar.gz"},{"method":"fetchzip","packages":["syndicate"],"path":"/nix/store/1y3nnpp2mhxqmdb3xh4c4k5k5l9hhqk3-source","ref":"20231019","rev":"57b99b20e7db1b97b1cb9c6df574bd13983c26fc","sha256":"1kgb3a78igs37xkmv8cbaxa17qdjf2h43vdmpda517c9086ggsn5","srcDir":"src","url":"https://git.syndicate-lang.org/ehmry/syndicate-nim/archive/57b99b20e7db1b97b1cb9c6df574bd13983c26fc.tar.gz"},{"method":"fetchzip","packages":["ws"],"path":"/nix/store/zd51j4dphs6h1hyhdbzdv840c8813ai8-source","ref":"0.5.0","rev":"9536bf99ddf5948db221ccb7bb3663aa238a8e21","sha256":"0j8z9jlvzb1h60v7rryvh2wx6vg99lra6i62whf3fknc53l641fz","srcDir":"src","url":"https://github.com/treeform/ws/archive/9536bf99ddf5948db221ccb7bb3663aa238a8e21.tar.gz"}]}
|
|
|
@ -1,5 +0,0 @@
|
||||||
let
|
|
||||||
syndicate = builtins.getFlake "syndicate";
|
|
||||||
pkgs =
|
|
||||||
import <nixpkgs> { overlays = builtins.attrValues syndicate.overlays; };
|
|
||||||
in pkgs.nim2Packages.syndicate_utils
|
|
|
@ -1,3 +0,0 @@
|
||||||
include_rules
|
|
||||||
: websocket_actor.nim | $(SYNDICATE_PROTOCOL) ../<schema> |> !nim_bin |> {bin}
|
|
||||||
: {bin} |> !assert_built |>
|
|
|
@ -1,56 +0,0 @@
|
||||||
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
|
||||||
# SPDX-License-Identifier: Unlicense
|
|
||||||
|
|
||||||
import std/[asyncdispatch, json]
|
|
||||||
import preserves, preserves/jsonhooks
|
|
||||||
import syndicate
|
|
||||||
from syndicate/relays import connectStdio
|
|
||||||
import ws
|
|
||||||
|
|
||||||
type
|
|
||||||
Args* {.preservesDictionary.} = object
|
|
||||||
dataspace: Cap
|
|
||||||
url: string
|
|
||||||
|
|
||||||
SendJson* {.preservesRecord: "send".} = object
|
|
||||||
data: JsonNode
|
|
||||||
RecvJson* {.preservesRecord: "recv".} = object
|
|
||||||
data: JsonNode
|
|
||||||
|
|
||||||
runActor("websocket-json-actor") do (root: Cap; turn: var Turn):
|
|
||||||
connectStdio(turn, root)
|
|
||||||
during(turn, root, ?Args) do (ds: Cap, url: string):
|
|
||||||
let facet = turn.facet
|
|
||||||
var
|
|
||||||
ws: WebSocket
|
|
||||||
connectedHandle: Handle
|
|
||||||
newWebSocket(url).addCallback(turn) do (turn: var Turn; sock: WebSocket):
|
|
||||||
ws = sock
|
|
||||||
let connectedHandle = publish(turn, ds, initRecord("connected", url.toPreserve))
|
|
||||||
var fut: Future[(Opcode, string)]
|
|
||||||
proc recvMessage() {.gcsafe.} =
|
|
||||||
fut = receivePacket ws
|
|
||||||
addCallback(fut, facet) do (turn: var Turn):
|
|
||||||
let (opcode, data) = read fut
|
|
||||||
case opcode
|
|
||||||
of Text:
|
|
||||||
message(turn, ds,
|
|
||||||
RecvJson(data: data.parseJson))
|
|
||||||
of Binary:
|
|
||||||
message(turn, ds,
|
|
||||||
initRecord("recv", cast[seq[byte]](data).toPreserve))
|
|
||||||
of Ping:
|
|
||||||
asyncCheck(turn, ws.send(data, Pong))
|
|
||||||
of Pong, Cont:
|
|
||||||
discard
|
|
||||||
of Close:
|
|
||||||
retract(turn, connectedHandle)
|
|
||||||
stderr.writeLine "closed connection with ", url
|
|
||||||
stop(turn)
|
|
||||||
return
|
|
||||||
recvMessage()
|
|
||||||
recvMessage()
|
|
||||||
onMessage(turn, ds, ?SendJson) do (data: JsonNode):
|
|
||||||
asyncCheck(turn, ws.send($data, Text))
|
|
||||||
do:
|
|
||||||
close(ws)
|
|
|
@ -1,6 +0,0 @@
|
||||||
bin = @["websocket_actor"]
|
|
||||||
license = "Unlicense"
|
|
||||||
srcDir = "src"
|
|
||||||
version = "20231021"
|
|
||||||
|
|
||||||
requires "nim", "syndicate", "ws"
|
|
Loading…
Reference in New Issue