Initial commit

This commit is contained in:
Emery Hemingway 2023-03-26 17:02:55 -05:00
commit b601d9a1b7
13 changed files with 150 additions and 0 deletions

2
.envrc Normal file
View File

@ -0,0 +1,2 @@
source_env ..
use flake work#nix_actor

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/.direnv

31
README.md Normal file
View File

@ -0,0 +1,31 @@
# Syndicated Nix Actor
An actor for interacting with the [Nix](https://nixos.org/) daemon via the [Syndicated Actor Model](https://syndicate-lang.org/).
*This is only a proof-of-concept and is not useful in any meaningful way.*
## Example configuration
```
; create and publish a dedicated dataspace
let ?nixspace = dataspace
<nixspace $nixspace>
$nixspace [
; request a build of nixpkgs#hello
? <nix-build "nixpkgs#hello" ?output> [
$log ! <log "-" { hello: $output }>
]
]
; start nix_actor as a daemon
<require-service <daemon nix_actor>>
<daemon nix_actor {
argv: "/run/current-system/sw/bin/nix_actor"
protocol: application/syndicate
}>
; hand-off a capablity to the Nix dataspace to the actor
? <service-object <daemon nix_actor> ?actor> [
$actor <serve $nixspace>
]
```

1
Tuprules.tup Normal file
View File

@ -0,0 +1 @@
NIM_FLAGS += --backend:cpp

13
nix_actor.nimble Normal file
View File

@ -0,0 +1,13 @@
# Package
version = "20230326"
author = "Emery Hemingway"
description = "Syndicated Nix Actor"
license = "Unlicense"
srcDir = "src"
bin = @["nix_actor"]
# Dependencies
requires "nim >= 1.6.10", "syndicate >= 20230326"

4
protocol.prs Normal file
View File

@ -0,0 +1,4 @@
version 1 .
Build = <nix-build @input string @output any> .
Serve = <serve @cap #!any> .

2
src/Tupfile Normal file
View File

@ -0,0 +1,2 @@
include_rules
: nix_actor.nim | $(SYNDICATE_PROTOCOL) ./<protocol> |> !nim_bin |>

35
src/nix_actor.nim Normal file
View File

@ -0,0 +1,35 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
import std/[asyncdispatch, json, osproc]
import preserves, preserves/jsonhooks
import syndicate
from syndicate/protocols/dataspace import Observe
import ./nix_actor/protocol
import ./nix_actor/[main, store]
type Observe = dataspace.Observe[Ref]
proc build(spec: string): Build =
var execOutput = execProcess("nix", args = ["build", "--json", "--no-link", spec], options = {poUsePath})
stderr.writeLine execOutput
var js = parseJson(execOutput)
Build(input: spec, output: js[0].toPreserve)
proc bootNixFacet(ds: Ref; turn: var Turn): Facet =
# let store = openStore()
inFacet(turn) do (turn: var Turn):
let storePathObservation = ?Observe(pattern: !Build) ?? {0: grabLit()}
during(turn, ds, storePathObservation) do (spec: string):
stderr.writeLine "build ", spec
let a = build(spec)
discard publish(turn, ds, a)
proc bootNixActor(root: Ref; turn: var Turn) =
connectStdio(root, turn)
during(turn, root, ?Serve) do (ds: Ref):
discard bootNixFacet(ds, turn)
initNix() # Nix lib isn't actually being used but it's nice to know that it links.
bootDataspace("main", bootNixActor)
runForever()

2
src/nix_actor/Tupfile Normal file
View File

@ -0,0 +1,2 @@
include_rules
: ../../protocol.prs |> !preserves_schema_nim |> protocol.nim | ../<protocol>

7
src/nix_actor/main.nim Normal file
View File

@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
{.passC: staticExec("pkg-config --cflags nix-main").}
{.passL: staticExec("pkg-config --libs nix-main").}
proc initNix*() {.importcpp: "nix::initNix", header: "shared.hh".}

View File

@ -0,0 +1,17 @@
import
std/typetraits, preserves
type
Serve* {.preservesRecord: "serve".} = object
`cap`* {.preservesEmbedded.}: Preserve[void]
Build* {.preservesRecord: "nix-build".} = object
`input`*: string
`output`*: Preserve[void]
proc `$`*(x: Serve | Build): string =
`$`(toPreserve(x))
proc encode*(x: Serve | Build): seq[byte] =
encode(toPreserve(x))

21
src/nix_actor/store.nim Normal file
View File

@ -0,0 +1,21 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
{.passC: staticExec("pkg-config --cflags nix-store").}
{.passL: staticExec("pkg-config --libs nix-store").}
{.passC: "'-DSYSTEM=\"x86_64-linux\"'".}
type
StorePath {.importcpp: "nix::StorePath", header: "path.hh".} = object
discard
proc isDerivation*(path: StorePath): bool {.importcpp.}
type
Store {.importcpp: "nix::ref<nix::Store>", header: "store-api.hh".} = object
discard
proc ensurePath*(store: Store; path: StorePath) {.importcpp.}
proc openStore*(): Store {.importcpp: "nix::openStore".}

View File

@ -0,0 +1,14 @@
import
std/typetraits, preserves
type
Build* {.preservesRecord: "nix-build".} = object
`input`*: string
`output`*: string
proc `$`*(x: Build): string =
`$`(toPreserve(x))
proc encode*(x: Build): seq[byte] =
encode(toPreserve(x))