Refactor for Syndicate API update
This commit is contained in:
parent
0d789361d6
commit
bba515cdd8
32
lock.json
32
lock.json
|
@ -1,5 +1,17 @@
|
||||||
{
|
{
|
||||||
"depends": [
|
"depends": [
|
||||||
|
{
|
||||||
|
"method": "fetchzip",
|
||||||
|
"packages": [
|
||||||
|
"bigints"
|
||||||
|
],
|
||||||
|
"path": "/nix/store/jvrm392g8adfsgf36prgwkbyd7vh5jsw-source",
|
||||||
|
"ref": "20231006",
|
||||||
|
"rev": "86ea14d31eea9275e1408ca34e6bfe9c99989a96",
|
||||||
|
"sha256": "15pcpmnk1bnw3k8769rjzcpg00nahyrypwbxs88jnwr4aczp99j4",
|
||||||
|
"srcDir": "src",
|
||||||
|
"url": "https://github.com/ehmry/nim-bigints/archive/86ea14d31eea9275e1408ca34e6bfe9c99989a96.tar.gz"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"method": "fetchzip",
|
"method": "fetchzip",
|
||||||
"packages": [
|
"packages": [
|
||||||
|
@ -52,24 +64,24 @@
|
||||||
"packages": [
|
"packages": [
|
||||||
"preserves"
|
"preserves"
|
||||||
],
|
],
|
||||||
"path": "/nix/store/fmb2yckksz7iv3qdkk5gk1j060kppkq9-source",
|
"path": "/nix/store/fpkhfxnfbdcri6k7mac21r3byg738bs4-source",
|
||||||
"ref": "20231102",
|
"ref": "20240108",
|
||||||
"rev": "4faeb766dc3945bcfacaa1a836ef6ab29b20ceb0",
|
"rev": "a01ba8c96d65f670862ba074bf82b50cbda6ed99",
|
||||||
"sha256": "1a3g5bk1l1h250q3p6sqv6r1lpsplp330qqyp48r0i4a5r0jksq3",
|
"sha256": "0n8pghy2qfywx0psr54yzjvhdhi5av204150jyyzfxhigczd8sr4",
|
||||||
"srcDir": "src",
|
"srcDir": "src",
|
||||||
"url": "https://git.syndicate-lang.org/ehmry/preserves-nim/archive/4faeb766dc3945bcfacaa1a836ef6ab29b20ceb0.tar.gz"
|
"url": "https://git.syndicate-lang.org/ehmry/preserves-nim/archive/a01ba8c96d65f670862ba074bf82b50cbda6ed99.tar.gz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"method": "fetchzip",
|
"method": "fetchzip",
|
||||||
"packages": [
|
"packages": [
|
||||||
"syndicate"
|
"syndicate"
|
||||||
],
|
],
|
||||||
"path": "/nix/store/nhpvl223vbzdrlzikw7pgyfxs344w7ma-source",
|
"path": "/nix/store/hma19sff6k2bi6qj01yscbynz6x2zvxj-source",
|
||||||
"ref": "20231108",
|
"ref": "20240108",
|
||||||
"rev": "095418032180e360ea27ec7fcd63193944b68e2c",
|
"rev": "3e11884a916c0452c90128c29940856e2d347cb7",
|
||||||
"sha256": "09pbml2chzz0v5zpz67fs7raj0mfmg8qrih2vz85xxc51h7ncqvw",
|
"sha256": "0n1gbwllwwilz9fp5zyp4054vzcq1p7ddzg02sw8d0vqb1wmpsqm",
|
||||||
"srcDir": "src",
|
"srcDir": "src",
|
||||||
"url": "https://git.syndicate-lang.org/ehmry/syndicate-nim/archive/095418032180e360ea27ec7fcd63193944b68e2c.tar.gz"
|
"url": "https://git.syndicate-lang.org/ehmry/syndicate-nim/archive/3e11884a916c0452c90128c29940856e2d347cb7.tar.gz"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
version 1.
|
version 1.
|
||||||
|
|
||||||
Mountpoint = <mount @source string @target string @type string @status Status> .
|
Mountpoint = <mount @source string @target string @type string @status Status> .
|
||||||
Status = Failure / #t.
|
Status = Failure / @success #t .
|
||||||
Failure = <failure @msg string> .
|
Failure = <failure @msg string> .
|
||||||
|
|
|
@ -37,19 +37,24 @@ proc isObserve(pat: Pattern): bool =
|
||||||
pat.dcompound.orKind == DCompoundKind.rec and
|
pat.dcompound.orKind == DCompoundKind.rec and
|
||||||
pat.dcompound.rec.label.isSymbol"Observe"
|
pat.dcompound.rec.label.isSymbol"Observe"
|
||||||
|
|
||||||
runActor("cache_actor") do (turn: var Turn; root: Cap):
|
proc spawnCacheActor*(turn: var Turn; root: Cap): Actor =
|
||||||
spawnTimers(turn, root)
|
spawn("cache_actor", turn) do (turn: var Turn):
|
||||||
connectStdio(turn, root)
|
during(turn, root, ?:BootArgs) do (ds: Cap, lifetime: float64):
|
||||||
during(turn, root, ?BootArgs) do (ds: Cap, lifetime: float64):
|
onPublish(turn, ds, ?:Observe) do (pat: Pattern, obs: Cap):
|
||||||
onPublish(turn, ds, ?Observe) do (pat: Pattern, obs: Cap):
|
var cache: CacheEntity
|
||||||
var cache: CacheEntity
|
if obs.relay != turn.facet and not(pat.isObserve):
|
||||||
if obs.relay != turn.facet and not(pat.isObserve):
|
# Watch pattern if the observer is not us
|
||||||
# Watch pattern if the observer is not us
|
# and if the pattern isn't a recursive observe
|
||||||
# and if the pattern isn't a recursive observe
|
cache = CacheEntity(
|
||||||
cache = CacheEntity(
|
timeouts: root,
|
||||||
timeouts: root,
|
target: ds,
|
||||||
target: ds,
|
pattern: pat,
|
||||||
pattern: pat,
|
lifetime: lifetime,
|
||||||
lifetime: lifetime,
|
)
|
||||||
)
|
discard observe(turn, ds, pat, cache)
|
||||||
discard observe(turn, ds, pat, cache)
|
|
||||||
|
when isMainModule:
|
||||||
|
runActor("cache_actor") do (turn: var Turn; root: Cap):
|
||||||
|
spawnTimers(turn, root)
|
||||||
|
connectStdio(turn, root)
|
||||||
|
discard spawnCacheActor(turn, root)
|
||||||
|
|
|
@ -7,14 +7,11 @@ import std/[asyncdispatch, asyncfile, tables]
|
||||||
import posix, posix/inotify
|
import posix, posix/inotify
|
||||||
import preserves
|
import preserves
|
||||||
import syndicate, syndicate/[bags, relays]
|
import syndicate, syndicate/[bags, relays]
|
||||||
from syndicate/protocols/dataspace import Observe
|
|
||||||
import ./schema/inotify_actor
|
import ./schema/inotify_actor
|
||||||
|
|
||||||
var IN_NONBLOCK {.importc, nodecl.}: cint
|
var IN_NONBLOCK {.importc, nodecl.}: cint
|
||||||
|
|
||||||
type
|
type
|
||||||
Observe = dataspace.Observe[Cap]
|
|
||||||
# Registry = TableRef[cint, TableRef[Cap, HashSet[string]]]
|
|
||||||
BootArgs {.preservesDictionary.} = object
|
BootArgs {.preservesDictionary.} = object
|
||||||
dataspace: Cap
|
dataspace: Cap
|
||||||
|
|
||||||
|
@ -72,7 +69,7 @@ runActor("inotify_actor") do (root: Cap; turn: var Turn):
|
||||||
let buf = newSeq[byte](8192)
|
let buf = newSeq[byte](8192)
|
||||||
let eventPattern = ?Observe(pattern: !InotifyMessage) ?? { 0: grabLit(), 1: grabLit() }
|
let eventPattern = ?Observe(pattern: !InotifyMessage) ?? { 0: grabLit(), 1: grabLit() }
|
||||||
connectStdio(turn, root)
|
connectStdio(turn, root)
|
||||||
during(turn, root, ?BootArgs) do (ds: Cap):
|
during(turn, root, ?:BootArgs) do (ds: Cap):
|
||||||
let inf = inotify_init1(IN_NONBLOCK)
|
let inf = inotify_init1(IN_NONBLOCK)
|
||||||
doAssert inf != -1, $inf & " - " & $strerror(errno)
|
doAssert inf != -1, $inf & " - " & $strerror(errno)
|
||||||
var
|
var
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import std/json
|
import std/json
|
||||||
import preserves, preserves/jsonhooks
|
import preserves, preserves/jsonhooks
|
||||||
|
|
||||||
export fromPreserveHook, toPreserveHook
|
export fromPreservesHook, toPreservesHook
|
||||||
# re-export the hooks so that conversion "just works"
|
# re-export the hooks so that conversion "just works"
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
@ -7,28 +7,33 @@ import preserves, preserves/jsonhooks, syndicate, syndicate/relays
|
||||||
|
|
||||||
import ./schema/config, ./json_messages
|
import ./schema/config, ./json_messages
|
||||||
|
|
||||||
runActor("main") do (root: Cap; turn: var Turn):
|
proc spawnJsonSocketTranslator*(turn: var Turn; root: Cap): Actor =
|
||||||
connectStdio(turn, root)
|
spawn("json_socket_translator", turn) do (turn: var Turn):
|
||||||
during(turn, root, ?JsonSocketTranslatorArguments) do (ds: Cap, socketPath: string):
|
during(turn, root, ?:JsonSocketTranslatorArguments) do (ds: Cap, socketPath: string):
|
||||||
let socket = newAsyncSocket(
|
let socket = newAsyncSocket(
|
||||||
domain = AF_UNIX,
|
domain = AF_UNIX,
|
||||||
sockType = SOCK_STREAM,
|
sockType = SOCK_STREAM,
|
||||||
protocol = cast[Protocol](0),
|
protocol = cast[Protocol](0),
|
||||||
buffered = false,
|
buffered = false,
|
||||||
)
|
)
|
||||||
addCallback(connectUnix(socket, socketPath), turn) do (turn: var Turn):
|
addCallback(connectUnix(socket, socketPath), turn) do (turn: var Turn):
|
||||||
let a = JsonTranslatorConnected(path: socketPath)
|
let a = JsonTranslatorConnected(path: socketPath)
|
||||||
discard publish(turn, ds, a)
|
discard publish(turn, ds, a)
|
||||||
|
|
||||||
let socketFacet = turn.facet
|
let socketFacet = turn.facet
|
||||||
proc processOutput(fut: Future[string]) {.gcsafe.} =
|
proc processOutput(fut: Future[string]) {.gcsafe.} =
|
||||||
run(socketFacet) do (turn: var Turn):
|
run(socketFacet) do (turn: var Turn):
|
||||||
var data = fut.read.parseJson
|
var data = fut.read.parseJson
|
||||||
message(turn, ds, RecvJson(data: data))
|
message(turn, ds, RecvJson(data: data))
|
||||||
|
socket.recvLine.addCallback(processOutput)
|
||||||
socket.recvLine.addCallback(processOutput)
|
socket.recvLine.addCallback(processOutput)
|
||||||
socket.recvLine.addCallback(processOutput)
|
|
||||||
|
|
||||||
onMessage(turn, ds, ?SendJson) do (data: JsonNode):
|
onMessage(turn, ds, ?:SendJson) do (data: JsonNode):
|
||||||
asyncCheck(turn, send(socket, $data & "\n"))
|
asyncCheck(turn, send(socket, $data & "\n"))
|
||||||
do:
|
do:
|
||||||
close(socket)
|
close(socket)
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
runActor("json_socket_translator") do (turn: var Turn; root: Cap):
|
||||||
|
connectStdio(turn, root)
|
||||||
|
discard spawnJsonSocketTranslator(turn, root)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import std/[json, os, osproc]
|
||||||
import preserves
|
import preserves
|
||||||
import syndicate, syndicate/relays
|
import syndicate, syndicate/relays
|
||||||
|
|
||||||
from preserves/jsonhooks import toPreserveHook
|
from preserves/jsonhooks import toPreservesHook
|
||||||
|
|
||||||
import ./json_messages
|
import ./json_messages
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# SPDX-License-Identifier: Unlicense
|
# SPDX-License-Identifier: Unlicense
|
||||||
|
|
||||||
from os import commandLineParams
|
from os import commandLineParams
|
||||||
import preserves, syndicate/capabilities
|
import preserves, syndicate/capabilities, syndicate/protocols/sturdy
|
||||||
|
|
||||||
const usage = """
|
const usage = """
|
||||||
mintsturdyref OID < SECRET_KEY
|
mintsturdyref OID < SECRET_KEY
|
||||||
|
@ -19,7 +19,7 @@ See:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc main =
|
proc main =
|
||||||
var oids: seq[Preserve[void]]
|
var oids: seq[Value]
|
||||||
for p in commandLineParams():
|
for p in commandLineParams():
|
||||||
case p
|
case p
|
||||||
of "-h", "--help", "?":
|
of "-h", "--help", "?":
|
||||||
|
@ -28,7 +28,7 @@ proc main =
|
||||||
add(oids, parsePreserves p)
|
add(oids, parsePreserves p)
|
||||||
if oids.len == 0:
|
if oids.len == 0:
|
||||||
stderr.writeLine """using the "syndicate" OID"""
|
stderr.writeLine """using the "syndicate" OID"""
|
||||||
oids.add(toPreserve "syndicate")
|
oids.add(toPreserves "syndicate")
|
||||||
|
|
||||||
var key: array[16, byte]
|
var key: array[16, byte]
|
||||||
case readBytes(stdin, key, 0, 16)
|
case readBytes(stdin, key, 0, 16)
|
||||||
|
|
|
@ -25,7 +25,7 @@ runActor("mount_actor") do (turn: var Turn; root: Cap):
|
||||||
targetPat = ?Observe(pattern: !Mountpoint) ?? { 1: grabLit() }
|
targetPat = ?Observe(pattern: !Mountpoint) ?? { 1: grabLit() }
|
||||||
sourcePat = ?Observe(pattern: !Mountpoint) ?? { 0: grabLit(), 2: grabLit() }
|
sourcePat = ?Observe(pattern: !Mountpoint) ?? { 0: grabLit(), 2: grabLit() }
|
||||||
connectStdio(turn, root)
|
connectStdio(turn, root)
|
||||||
during(turn, root, ?BootArgs) do (ds: Cap):
|
during(turn, root, ?:BootArgs) do (ds: Cap):
|
||||||
during(turn, ds, targetPat) do (target: string):
|
during(turn, ds, targetPat) do (target: string):
|
||||||
during(turn, ds, sourcePat) do (source: string, fsType: string):
|
during(turn, ds, sourcePat) do (source: string, fsType: string):
|
||||||
var mountpoint = Mountpoint(
|
var mountpoint = Mountpoint(
|
||||||
|
@ -35,7 +35,7 @@ runActor("mount_actor") do (turn: var Turn; root: Cap):
|
||||||
)
|
)
|
||||||
var rc = mount(source, target, fsType, 0, nil)
|
var rc = mount(source, target, fsType, 0, nil)
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
mountpoint.status = Status(orKind: StatusKind.true)
|
mountpoint.status = Status(orKind: StatusKind.success)
|
||||||
else:
|
else:
|
||||||
mountpoint.status = Status(orKind: StatusKind.Failure)
|
mountpoint.status = Status(orKind: StatusKind.Failure)
|
||||||
mountpoint.status.failure.msg = osErrorMsg(osLastError())
|
mountpoint.status.failure.msg = osErrorMsg(osLastError())
|
||||||
|
|
|
@ -15,9 +15,9 @@ var
|
||||||
IP_TTL {.importc, nodecl, header: "<netinet/in.h>".}: int
|
IP_TTL {.importc, nodecl, header: "<netinet/in.h>".}: int
|
||||||
]#
|
]#
|
||||||
|
|
||||||
proc toPreserveHook(address: IpAddress; E: typedesc): Preserve[E] = toPreserve($address, E)
|
proc toPreservesHook(address: IpAddress): Value = toPreserves($address)
|
||||||
|
|
||||||
proc fromPreserveHook[E](address: var IpAddress; pr: Preserve[E]): bool =
|
proc fromPreservesHook(address: var IpAddress; pr: Value): bool =
|
||||||
try:
|
try:
|
||||||
if pr.isString:
|
if pr.isString:
|
||||||
address = parseIpAddress(pr.string)
|
address = parseIpAddress(pr.string)
|
||||||
|
@ -27,7 +27,7 @@ proc fromPreserveHook[E](address: var IpAddress; pr: Preserve[E]): bool =
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
# verify that the hook catches
|
# verify that the hook catches
|
||||||
var ip: IpAddress
|
var ip: IpAddress
|
||||||
assert fromPreserveHook(ip, toPreserveHook(ip, void))
|
assert fromPreservesHook(ip, toPreservesHook(ip))
|
||||||
|
|
||||||
type
|
type
|
||||||
IcmpHeader {.packed.} = object
|
IcmpHeader {.packed.} = object
|
||||||
|
@ -157,7 +157,7 @@ type Args {.preservesDictionary.} = object
|
||||||
runActor("net_mapper") do (root: Cap; turn: var Turn):
|
runActor("net_mapper") do (root: Cap; turn: var Turn):
|
||||||
connectStdio(turn, root)
|
connectStdio(turn, root)
|
||||||
let rttObserver = ?Observe(pattern: !RoundTripTime) ?? {0: grabLit()}
|
let rttObserver = ?Observe(pattern: !RoundTripTime) ?? {0: grabLit()}
|
||||||
during(turn, root, ?Args) do (ds: Cap):
|
during(turn, root, ?:Args) do (ds: Cap):
|
||||||
during(turn, ds, rttObserver) do (address: IpAddress):
|
during(turn, ds, rttObserver) do (address: IpAddress):
|
||||||
var ping: Pinger
|
var ping: Pinger
|
||||||
if address.family == IpAddressFamily.IPv4:
|
if address.family == IpAddressFamily.IPv4:
|
||||||
|
|
|
@ -16,6 +16,6 @@ proc main =
|
||||||
info.argv = commandLineParams()
|
info.argv = commandLineParams()
|
||||||
for key, val in envPairs(): info.env[key] = val
|
for key, val in envPairs(): info.env[key] = val
|
||||||
info.dir = getCurrentDir()
|
info.dir = getCurrentDir()
|
||||||
writeLine(stdout, info.toPreserve)
|
writeLine(stdout, info.toPreserves)
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -19,7 +19,7 @@ proc main =
|
||||||
resolve(turn, root, route) do (turn: var Turn; ds: Cap):
|
resolve(turn, root, route) do (turn: var Turn; ds: Cap):
|
||||||
case paramCount()
|
case paramCount()
|
||||||
of 0:
|
of 0:
|
||||||
let pat = ?Options
|
let pat = ?:Options
|
||||||
onPublish(turn, ds, pat) do (options: seq[string]):
|
onPublish(turn, ds, pat) do (options: seq[string]):
|
||||||
stdout.writeLine options.join("\n")
|
stdout.writeLine options.join("\n")
|
||||||
quit()
|
quit()
|
||||||
|
|
|
@ -7,12 +7,12 @@ type
|
||||||
`path`*: string
|
`path`*: string
|
||||||
|
|
||||||
JsonSocketTranslatorArguments* {.preservesDictionary.} = object
|
JsonSocketTranslatorArguments* {.preservesDictionary.} = object
|
||||||
`dataspace`* {.preservesEmbedded.}: Preserve[void]
|
`dataspace`* {.preservesEmbedded.}: Value
|
||||||
`socket`*: string
|
`socket`*: string
|
||||||
|
|
||||||
proc `$`*(x: JsonTranslatorConnected | JsonSocketTranslatorArguments): string =
|
proc `$`*(x: JsonTranslatorConnected | JsonSocketTranslatorArguments): string =
|
||||||
`$`(toPreserve(x))
|
`$`(toPreserves(x))
|
||||||
|
|
||||||
proc encode*(x: JsonTranslatorConnected | JsonSocketTranslatorArguments): seq[
|
proc encode*(x: JsonTranslatorConnected | JsonSocketTranslatorArguments): seq[
|
||||||
byte] =
|
byte] =
|
||||||
encode(toPreserve(x))
|
encode(toPreserves(x))
|
||||||
|
|
|
@ -10,7 +10,7 @@ type
|
||||||
`name`*: string
|
`name`*: string
|
||||||
|
|
||||||
proc `$`*(x: InotifyMessage): string =
|
proc `$`*(x: InotifyMessage): string =
|
||||||
`$`(toPreserve(x))
|
`$`(toPreserves(x))
|
||||||
|
|
||||||
proc encode*(x: InotifyMessage): seq[byte] =
|
proc encode*(x: InotifyMessage): seq[byte] =
|
||||||
encode(toPreserve(x))
|
encode(toPreserves(x))
|
||||||
|
|
|
@ -13,18 +13,18 @@ type
|
||||||
`status`*: Status
|
`status`*: Status
|
||||||
|
|
||||||
StatusKind* {.pure.} = enum
|
StatusKind* {.pure.} = enum
|
||||||
`Failure`, `true`
|
`Failure`, `success`
|
||||||
`Status`* {.preservesOr.} = object
|
`Status`* {.preservesOr.} = object
|
||||||
case orKind*: StatusKind
|
case orKind*: StatusKind
|
||||||
of StatusKind.`Failure`:
|
of StatusKind.`Failure`:
|
||||||
`failure`*: Failure
|
`failure`*: Failure
|
||||||
|
|
||||||
of StatusKind.`true`:
|
of StatusKind.`success`:
|
||||||
`true`* {.preservesLiteral: "#t".}: bool
|
`success`* {.preservesLiteral: "#t".}: bool
|
||||||
|
|
||||||
|
|
||||||
proc `$`*(x: Failure | Mountpoint | Status): string =
|
proc `$`*(x: Failure | Mountpoint | Status): string =
|
||||||
`$`(toPreserve(x))
|
`$`(toPreserves(x))
|
||||||
|
|
||||||
proc encode*(x: Failure | Mountpoint | Status): seq[byte] =
|
proc encode*(x: Failure | Mountpoint | Status): seq[byte] =
|
||||||
encode(toPreserve(x))
|
encode(toPreserves(x))
|
||||||
|
|
|
@ -10,7 +10,7 @@ type
|
||||||
`maximum`*: float32
|
`maximum`*: float32
|
||||||
|
|
||||||
proc `$`*(x: RoundTripTime): string =
|
proc `$`*(x: RoundTripTime): string =
|
||||||
`$`(toPreserve(x))
|
`$`(toPreserves(x))
|
||||||
|
|
||||||
proc encode*(x: RoundTripTime): seq[byte] =
|
proc encode*(x: RoundTripTime): seq[byte] =
|
||||||
encode(toPreserve(x))
|
encode(toPreserves(x))
|
||||||
|
|
|
@ -12,7 +12,7 @@ type
|
||||||
`options`*: seq[string]
|
`options`*: seq[string]
|
||||||
|
|
||||||
proc `$`*(x: Environment | Select | Options): string =
|
proc `$`*(x: Environment | Select | Options): string =
|
||||||
`$`(toPreserve(x))
|
`$`(toPreserves(x))
|
||||||
|
|
||||||
proc encode*(x: Environment | Select | Options): seq[byte] =
|
proc encode*(x: Environment | Select | Options): seq[byte] =
|
||||||
encode(toPreserve(x))
|
encode(toPreserves(x))
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
|
|
||||||
## An actor for relaying Webhooks.
|
## An actor for relaying Webhooks.
|
||||||
|
|
||||||
import std/[asyncdispatch, asynchttpserver, json, net, sets, strutils, tables, uri]
|
import std/[asyncdispatch, asynchttpserver, net, strutils, tables, uri]
|
||||||
|
|
||||||
import preserves, preserves/jsonhooks
|
import preserves, preserves/jsonhooks
|
||||||
import syndicate, syndicate/[bags, relays]
|
import syndicate, syndicate/[bags, relays]
|
||||||
import syndicate/protocols/[http, transportAddress]
|
import syndicate/protocols/[http, transportAddress]
|
||||||
|
|
||||||
type
|
type
|
||||||
|
CapBag = Bag[Cap]
|
||||||
Endpoints = Table[seq[string], Cap]
|
Endpoints = Table[seq[string], Cap]
|
||||||
WebhookArgs {.preservesDictionary.} = object
|
WebhookArgs {.preservesDictionary.} = object
|
||||||
endpoints: Assertion
|
endpoints: Assertion
|
||||||
|
@ -19,36 +20,37 @@ type
|
||||||
|
|
||||||
func splitPath(s: string): seq[string] = s.strip(chars={'/'}).split('/')
|
func splitPath(s: string): seq[string] = s.strip(chars={'/'}).split('/')
|
||||||
|
|
||||||
proc toRecord(req: Request; seqnum: BiggestInt; path: seq[string]): HttpRequest =
|
proc toRecord(req: Request; seqnum: BiggestInt; path: seq[string]): Value =
|
||||||
## Convert a request value from the std/asynchttpserver module
|
## Convert a request value from the std/asynchttpserver module
|
||||||
## to a request type from syndicate/protocols/http.
|
## to a request type from syndicate/protocols/http.
|
||||||
result.sequenceNumber = seqnum
|
var record: HttpRequest
|
||||||
result.host = req.hostname
|
record.sequenceNumber = seqnum
|
||||||
result.`method` = Symbol($req.reqMethod)
|
record.host = req.hostname
|
||||||
result.path = path
|
record.`method` = Symbol($req.reqMethod)
|
||||||
|
record.path = path
|
||||||
for key, val in req.headers.pairs:
|
for key, val in req.headers.pairs:
|
||||||
result.headers[Symbol key] = val
|
record.headers[Symbol key] = val
|
||||||
for key, val in decodeQuery(req.url.query):
|
for key, val in decodeQuery(req.url.query):
|
||||||
result.query[Symbol key] =
|
record.query[Symbol key] =
|
||||||
@[QueryValue(orKind: QueryValueKind.string, string: val)]
|
@[QueryValue(orKind: QueryValueKind.string, string: val)]
|
||||||
let contentType = req.headers.getOrDefault("content-type")
|
let contentType = req.headers.getOrDefault("content-type")
|
||||||
|
result = toPreserves record
|
||||||
if req.body.len > 0:
|
if req.body.len > 0:
|
||||||
result.body = RequestBody(orKind: RequestBodyKind.present)
|
result[7] =
|
||||||
case contentType.toString
|
case contentType.toString
|
||||||
of "application/json":
|
of "application/json":
|
||||||
var js = parseJson req.body
|
req.body.parsePreserves
|
||||||
result.body.present = js.toPreserve
|
of "application/octet-stream":
|
||||||
of "application/octet-stream":
|
cast[seq[byte]](req.body).toPreserves
|
||||||
result.body.present = cast[seq[byte]](req.body).toPreserve
|
else:
|
||||||
else:
|
req.body.toPreserves
|
||||||
result.body.present = req.body.toPreserve
|
|
||||||
|
|
||||||
proc bootWebhookActor*(turn: var Turn; root: Cap): Actor =
|
proc bootWebhookActor*(turn: var Turn; root: Cap): Actor =
|
||||||
spawn("webhooks", turn) do (turn: var Turn):
|
spawn("webhooks", turn) do (turn: var Turn):
|
||||||
during(turn, root, inject(!BootArgs, {1: grab(), 2: grab()})) do (host: string; port: Port):
|
during(turn, root, inject(!BootArgs, {1: grab(), 2: grab()})) do (host: string; port: Port):
|
||||||
var seqNum: BiggestInt
|
var seqNum: BiggestInt
|
||||||
let facet = turn.facet
|
let facet = turn.facet
|
||||||
let endpoints = newTable[seq[string], Bag[Cap]]()
|
let endpoints = newTable[seq[string], CapBag]()
|
||||||
# use a bag so the same capability registered multiple
|
# use a bag so the same capability registered multiple
|
||||||
# times with the same path does not get duplicate messages
|
# times with the same path does not get duplicate messages
|
||||||
|
|
||||||
|
@ -60,10 +62,11 @@ proc bootWebhookActor*(turn: var Turn; root: Cap): Actor =
|
||||||
"no capabilities registered at $1\n" % [req.url.path])
|
"no capabilities registered at $1\n" % [req.url.path])
|
||||||
else:
|
else:
|
||||||
result = respond(req, Http200, "")
|
result = respond(req, Http200, "")
|
||||||
run(facet) do (turn: var Turn):
|
proc act(turn: var Turn) {.gcsafe.} =
|
||||||
var rec = req.toRecord(seqNum, path)
|
let rec = req.toRecord(seqNum, path)
|
||||||
for cap in endpoints[rec.path]:
|
for cap in endpoints[path]:
|
||||||
message(turn, cap, rec)
|
message(turn, cap, rec)
|
||||||
|
run(facet, act)
|
||||||
|
|
||||||
let server = newAsyncHttpServer()
|
let server = newAsyncHttpServer()
|
||||||
if host.isIpAddress:
|
if host.isIpAddress:
|
||||||
|
@ -80,7 +83,7 @@ proc bootWebhookActor*(turn: var Turn; root: Cap): Actor =
|
||||||
during(turn, root, inject(!BootArgs, {0: grab(), 1: ?host, 2: ?port})) do (eps: Endpoints):
|
during(turn, root, inject(!BootArgs, {0: grab(), 1: ?host, 2: ?port})) do (eps: Endpoints):
|
||||||
for path, cap in eps:
|
for path, cap in eps:
|
||||||
if not endpoints.hasKey path:
|
if not endpoints.hasKey path:
|
||||||
endpoints[path] = Bag[Cap]()
|
endpoints[path] = CapBag()
|
||||||
discard endpoints[path].change(cap, +1)
|
discard endpoints[path].change(cap, +1)
|
||||||
do:
|
do:
|
||||||
for path, cap in eps:
|
for path, cap in eps:
|
||||||
|
@ -88,5 +91,3 @@ proc bootWebhookActor*(turn: var Turn; root: Cap): Actor =
|
||||||
|
|
||||||
do:
|
do:
|
||||||
close(server)
|
close(server)
|
||||||
|
|
||||||
# TODO: JSON payloads
|
|
||||||
|
|
|
@ -15,17 +15,17 @@ proc exitProc() {.noconv.} =
|
||||||
|
|
||||||
setControlCHook(exitProc)
|
setControlCHook(exitProc)
|
||||||
|
|
||||||
proc parsePattern(pr: Assertion): Pattern =
|
proc parsePattern(pr: Value): Pattern =
|
||||||
let
|
let
|
||||||
dropSigil = initRecord("lit", "_".toSymbol(Cap))
|
dropSigil = initRecord("lit", "_".toSymbol)
|
||||||
grabSigil = initRecord("lit", "?".toSymbol(Cap))
|
grabSigil = initRecord("lit", "?".toSymbol)
|
||||||
var pr = grab(pr).toPreserve(Cap)
|
var pr = grab(pr).toPreserves
|
||||||
apply(pr) do (pr: var Assertion):
|
apply(pr) do (pr: var Value):
|
||||||
if pr == dropSigil:
|
if pr == dropSigil:
|
||||||
pr = initRecord[Cap]("_")
|
pr = initRecord("_")
|
||||||
elif pr == grabSigil:
|
elif pr == grabSigil:
|
||||||
pr = initRecord("bind", initRecord[Cap]("_"))
|
pr = initRecord("bind", initRecord("_"))
|
||||||
doAssert result.fromPreserve(pr)
|
doAssert result.fromPreserves(pr)
|
||||||
|
|
||||||
proc inputPattern: Pattern =
|
proc inputPattern: Pattern =
|
||||||
var args = commandLineParams()
|
var args = commandLineParams()
|
||||||
|
@ -36,10 +36,10 @@ proc inputPattern: Pattern =
|
||||||
if input == "":
|
if input == "":
|
||||||
quit "expected Preserves Pattern on stdin"
|
quit "expected Preserves Pattern on stdin"
|
||||||
else:
|
else:
|
||||||
var pr: Assertion
|
var pr: Value
|
||||||
try: pr = decodePreserves(input, Cap)
|
try: pr = decodePreserves(input)
|
||||||
except ValueError: discard
|
except ValueError: discard
|
||||||
try: pr = parsePreserves(input, Cap)
|
try: pr = parsePreserves(input)
|
||||||
except ValueError: discard
|
except ValueError: discard
|
||||||
if pr.isFalse:
|
if pr.isFalse:
|
||||||
quit "failed to parse Preserves argument"
|
quit "failed to parse Preserves argument"
|
||||||
|
@ -47,7 +47,7 @@ proc inputPattern: Pattern =
|
||||||
|
|
||||||
type TermEntity {.final.} = ref object of Entity
|
type TermEntity {.final.} = ref object of Entity
|
||||||
pattern: Pattern
|
pattern: Pattern
|
||||||
value: Assertion
|
value: Value
|
||||||
|
|
||||||
method publish(te: TermEntity; turn: var Turn; v: AssertionRef; h: Handle) =
|
method publish(te: TermEntity; turn: var Turn; v: AssertionRef; h: Handle) =
|
||||||
te.value = v.value
|
te.value = v.value
|
||||||
|
|
|
@ -2,34 +2,32 @@
|
||||||
# SPDX-License-Identifier: Unlicense
|
# SPDX-License-Identifier: Unlicense
|
||||||
|
|
||||||
import std/[os, tables]
|
import std/[os, tables]
|
||||||
import preserves
|
import preserves, syndicate, syndicate/[durings, relays]
|
||||||
import syndicate,
|
|
||||||
syndicate/[durings, relays]
|
|
||||||
|
|
||||||
proc parsePattern(pr: Assertion): Pattern =
|
proc parsePattern(pr: Value): Pattern =
|
||||||
let
|
let
|
||||||
dropSigil = initRecord("lit", "_".toSymbol(Cap))
|
dropSigil = initRecord("lit", "_".toSymbol)
|
||||||
grabSigil = initRecord("lit", "?".toSymbol(Cap))
|
grabSigil = initRecord("lit", "?".toSymbol)
|
||||||
var pr = grab(pr).toPreserve(Cap)
|
var pr = grab(pr).toPreserves
|
||||||
apply(pr) do (pr: var Assertion):
|
apply(pr) do (pr: var Value):
|
||||||
if pr == dropSigil:
|
if pr == dropSigil:
|
||||||
pr = initRecord[Cap]("_")
|
pr = initRecord("_")
|
||||||
elif pr == grabSigil:
|
elif pr == grabSigil:
|
||||||
pr = initRecord("bind", initRecord[Cap]("_"))
|
pr = initRecord("bind", initRecord("_"))
|
||||||
doAssert result.fromPreserve(pr)
|
doAssert result.fromPreserves(pr)
|
||||||
|
|
||||||
proc inputPatterns: seq[Pattern] =
|
proc inputPatterns: seq[Pattern] =
|
||||||
var args = commandLineParams()
|
var args = commandLineParams()
|
||||||
result.setLen(args.len)
|
result.setLen(args.len)
|
||||||
for i, input in args:
|
for i, input in args:
|
||||||
try: result[i] = input.parsePreserves(Cap).parsePattern
|
try: result[i] = input.parsePreserves.parsePattern
|
||||||
except ValueError:
|
except ValueError:
|
||||||
quit "failed to parse Preserves argument"
|
quit "failed to parse Preserves argument"
|
||||||
|
|
||||||
type DumpEntity {.final.} = ref object of Entity
|
type DumpEntity {.final.} = ref object of Entity
|
||||||
assertions: Table[Handle, seq[Assertion]]
|
assertions: Table[Handle, seq[Value]]
|
||||||
|
|
||||||
proc toLine(values: seq[Assertion]; prefix: char): string =
|
proc toLine(values: seq[Value]; prefix: char): string =
|
||||||
result = newStringOfCap(1024)
|
result = newStringOfCap(1024)
|
||||||
let sep = getEnv("FS", " ")
|
let sep = getEnv("FS", " ")
|
||||||
result.add(prefix)
|
result.add(prefix)
|
||||||
|
@ -45,7 +43,7 @@ method publish(dump: DumpEntity; turn: var Turn; ass: AssertionRef; h: Handle) =
|
||||||
dump.assertions[h] = values
|
dump.assertions[h] = values
|
||||||
|
|
||||||
method retract(dump: DumpEntity; turn: var Turn; h: Handle) =
|
method retract(dump: DumpEntity; turn: var Turn; h: Handle) =
|
||||||
var values: seq[Assertion]
|
var values: seq[Value]
|
||||||
if dump.assertions.pop(h, values):
|
if dump.assertions.pop(h, values):
|
||||||
stdout.write(values.toLine('-'))
|
stdout.write(values.toLine('-'))
|
||||||
stdout.flushFile()
|
stdout.flushFile()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "20231226"
|
version = "20240108"
|
||||||
author = "Emery Hemingway"
|
author = "Emery Hemingway"
|
||||||
description = "Utilites for Syndicated Actors and Synit"
|
description = "Utilites for Syndicated Actors and Synit"
|
||||||
license = "unlicense"
|
license = "unlicense"
|
||||||
|
@ -10,4 +10,4 @@ bin = @["cache_actor", "json_socket_translator", "json_translator", "m
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|
||||||
requires "nim >= 1.6.6", "illwill", "syndicate >= 20231108"
|
requires "nim >= 2.0.0", "illwill", "syndicate >= 20240108"
|
||||||
|
|
Loading…
Reference in New Issue