sqlite-actor: convert to gatekeeper protocol

This commit is contained in:
Emery Hemingway 2024-06-04 12:49:56 +03:00
parent 0b4aa89311
commit d76f1df350
4 changed files with 58 additions and 35 deletions

View File

@ -414,30 +414,43 @@ It can be used to feed the environment variables of a nested child of the Syndic
## 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.
Readonly access to SQLite databases.
Asserts rows as records in response to SQL query assertions.
Dynamic updates are not implemented.
```
# 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 ?sqliteStep = <sqlite { database: "/var/db/stuff.db" }>
let ?tuplespace = dataspace
$sqlspace <query "SELECT id, name FROM stuff" $tuplespace>
$tuplespace ? [?id ?name] [
$log ! <log "-" { row: <example-row $id $name> }>
$tuplespace ? ?row [
$log ! <log "-" { line: $row }>
]
let ?resolver = dataspace
$resolver [
? <rejected ?detail> [
$log ! <log "-" { line: $detail }>
]
? <accepted ?sqlspace> [
$log ! <log "-" { sqlspace: $sqlspace }>
$sqlspace ? <sql-error ?msg ?context> [
$log ! <log "-" { line: $msg context: $context }>
]
$sqlspace <query [ SELECT local_display_name FROM contacts ] $tuplespace>
]
]
<require-service <daemon sqlite-actor>>
$config ? <service-object <daemon sqlite-actor> ?cap> [
$cap <resolve $sqliteStep $resolver>
]
<daemon sqlite-actor {
argv: [ "/bin/sqlite-actor" ]
clearEnv: #t
protocol: application/syndicate
}>
```
## syndump

View File

@ -69,6 +69,10 @@
"name": "nim:bin:syndump",
"value": "syndump"
},
{
"name": "nim:bin:sqlite-actor",
"value": "sqlite_actor"
},
{
"name": "nim:srcDir",
"value": "src"

View File

@ -40,6 +40,12 @@ type
Base64DecoderArguments* {.preservesRecord: "base64-decoder".} = object
`field0`*: Base64DecoderArgumentsField0
SqliteStepField0* {.preservesDictionary.} = object
`database`*: string
SqliteStep* {.preservesRecord: "sqlite".} = object
`field0`*: SqliteStepField0
XsltArgumentsField0* {.preservesDictionary.} = object
`dataspace`* {.preservesEmbedded.}: EmbeddedRef
@ -71,13 +77,6 @@ type
FileSystemUsageArguments* {.preservesRecord: "file-system-usage".} = object
`field0`*: FileSystemUsageArgumentsField0
SqliteArgumentsField0* {.preservesDictionary.} = object
`database`*: string
`dataspace`* {.preservesEmbedded.}: EmbeddedRef
SqliteArguments* {.preservesRecord: "sqlite".} = object
`field0`*: SqliteArgumentsField0
PostgreStepField0* {.preservesDictionary.} = object
`connection`*: seq[PostgreConnectionParameter]
@ -126,12 +125,12 @@ type
proc `$`*(x: WebsocketArguments | HttpClientArguments | JsonTranslatorArguments |
SocketAddress |
Base64DecoderArguments |
SqliteStep |
XsltArguments |
HttpDriverArguments |
JsonSocketTranslatorStep |
WebhooksArguments |
FileSystemUsageArguments |
SqliteArguments |
PostgreStep |
TcpAddress |
CacheArguments |
@ -147,12 +146,12 @@ proc encode*(x: WebsocketArguments | HttpClientArguments |
JsonTranslatorArguments |
SocketAddress |
Base64DecoderArguments |
SqliteStep |
XsltArguments |
HttpDriverArguments |
JsonSocketTranslatorStep |
WebhooksArguments |
FileSystemUsageArguments |
SqliteArguments |
PostgreStep |
TcpAddress |
CacheArguments |

View File

@ -1,8 +1,10 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
import preserves, syndicate
import ./schema/[config, sql]
import
pkg/preserves,
pkg/syndicate, pkg/syndicate/protocols/[gatekeeper, sturdy],
./schema/[config, sql]
# Avoid Sqlite3 from the standard library because it is
# only held together by wishful thinking and dlload.
@ -107,19 +109,24 @@ proc renderSql(tokens: openarray[Value]): string =
else:
return ""
proc spawnSqliteActor*(turn: Turn; root: Cap): Actor {.discardable.} =
spawn("sqlite-actor", turn) do (turn: Turn):
during(turn, root, ?:SqliteArguments) do (path: string, ds: Cap):
proc spawnSqliteActor*(turn: Turn; relay: Cap): Actor {.discardable.} =
result = spawnActor(turn, "sqlite") do (turn: Turn):
let pat = Resolve?:{ 0: SqliteStep.grabTypeFlat, 1: grab() }
during(turn, relay, pat) do (path: string, observer: Cap):
linkActor(turn, path) do (turn: Turn):
let facet = turn.facet
stderr.writeLine("opening SQLite database ", path)
var db: Sqlite3
if open_v2(path, addr db, SQLITE_OPEN_READONLY, nil) != SQLITE_OK:
assertError(facet, ds, db, path)
discard publish(turn, observer,
Rejected(detail: toPreserves($errmsg(db))))
else:
turn.onStop do (turn: Turn):
close(db)
stderr.writeLine("closed SQLite database ", path)
let ds = turn.newDataspace()
discard publish(turn, observer,
ResolvedAccepted(responderSession: ds))
during(turn, ds, ?:Query) do (statement: seq[Value], target: Cap):
var
stmt: Stmt
@ -145,5 +152,5 @@ proc spawnSqliteActor*(turn: Turn; root: Cap): Actor {.discardable.} =
when isMainModule:
import syndicate/relays
runActor("main") do (turn: Turn):
resolveEnvironment(turn) do (turn: Turn; ds: Cap):
spawnSqliteActor(turn, ds)
resolveEnvironment(turn) do (turn: Turn; relay: Cap):
spawnSqliteActor(turn, relay)