Building Clients

This page is very incomplete and a work in progress.

Implementing sideloading

Let’s start by looking at an exchange of messages while using sideloading:

;; -> init sideloading
{:op      "sideloader-start"
 :id      "1"
 :session "x"}
{:op      "eval"
 :id      "2"
 :session "x"
 :code    (quote (require '[foo.bar :as bar])
                 (bar/qaz))}
;; <- lookup for foo.bar
{:id      "1"
 :session "x"
 :status  :sideloader-lookup
 :type    "resource"
 :name    "foo/bar.clj"}
;; -> providing resource
{:id      "3"
 :session "x"
 :op      "sideloader-provide"
 :type    "resource"
 :name    "foo/bar.clj"
 :content "<base64 package>"}
;; <- ack of provided resource
{:id      "3"
 :session "x"
 :status  :done}
;; <- result of eval
{:id      "2"
 :session "x"
 :value   "Qaz"
 :status  :done}

Note that between sending the eval op in message 2 and receiving the result, two other messages were dealt with:

  • We received a response from message 1, requesting a resource. This indicates that the the resource was not found on the server JVM, and evaluation is blocked until we provide it, or respond with an empty package.

  • We provide the resource/file using message 3, to which the server responds with a :done.

This unblocks the eval command, which returns the value Qaz in the final message.

It’s thus important, once sideloading has started, to asynchronously handle lookup requests, without these being blocked by waiting on a response from another message.