syndicate-2017/racket/syndicate/examples/actor/example-demand-matcher-glit...

37 lines
1.6 KiB
Racket

#lang syndicate/actor
;; Example showing an interesting design flaw (?) (bug?) in the
;; old-school LLL demand-matcher when demand changes too quickly. The
;; port 6000 server is started, but by the time it starts monitoring
;; demand for its services, the demand is already gone, replaced with
;; demand for port 5999. This causes connections to be accepted on
;; port 6000 going nowhere.
;;
;; One fix is to use #:assertions to give the TCP listener actor some
;; initial interests, thus transferring responsibility atomically.
;; Another is to modify the demand-matcher to do something like
;; `during/spawn` is doing, using an auxiliary protocol to centralise
;; tracking of demand and supply at the demand-matcher rather than
;; delegating it to the services.
(require syndicate/protocol/advertise)
(require/activate syndicate/drivers/tcp)
(struct listen-port (number) #:prefab) ;; assertion
(define default-port 6000)
(spawn #:name 'connection-acceptor
(define/query-value port default-port (listen-port $v) v)
(assert (advertise (observe (tcp-channel _ (tcp-listener (port)) _))))
(during (advertise (tcp-channel $c (tcp-listener (port)) _))
(let ((accepted-port (port))) ;; capture field value at time of connect
(assert (advertise (tcp-channel (tcp-listener accepted-port) c _)))
(on-start
(printf "Accepted connection from ~v on port ~a\n" c accepted-port)
(send! (tcp-channel (tcp-listener accepted-port) c #"Hello!\n")))
(on-stop
(printf "Closed connection ~v on port ~a\n" c accepted-port)))))
(spawn #:name 'configuration-provider
(assert (listen-port 5999)))