diff --git a/.envrc b/.envrc index 2a928c3..07423d4 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,3 @@ export LD_LIBRARY_PATH="$PWD/lib:$LD_LIBRARY_PATH" +export DATABASE_URL="sqlite:lib/crossfire.sqlite" +[ ! -d lib ] && mkdir lib diff --git a/.gitignore b/.gitignore index 3847f31..0c1d76b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ *.zo *.dep *.so +*.sqlite /crossfire/compiled/ /crossfire/doc/ diff --git a/crossfire/comms.rkt b/crossfire/comms.rkt index b75f479..b2fabb8 100644 --- a/crossfire/comms.rkt +++ b/crossfire/comms.rkt @@ -17,7 +17,8 @@ ;; along with this program. If not, see . (require racket/async-channel racket/bool racket/engine racket/fasl racket/function racket/list - racket/match racket/tcp + racket/match racket/tcp syntax/parse/define + (for-syntax racket/base racket/syntax) "not-crypto.rkt") ;; define message types (they must all be prefab for fasl) @@ -490,6 +491,45 @@ (provide make-transaction-manager tm-register-rpc tm-deregister-rpc tm-transact tm-shutdown) + +;; utility functions and macros for defining rpcs + +;; id generation helpers +(define-for-syntax (rpc-type-id what) + (format-id what "rpc-type-~a" (syntax-e what))) +(define-for-syntax (rpc-impl-id what) + (format-id what "rpc-impl-~a" (syntax-e what))) + +;; parameters for comms, tm, and targeted node +(define current-comms (make-parameter #f)) +(define current-tm (make-parameter #f)) +(define current-to-node (make-parameter #f)) + +;; defines a class of rpcs +(define-simple-macro (define-rpc-type type:id) + #:with def-id (rpc-type-id #'type) + (define def-id (make-hash))) + +;; defines an rpc implementation, registers it with a given class of rpcs and makes a wrapper to +;; call it +(define-simple-macro (define-rpc type:id (name:id args:id ...) body:expr ...) + #:with def-id (rpc-type-id #'type) + #:with impl-id (rpc-impl-id #'name) + (begin + (define (impl-id args ...) body ...) + (define (name args ...) + (tm-transact (current-tm) (current-to-node) (quote name) (list args ...))) + (hash-set! def-id (quote name) impl-id))) + +;; installs all rpcs of a given rpc class into the transaction manager +(define-simple-macro (install-rpc-type type:id) + #:with def-id (rpc-type-id #'type) + (for ([(k v) (in-hash def-id)]) + (tm-register-rpc (current-tm) k v))) + +(provide current-comms current-tm current-to-node + define-rpc-type define-rpc install-rpc-type) + ; ;; demo code ; (define server-sk #"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") ; (define server-pk (crypto-sign-public-key server-sk)) diff --git a/crossfire/info.rkt b/crossfire/info.rkt index 0dd936d..97cc10e 100644 --- a/crossfire/info.rkt +++ b/crossfire/info.rkt @@ -21,6 +21,7 @@ (define pkg-authors '(haskal)) (define collection "crossfire") -(define deps '("base")) +(define deps '("base" "db-lib" "scribble-text-lib" + "north")) (define build-deps '("scribble-lib" "racket-doc" "rackunit-lib")) (define scribblings '(("scribblings/crossfire.scrbl" ()))) diff --git a/crossfire/migrations/20201113-add-tasks-table.sql b/crossfire/migrations/20201113-add-tasks-table.sql new file mode 100644 index 0000000..8e5c295 --- /dev/null +++ b/crossfire/migrations/20201113-add-tasks-table.sql @@ -0,0 +1,11 @@ +#lang north + +-- @revision: e50ab485d8590ead53c2518396c04f81 +-- @description: Creates the tasks table. +-- @up { +create table tasks (id integer primary key, name text not null, manifest blob not null); +-- } + +-- @down { +drop table tasks; +-- } diff --git a/crossfire/protocol.rkt b/crossfire/protocol.rkt index a524713..3c38724 100644 --- a/crossfire/protocol.rkt +++ b/crossfire/protocol.rkt @@ -16,48 +16,31 @@ ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see . -(require "comms.rkt" "not-crypto.rkt" - syntax/parse/define - (for-syntax racket/base racket/syntax)) +(require db/base db/sqlite3 racket/path + "comms.rkt" "not-crypto.rkt") -;; utility functions and macros for defining rpcs +;; configuration -;; id generation helpers -(define-for-syntax (rpc-type-id what) - (format-id what "rpc-type-~a" (syntax-e what))) -(define-for-syntax (rpc-impl-id what) - (format-id what "rpc-impl-~a" (syntax-e what))) +(define PRODUCTION? #f) -;; parameters for comms, tm, and targeted node -(define current-comms (make-parameter #f)) -(define current-tm (make-parameter #f)) -(define current-to-node (make-parameter #f)) - -;; defines a class of rpcs -(define-simple-macro (define-rpc-type type:id) - #:with def-id (rpc-type-id #'type) - (define def-id (make-hash))) - -;; defines an rpc implementation, registers it with a given class of rpcs and makes a wrapper to -;; call it -(define-simple-macro (define-rpc type:id (name:id args:id ...) body:expr ...) - #:with def-id (rpc-type-id #'type) - #:with impl-id (rpc-impl-id #'name) - (begin - (define (impl-id args ...) body ...) - (define (name args ...) - (tm-transact (current-tm) (current-to-node) (quote name) (list args ...))) - (hash-set! def-id (quote name) impl-id))) - -;; installs all rpcs of a given rpc class into the transaction manager -(define-simple-macro (install-rpc-type type:id) - #:with def-id (rpc-type-id #'type) - (for ([(k v) (in-hash def-id)]) - (tm-register-rpc (current-tm) k v))) +(define SERVER-DATA-DIR (if PRODUCTION? "/var/lib/crossfire/" "lib/")) +(define SERVER-DB-PATH (build-path SERVER-DATA-DIR "crossfire.sqlite")) -;; ok now we get to the real stuff -;; server rpc functions +;; database + +(define (open-server-db) + (sqlite3-connect #:database SERVER-DB-PATH)) + +(define current-db (make-parameter #f)) + +(define (with-server-db proc) + (parameterize ([current-db (open-server-db)]) + (proc) + (disconnect (current-db)))) + + +;; rpc calls (define-rpc-type server) @@ -67,6 +50,3 @@ (add1 a)) -;; agent rpc functions - -;; TODO ...