add initial framework for distributing subtasks
This commit is contained in:
parent
2d45fe666b
commit
737230c433
|
@ -240,6 +240,8 @@
|
||||||
from (or (= data (node-id my-node)) (hash-has-key? peer-registry data) #f))]
|
from (or (= data (node-id my-node)) (hash-has-key? peer-registry data) #f))]
|
||||||
['get-node-info (thread-send from (hash-ref node-registry data #f) #f)]
|
['get-node-info (thread-send from (hash-ref node-registry data #f) #f)]
|
||||||
['set-node-info (hash-set! node-registry (node-id data) data) (thread-send from (void) #f)]
|
['set-node-info (hash-set! node-registry (node-id data) data) (thread-send from (void) #f)]
|
||||||
|
;; also call destroy-channel
|
||||||
|
['raw-delete-node (hash-remove! node-registry data) (thread-send from (void) #f)]
|
||||||
['register-channel
|
['register-channel
|
||||||
(match-define (cons peer-id thd) data)
|
(match-define (cons peer-id thd) data)
|
||||||
(when (hash-has-key? peer-registry peer-id)
|
(when (hash-has-key? peer-registry peer-id)
|
||||||
|
@ -319,6 +321,10 @@
|
||||||
(define (comms-get-node-info comms id)
|
(define (comms-get-node-info comms id)
|
||||||
(thread-sendrecv comms 'get-node-info id))
|
(thread-sendrecv comms 'get-node-info id))
|
||||||
|
|
||||||
|
(define (comms-delete-node comms id)
|
||||||
|
(thread-sendrecv comms 'destroy-channel id)
|
||||||
|
(thread-sendrecv comms 'raw-delete-node id))
|
||||||
|
|
||||||
(define (comms-local-channel comms)
|
(define (comms-local-channel comms)
|
||||||
(thread-sendrecv comms 'local-channel (void)))
|
(thread-sendrecv comms 'local-channel (void)))
|
||||||
|
|
||||||
|
@ -344,7 +350,7 @@
|
||||||
(comms-dispatch-msg comms to-id msg)))
|
(comms-dispatch-msg comms to-id msg)))
|
||||||
|
|
||||||
(provide make-comms comms-listen comms-connect comms-get-node-info comms-set-node-info
|
(provide make-comms comms-listen comms-connect comms-get-node-info comms-set-node-info
|
||||||
comms-channel-available?)
|
comms-delete-node comms-channel-available?)
|
||||||
|
|
||||||
;; transactional messages support
|
;; transactional messages support
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,8 @@ create table node_resource(nodeid integer not null, resource text not null,
|
||||||
-- }
|
-- }
|
||||||
-- @up {
|
-- @up {
|
||||||
create table task(id integer primary key, name text not null, manifest blob not null,
|
create table task(id integer primary key, name text not null, manifest blob not null,
|
||||||
committed boolean not null);
|
committed boolean not null default false,
|
||||||
|
complete boolean not null default false);
|
||||||
-- }
|
-- }
|
||||||
-- @up {
|
-- @up {
|
||||||
create table task_log(taskid integer not null, worker integer not null,
|
create table task_log(taskid integer not null, worker integer not null,
|
||||||
|
|
|
@ -17,13 +17,17 @@
|
||||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
(require (only-in data/integer-set make-integer-set integer-set-contents [union integer-set-union]
|
(require (only-in data/integer-set make-integer-set integer-set-contents [union integer-set-union]
|
||||||
[count integer-set-count])
|
[count integer-set-count] [intersect integer-set-intersect]
|
||||||
|
[subtract integer-set-subtract])
|
||||||
racket/list racket/match racket/vector)
|
racket/list racket/match racket/vector)
|
||||||
|
|
||||||
(provide pos->integer-set-pos
|
(provide char->integer-set string->integer-set range->integer-set
|
||||||
char->integer-set string->integer-set range->integer-set
|
;; re-export renamed integer-set accessors
|
||||||
|
make-integer-set integer-set-contents integer-set-count integer-set-union
|
||||||
|
integer-set-intersect integer-set-subtract
|
||||||
builtin-isets
|
builtin-isets
|
||||||
pattern-count pos->pattern-pos resolve-pattern-pos)
|
pattern-count pos->pattern-pos resolve-pattern-pos
|
||||||
|
pattern-range-take)
|
||||||
|
|
||||||
;; pattern processing
|
;; pattern processing
|
||||||
;; NOTE: data/integer-set WFS intervals are INCLUSIVE
|
;; NOTE: data/integer-set WFS intervals are INCLUSIVE
|
||||||
|
@ -101,3 +105,18 @@
|
||||||
(define (resolve-pattern-pos pattern pp)
|
(define (resolve-pattern-pos pattern pp)
|
||||||
(for/vector ([iset (in-vector pattern)] [pos (in-vector pp)])
|
(for/vector ([iset (in-vector pattern)] [pos (in-vector pp)])
|
||||||
(pos->integer-set-pos iset pos)))
|
(pos->integer-set-pos iset pos)))
|
||||||
|
|
||||||
|
;; utils for pattern ranges [0, pattern-count) mapped to patterns with the above functions
|
||||||
|
;; a pattern range is represented by an integer-set, the wfs item boundaries would get converted
|
||||||
|
;; into resolved pattern pos, etc
|
||||||
|
|
||||||
|
;; takes up to n elements from the pattern range
|
||||||
|
;; returns the subrange and pr minus subrange
|
||||||
|
(define (pattern-range-take pr n)
|
||||||
|
(cond
|
||||||
|
[(>= n (integer-set-count pr)) (values pr (make-integer-set '()))]
|
||||||
|
[else
|
||||||
|
(match-define (cons _ bound) (pos->integer-set-pos pr (sub1 n)))
|
||||||
|
(define subrange (integer-set-intersect (make-integer-set `((0 . ,bound))) pr))
|
||||||
|
(define new-pr (integer-set-subtract pr subrange))
|
||||||
|
(values subrange new-pr)]))
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
(require db/base db/sqlite3
|
(require db/base db/sqlite3
|
||||||
racket/bool racket/fasl racket/file racket/match racket/runtime-path racket/path
|
data/queue racket/bool racket/fasl racket/file racket/match
|
||||||
racket/set racket/string
|
racket/path racket/runtime-path racket/set racket/string
|
||||||
north/base north/adapter/base north/adapter/sqlite
|
north/base north/adapter/base north/adapter/sqlite
|
||||||
"comms.rkt" "not-crypto.rkt"
|
"comms.rkt" "not-crypto.rkt"
|
||||||
;; port-fsync
|
;; port-fsync
|
||||||
|
@ -77,14 +77,15 @@
|
||||||
where node.type = ?")
|
where node.type = ?")
|
||||||
(define-stmt q-get-node-resources "select resource from node_resource where nodeid=?")
|
(define-stmt q-get-node-resources "select resource from node_resource where nodeid=?")
|
||||||
(define-stmt q-edit-node "update node set name=? where id=?")
|
(define-stmt q-edit-node "update node set name=? where id=?")
|
||||||
|
(define-stmt q-delete-node "delete from node where id=?")
|
||||||
(define-stmt q-get-node-type "select type from node where id=?")
|
(define-stmt q-get-node-type "select type from node where id=?")
|
||||||
(define-stmt q-get-node-info "select name, arch, type, secret from node where id=?")
|
(define-stmt q-get-node-info "select name, arch, type, secret from node where id=?")
|
||||||
|
|
||||||
(define-stmt q-new-task "insert into task (name, manifest, committed) values (?, ?, 0)")
|
(define-stmt q-new-task "insert into task (name, manifest) values (?, ?)")
|
||||||
(define-stmt q-get-task-id-commit "select id, committed from task")
|
(define-stmt q-get-task-id-commit "select id, committed from task")
|
||||||
(define-stmt q-set-task-commit "update task set committed=1 where id=?")
|
(define-stmt q-set-task-commit "update task set committed=1 where id=?")
|
||||||
(define-stmt q-delete-task "delete from task where id=?")
|
(define-stmt q-delete-task "delete from task where id=?")
|
||||||
(define-stmt q-get-tasks "select id, name, manifest from task")
|
(define-stmt q-get-tasks "select id, name, manifest, complete from task")
|
||||||
|
|
||||||
;; utils
|
;; utils
|
||||||
|
|
||||||
|
@ -134,7 +135,7 @@
|
||||||
(define-rpc-type server)
|
(define-rpc-type server)
|
||||||
|
|
||||||
(struct node-info [id name arch type resources online?] #:prefab)
|
(struct node-info [id name arch type resources online?] #:prefab)
|
||||||
(struct project-info [id name manifest] #:prefab)
|
(struct project-info [id name manifest complete?] #:prefab)
|
||||||
|
|
||||||
(define (get-nodes type)
|
(define (get-nodes type)
|
||||||
(define type-str (symbol->string type))
|
(define type-str (symbol->string type))
|
||||||
|
@ -208,7 +209,9 @@
|
||||||
(for ([res (in-set (set-subtract new-resource existing-resource))])
|
(for ([res (in-set (set-subtract new-resource existing-resource))])
|
||||||
(query-exec (current-db) q-add-node-res id res))
|
(query-exec (current-db) q-add-node-res id res))
|
||||||
(for ([res (in-set (set-subtract existing-resource new-resource))])
|
(for ([res (in-set (set-subtract existing-resource new-resource))])
|
||||||
(query-exec (current-db) q-del-node-res id res)))))
|
(query-exec (current-db) q-del-node-res id res))))
|
||||||
|
(define comms-node (comms-get-node-info (current-comms) id))
|
||||||
|
(comms-set-node-info (current-comms) (struct-copy node comms-node [name name])))
|
||||||
|
|
||||||
(define-rpc server (get-agent-deployment id)
|
(define-rpc server (get-agent-deployment id)
|
||||||
(enforce-subject 'client)
|
(enforce-subject 'client)
|
||||||
|
@ -218,16 +221,25 @@
|
||||||
arch (current-server-public-node))]
|
arch (current-server-public-node))]
|
||||||
[_ (error "invalid id or wrong node type")]))
|
[_ (error "invalid id or wrong node type")]))
|
||||||
|
|
||||||
|
(define-rpc server (delete-agent id)
|
||||||
|
(enforce-subject 'client)
|
||||||
|
(call-with-transaction (current-db) (lambda ()
|
||||||
|
(enforce-object id 'agent)
|
||||||
|
(query-exec (current-db) q-delete-node id)))
|
||||||
|
(comms-delete-node (current-comms) id))
|
||||||
|
|
||||||
;; client rpcs :: projects
|
;; client rpcs :: projects
|
||||||
|
|
||||||
(define-rpc server (new-project name manifest tar)
|
(define-rpc server (new-project name manifest tar)
|
||||||
(enforce-subject 'client)
|
(enforce-subject 'client)
|
||||||
(make-task name manifest tar))
|
(define id (make-task name manifest tar))
|
||||||
|
(void id)
|
||||||
|
id)
|
||||||
|
|
||||||
(define-rpc server (get-projects)
|
(define-rpc server (get-projects)
|
||||||
(enforce-subject 'client)
|
(enforce-subject 'client)
|
||||||
(for/list ([(id name manifest) (in-query (current-db) q-get-tasks)])
|
(for/list ([(id name manifest complete?) (in-query (current-db) q-get-tasks)])
|
||||||
(project-info id name (fasl->s-exp manifest))))
|
(project-info id name (fasl->s-exp manifest) complete?)))
|
||||||
|
|
||||||
;; agent rpcs
|
;; agent rpcs
|
||||||
|
|
||||||
|
@ -236,6 +248,51 @@
|
||||||
(error "TODO"))
|
(error "TODO"))
|
||||||
|
|
||||||
|
|
||||||
|
;; agent handling
|
||||||
|
;; distributing subtasks
|
||||||
|
|
||||||
|
;; minimum batch of inputs that will be scheduled for a node
|
||||||
|
;; the batch size scales to how fast the node completes a batch
|
||||||
|
(define MIN-SUBTASK-SIZE 10)
|
||||||
|
;; aim to batch every 5 minutes
|
||||||
|
(define OPTIMAL-COMPLETION-SECS 300)
|
||||||
|
|
||||||
|
(define (agent-handler)
|
||||||
|
;; unlike comms, messages to agent-handler have no responses. just thread-send, it's one-way
|
||||||
|
(define cust (make-custodian))
|
||||||
|
(define this-thread (current-thread))
|
||||||
|
;; make an auto cleanup thread :P
|
||||||
|
(thread (lambda () (thread-wait this-thread) (custodian-shutdown-all cust)))
|
||||||
|
|
||||||
|
;; tasks
|
||||||
|
;; pending task queue
|
||||||
|
(define task-queue (make-queue))
|
||||||
|
;; id to manifest
|
||||||
|
(define current-tasks (make-hash))
|
||||||
|
|
||||||
|
;; agent state
|
||||||
|
(struct state [task-id pattern time-start errors] #:transparent #:mutable)
|
||||||
|
;; hash of agents and states
|
||||||
|
(define agents (make-hash))
|
||||||
|
|
||||||
|
(define (handle-thd-msg)
|
||||||
|
(match (thread-receive)
|
||||||
|
[(cons 'new-agent (cons id resources)) (error "TODO")]
|
||||||
|
[(cons 'delete-agent id) (error "TODO")]
|
||||||
|
[(cons 'new-task (cons id manifest)) (error "TODO")]
|
||||||
|
[(cons 'cancel-task id) (error "TODO")]
|
||||||
|
[_ (error "unknown agent handler message")]))
|
||||||
|
|
||||||
|
(let loop ()
|
||||||
|
(define thd-evt (thread-receive-evt))
|
||||||
|
(match (sync thd-evt)
|
||||||
|
[(== thd-evt) (handle-thd-msg)])
|
||||||
|
(loop)))
|
||||||
|
|
||||||
|
(define (make-agent-handler)
|
||||||
|
(thread agent-handler))
|
||||||
|
|
||||||
|
|
||||||
;; command line usage
|
;; command line usage
|
||||||
(module+ main
|
(module+ main
|
||||||
(require racket/cmdline)
|
(require racket/cmdline)
|
||||||
|
|
Loading…
Reference in New Issue