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 ...