syndicate-rkt/syndicate/broker/server.rkt

60 lines
2.3 KiB
Racket

#lang imperative-syndicate
(provide (struct-out server-connection)
(struct-out server-inbound)
(struct-out server-outbound)
(struct-out server-envelope))
(require "wire-protocol.rkt")
(require imperative-syndicate/term)
(require racket/set)
;; Internal connection protocol
(assertion-struct server-connection (connection-id scope))
(assertion-struct server-inbound (connection-id body))
(assertion-struct server-outbound (connection-id body))
;; Internal isolation
(assertion-struct server-envelope (scope body))
(spawn #:name 'server-connection-factory
(during/spawn (server-connection $id $scope)
(define endpoints (set))
(on (message (server-inbound id (Assert $ep $a)))
(when (not (set-member? endpoints ep))
(set! endpoints (set-add endpoints ep))
(react
(on-stop (set! endpoints (set-remove endpoints ep)))
(field [assertion a])
(define (recompute-endpoint)
(define a (assertion))
(if (observe? a)
(let* ((pattern (observe-specification a))
(spec (server-envelope scope pattern)))
(values (observe spec)
(term->skeleton-interest
spec
(capture-facet-context
(lambda (op . captured-values)
(schedule-script!
(current-actor)
(lambda ()
(define ctor (match op ['+ Add] ['- Del] ['! Msg]))
(send! (server-outbound id (ctor ep captured-values))))))))))
(values (server-envelope scope a) #f)))
(add-endpoint! (current-facet) "server" #t recompute-endpoint)
(on (message (server-inbound id (Assert ep $new-a)))
(assertion new-a))
(stop-when (message (server-inbound id (Clear ep)))))))
(on (message (server-inbound id (Message $body)))
(send! (server-envelope scope body)))
(on (message (server-inbound id (Ping)))
(send! (server-outbound id (Pong))))))