Next: Introduction, Previous: (dir), Up: (dir) [Contents][Index]
This is the intercom Reference Manual, version 0.0.1, generated automatically by Declt version 2.4 "Will Decker" on Wed Jun 20 12:01:49 2018 GMT+0.
• Introduction: | What intercom is all about | |
• Systems: | The systems documentation | |
• Files: | The files documentation | |
• Packages: | The packages documentation | |
• Definitions: | The symbols documentation | |
• Indexes: | Concepts, functions, variables and data types |
h1. Intercom Intercom is an easy to use library for high-level, bi-direcational communication between javascript and a lisp image with hunchentoot. It tries to optimize the amount of requests to the server and keeps the interface clean. Features: * JSON communication channel * automatically adapting polling speed * clean js and lisp RPC interface * multiple responses per request * requests can be canceled * bundled requests and responses h2. Simple Example As a simple example, we create a remote procedure call which sends you astring
everyinterval
seconds,count
times. h3. Lisp implementation To define a remote procedure in the lisp backend, you use the macrodefine-remote-procedure
. The first argument is the name of the remote procedure, which can be either astring
or asymbol
(which will be downcased). The following is an arg list, similar to what you would expect in a function definition. These values will be filled in with jsown objects (this can be lisp numbers, lisp lists, lisp strings or jsown representations of a javascript object). Inside the body of the RPC definition, you have access to themessage
function. This sends a response for _this_ RPC to the client. The first argument is atype
of the response, the second argument is a jsown instance, which represents thebody
. Remember, many lisp primitives are jsown objects.h3. Javascript implementation The javascript side uses a ks.Intercom object to interact with the server. The intercom object is initialized with the url of the server. Requests are made to the /talk interface of the server. To call a remote procedure on the server, you use the call function of an intercom object. This call function expects an object with the following properties: * *name* the name of the remote procedure to call * *args* the arguments to be passed to the remote procedure, as a list of JSON objects or javascript primitives. * *keys* when a message with this type is received, we stop listening for further requests for this RPC and call the onFinish function. * *onResponse* this function gets called when we receive a message from the server. The entire message object is passed in as an argument. * *onFinish* this function gets called when a message is received with a type in the(define-remote-procedure echo (string count interval) (loop repeat count do (sleep interval) (message "value" string)) (message "ready" :true))
keys
list. It behaves exactly as the onResponse function.The response argument that is passed in to thevar intercom=new ks.Intercom({url:"/talk"}); intercom.call({name:"test", args:[10,2,1], keys:["ready"], onResponse:function(response){ console.log("intermediate response: " +JSON.stringify(response)); }, onFinish:function(response){ console.log("final response: "+ JSON.stringify(response)); } });
onResponse
andonFinish
function is a javascript object with the following properties: * *type* the type of response that was provided by the server. If this type is contained in thekeys
list of the call, theonFinish
function is called instead of theonResponse
function. * *body* the body of the response the actual content that is returned by the server. h3. What happens on the wire # Slow speed polling # intercom.call(...) # immediately send request + start high speed polling # responses arrive # ... # final resonse arrives + start slow speed polling Or in prosaic format: When no requests are running on the server, we poll the server at a slow speed (configurable through the defaultPollSpeed property of the intercom object in ms). When a call is made, this speed can be increased. At every poll to the server, we requests all messages that the server wishes to send and send them to the javascript client. At the client side, these responses are then handled by the appropriate request. When no active requests remain, the polling speed is decreased again. The fast pollspeed when there are open requests is obtained by taking the minimum of the following properties: * the minimum of the minSpeed properties of the open requests (for requests that specify this property) in ms. * the minimum of the result of the getSpeedAfterTime function of the open requests if such a function is specified. This function accepts a time in ms since the request was accepted and returns the pollspeed in ms. * the defaultPollSpeed property of the intercom object in ms. Please note that the polling mechanism is used as a heartbeat as well. As a result, we have had to limit the minimum pollSpeed to one poll per ten seconds. Values of more than 10000 will be interpreted as being equal to the maximum. Values smaller than zero will be assumed equal to zero (poll as soon as possible). h2. Javascript Features The API that is provided on the javascript side consists of the ks.Intercom class and its three public functions:call
,cancel
andcomplete
. Thecall
function has been described in some detail above. However, it is worth noting that thecall
function actually returns an object that can be used to cancel a request, as in the following example:Thevar request=intercom.call( {name:"echo", args:[{string:"foobar", count:3, interval:1}], keys:["ready"], onResponse:function(response){ console.log("received single response with body: "+response.body); }, onFinish:function(response){ console.log("received final response with body: "+response.body); } }); ... results.intercom.cancel(request);
cancel
function expects an object that was created by thecall
function. It sends a message to the server to inform it that no further messages are required for the given request and also calls thecomplete
function on the intercom object. Thecomplete
function also expects an object that was created by thecall
function. It simply tells the intercom object to stop listening for messages for the given request. It does not inform the server about this, as it is assumed the server already knows (this happens for instance when the server sends a message with a finalizing type). Users are not recommended to use the complete function, they should use the keys list of a request instead. h2. Lisp Features the implementation on te lisp side offers two 'special' features when defininig remote procedure calls. h3. RPC name The name of the RPC can either be a string or a symbol. When a string is used, this name can be used (case sensitive) for identifying the RPC in the javascript call. When a symbol is used, it is downcased and the downcased name is used for the javascript call. Let's build two example functions and check when each one is called when.The following javascript calls call both remote procedures.(define-remote-procedure echo (string) (message "result" string)) (define-remote-procedure "eCHo" (string) (message "result" (format nil "HELLO! ~A" string)))
They result in these messages to be logged on the console:intercom.call( {name:"echo", args:["Hello John"], keys:["result"], onFinish:function(response){ console.log("echo resulted in " + response.body); }}); intercom.call( {name:"eCHo", args:["Hello Jake"], keys:["result"], onFinish:function(response){ console.log("eCHo resulted in " + response.body); }});
h3. Keyword Arguments Theecho resulted in Hello John eCHo resulted in HELLO! Hello Jake
&key
argument in the parameter list in the definition of a remote procedure would traditionally be nonsensical when coming from a list of javascript objects. There's no way to generate keyword symbols from the javascript side. The use of the&key
argument list destructures the javascript object and fetches the keys with that name from the javascript object. The name of the key to fetch is the lowercased name of the symbol. This allows for a slightly more javascript-style of passing complex arguments. Let's build two examples to show how this can make code i bit more readable.These examples can be called with the following javascript snippets:(define-remote-procedure hello (friend-p &key first-name last-name) (message "result" (if friend-p (format nil "Hello ~A ~A" first-name last-name) (format nil "Hi ~A" first-name)))) (define-remote-procedure format-buy-car (&key title first-name last-name &key make type engine) (message "result" (format nil "~A ~A ~A is buying a ~A ~A with a ~A in it." title first-name last-name make type engine)))
h2. Performance Considerations For every RPC a new thread is built. If you have a lot active threads, this can hose your system.intercom.call( {name:"hello", args:[false, {"first-name":"James", "last-name":"Dean"], keys:["result"], onFinish:function(response){ console.log(response.body); }}); intercom.call( {name:"format-buy-car", args:[{title:"Mr.", "first-name":"Bill", "last-name":"Gates"}, {make:"Seat",type:"Marbella",engine:"843cc"}], keys:["result"], onFinish:function(response){ console.log(response.body); }});
Next: Files, Previous: Introduction, Up: Top [Contents][Index]
The main system appears first, followed by any subsystem dependency.
• The intercom system: |
Aad Versteden <aad@knowified.com>
Aad Versteden <aad@knowified.com>
MIT
Intercom allows bidirectional message passing between javascript and lisp.
0.0.1
intercom.asd (file)
Files are sorted by type and then listed depth-first from the systems components trees.
• Lisp files: |
• The intercom.asd file: | ||
• The intercom/packages.lisp file: | ||
• The intercom/intercom.lisp file: |
Next: The intercom/packages<dot>lisp file, Previous: Lisp files, Up: Lisp files [Contents][Index]
intercom.asd
intercom (system)
Next: The intercom/intercom<dot>lisp file, Previous: The intercom<dot>asd file, Up: Lisp files [Contents][Index]
Previous: The intercom/packages<dot>lisp file, Up: Lisp files [Contents][Index]
packages.lisp (file)
intercom (system)
intercom.lisp
Next: Definitions, Previous: Files, Up: Top [Contents][Index]
Packages are listed by definition order.
• The intercom package: |
packages.lisp (file)
Definitions are sorted by export status, category, package, and then by lexicographic order.
• Exported definitions: | ||
• Internal definitions: |
Next: Internal definitions, Previous: Definitions, Up: Definitions [Contents][Index]
• Exported special variables: | ||
• Exported macros: | ||
• Exported functions: |
Next: Exported macros, Previous: Exported definitions, Up: Exported definitions [Contents][Index]
the time we have before we assume the session has ended.
intercom.lisp (file)
the time we have before we assume the head is detached.
intercom.lisp (file)
when non-nil, this should be a character stream. an s-expression based log is written to the
stream containing the ping-times, the requests and the responses for each user. the format is
as follows:
- ping :: (ping utime hydra-body-id hydra-head-id ip-address)
- request :: (req utime hydra-body-id hydra-head-id request-id request-name arg1..argn)
- responses :: (res utime hydra-body-id hydra-head-id request-id time message-type message-value)
- closes :: (close utime hydra-body-id hydra-head-id request-id)
intercom.lisp (file)
should contain an alist in which the keywords are special variables and the values are evaluated (in the creating thread) each time a remote procedure is built. this allows you to pass special variables.
intercom.lisp (file)
Next: Exported functions, Previous: Exported special variables, Up: Exported definitions [Contents][Index]
defines a remote procedure with <name> as the name to be called and <arguments> as the assumed arguments. if <name> is a symbol with only non- lower-case-p characters, then it is converted to lowercase.
intercom.lisp (file)
creates a lambda which can be threaded. it locally binds the variables which are needed by intercom.
intercom.lisp (file)
executes <body> in an environment in which all errors are catched and sent as a message with type "fail" to the user.
intercom.lisp (file)
executes <body> with a lock on the datastore of hydra-head.
this should be used when the new value is based on previous values in the session.
intercom.lisp (file)
executes <body> with a lock on the datastore of hydra-body.
this should be used when the new value is based on previous values in the session.
intercom.lisp (file)
Previous: Exported macros, Up: Exported definitions [Contents][Index]
returns non-nil if we are currently in an active remote procedure. alias for in-active-remote-procedure-p.
intercom.lisp (file)
adds <function> to the list of functions to call on garbage collection of <screen>.
intercom.lisp (file)
adds <function> to the list of functions to call on garbage collection of <session>.
intercom.lisp (file)
returns non-nil iff the end of the current remote-procedure indicates that the rid should be killed. setfable place defaults to t.
intercom.lisp (file)
(setf auto-end-remote-procedure-p) (function)
sets the killing of the remote-procedure to <value>. non-nil indicates that the remote-procedure should be killed (the default), nil indicates the inverse.
intercom.lisp (file)
auto-end-remote-procedure-p (function)
handle-talk-request handles a talk request.
splitting this off allows us to handle talking when easy-handlers aren’t in use.
intercom.lisp (file)
sends a message to the client
intercom.lisp (file)
removes <function> from the list of functions to call on the garbage collection of <screen>.
intercom.lisp (file)
removes <function> from the list of functions to call on the garbage collection of <session>.
intercom.lisp (file)
returns the value of <key> which belongs to <screen>, or nil if it didn’t exist. the second value is non-nil iff <key> was found in <screen>.
intercom.lisp (file)
(setf screen-var) (function)
sets the value of ,key> which belongs to <screen> to <value>.
intercom.lisp (file)
screen-var (function)
returns the value of <key> which belongs to <session>, or nil if it didn’t exist. the second value is non-nil iff <key> was found in <session>.
intercom.lisp (file)
(setf session-var) (function)
sets the value of ,key> which belongs to <session> to <value>.
intercom.lisp (file)
session-var (function)
translates the remote procedure name <name> to the remote procedure name as can be called from the javascript world.
intercom.lisp (file)
Previous: Exported definitions, Up: Definitions [Contents][Index]
• Internal special variables: | ||
• Internal macros: | ||
• Internal functions: | ||
• Internal generic functions: | ||
• Internal structures: |
Next: Internal macros, Previous: Internal definitions, Up: Internal definitions [Contents][Index]
when this is set to non-nil in a given thread (which is the default for call-remote-procedure, then the ending of the call to call-remote-procedure signals the end of the rid. you can turn it on with #’auto-end-remote-procedure and turn it off with #’dont-auto-end-remote-procedure.
intercom.lisp (file)
contains the internal runtime when this RPC call was started.
intercom.lisp (file)
this lock is used when accessing the hydra-auth-store
intercom.lisp (file)
a hash-table linking each "hydra" cookie value to the authentication which belongs to it.
intercom.lisp (file)
contains the hydra-body once we have a hydra-body in the current request
intercom.lisp (file)
contains the hydra-head once we have one in the current request
intercom.lisp (file)
represents the screen identifier of the current request
intercom.lisp (file)
this lock should be held when writing to the log stream.
intercom.lisp (file)
contains all intercom remote procedures, the keywords being the matched string and the values being the corresponding function.
intercom.lisp (file)
variable which contains the request id in functions which represent the execution of a remote procedure.
intercom.lisp (file)
Next: Internal functions, Previous: Internal special variables, Up: Internal definitions [Contents][Index]
asserts that place is an eql-compatible place.
this means it must be one of:
1. a symbol
2. a character
3. a number
intercom.lisp (file)
asserts that <place> contains a hydra-body
intercom.lisp (file)
asserts that <place> contains a hydra-head
intercom.lisp (file)
asserts that <place> contains a hydra-session
intercom.lisp (file)
asserts that <place> contains a non-empty string.
intercom.lisp (file)
intercom.lisp (file)
executes a hunchentoot request in an environment in which the special local variables are
bound to be special and local.
this contains:
- *hydra-body*
- *hydra-head*
- *hydra-head-id*
intercom.lisp (file)
executes <body> in an environment where the <log*> function is defined iff *log-request-stream* is non-nil. the <log*> function takes the type of content to log, followed by the content itself by &rest and it splices hydra-body-id hydra-head-id in that list.
intercom.lisp (file)
makes sure each variable in variables is bound to itself, essentially allowing you to write ,, in a double backtick to get that symbol. handy for gensym.
intercom.lisp (file)
executes <body> in an environment in which *hydra-auth-store* is locked.
intercom.lisp (file)
executes body in an environment in which <store> is locked.
intercom.lisp (file)
executes <body> in a piece of code in which the head’s data is locked
intercom.lisp (file)
Next: Internal generic functions, Previous: Internal macros, Up: Internal definitions [Contents][Index]
asserts that we’re currently running in an environment which is sane for intercom requests/executions
intercom.lisp (file)
attaches <hydra-head> to <hydra-body>
intercom.lisp (file)
builds a new authentication, which identifies hydra-body, and stores it in the necessary structures.
intercom.lisp (file)
builds a new hydra-body and sets it as the current hydra-body.
intercom.lisp (file)
calls the remote prodecure with name <name> and <args> as the arguments with <rid> as reference. assumes the special variables *hydra-head* and *hydra-body* exist and respectively contain a hydra-head and a hydra-body.
intercom.lisp (file)
handles the logging of close requests
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
discover-hydra returns non-nil iff we had a session-cookie through which we could find a hydra session-validation which is valid for our current session. this function sets up all special variables for the hydra to be happy. it also touches the hydra-body and the relevant hydra-head so we’re active.
intercom.lisp (file)
returns non-nil iff we had a session-cookie through which we could
find a hydra session-validation which is valid for our current session.
this function sets up all special variables for the hydra-body,
but leaves the hydra-head for another solution to figure out.
intercom.lisp (file)
returns the hhid if one was given as a get-variable, or creates a new hhid.
does *not* put the hhid on the message stack.
returns (values hhid newp). if newp is t, a message should be sent to the
client (see (send-current-hhid)) so the client knows the hhid.
intercom.lisp (file)
ensures the hydra is set up. this means that:
- after this function execution:
- *hydra-head* is bound to the hydra’s head
- *hydra-body* is bound to the hydra’s body
- *hydra-auth-store* contains an authentication for continued storage
- after this request:
- the user has a "hydra" cookie which links to this session.
intercom.lisp (file)
ensures the hydra-head exists and is set in the variable *hydra-head*. assumes *hydra-body* is set. returns the current hydra-head.
intercom.lisp (file)
fetches and clears the messages in the mailbox
intercom.lisp (file)
garbage collect the head hydras. this removes the session-validation objects and removes the head heads.
intercom.lisp (file)
garbage-collects a hydra-body
intercom.lisp (file)
garbage-collects a hydra-head
intercom.lisp (file)
detaches the dead heads from <hydra-body>.
intercom.lisp (file)
we generate an id by taking the universal time and augmenting it by some random number
intercom.lisp (file)
returns the remote procedure for <name> or nil if the procedure doesn’t exist.
intercom.lisp (file)
returns a list of all hash-keys in <hash>
intercom.lisp (file)
returns non-nil iff the <hydra> hasn’t been touched for too long of a time.
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
returns non-nil iff the <hydra> hasn’t been touched for too long of a time.
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
returns non-nil if we are currently in a remote procedure with an active rid.
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
reads the key from store
intercom.lisp (file)
(setf kv-store-read) (function)
sets <key> in <store> to <value>
intercom.lisp (file)
kv-store-read (function)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
constructs a log message string for type and the followed arguments.
intercom.lisp (file)
builds the s-expression representation for the lambda function which can be called for the definition of a remote procedure. this handles the creation of the &key arguments.
intercom.lisp (file)
constructs a new session-validation object for the current session.
intercom.lisp (file)
intercom.lisp (file)
closes the request for the rid.
intercom.lisp (file)
performs an intercom request as described by <jsown-request>.
intercom.lisp (file)
handles the logging of the ping request
intercom.lisp (file)
registers the remote procedure for <name> to be <function>.
intercom.lisp (file)
removes the session-validation <session-validation> from the known validations.
intercom.lisp (file)
removes the <rid> from the list of active rids
intercom.lisp (file)
handles the logging of the new requests
intercom.lisp (file)
handles the logging of the responses
intercom.lisp (file)
returns all hydra session-varlidation instance which belong to the given hydra-id
intercom.lisp (file)
returns non-nil iff <rid> is active for the current user. by use of the variable my-active-rids, the currently active rids can be overridden. !only use when you know what you’re doing!
intercom.lisp (file)
pretty-prints and concatenates the resulting strings of each arg in <args>.
intercom.lisp (file)
sends the current hhid to the client by using the correct intercom message. requires that *hydra-head* and *hydra-head-id* are set correctly.
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
intercom.lisp (file)
sets <rid> to be active
intercom.lisp (file)
stores the hydra session-validation so it can be found back.
intercom.lisp (file)
intercom.lisp (file)
calculates the initial bindings for the current thread. this consists of whatever is available in bordeaux-threads:*initial-bindings*, but with what *remote-procedure* contains in front of it (in which the values are evaluated).
intercom.lisp (file)
validates the session-validation for the current request
intercom.lisp (file)
Next: Internal structures, Previous: Internal functions, Up: Internal definitions [Contents][Index]
touches an object, updating the modification time.
intercom.lisp (file)
Previous: Internal generic functions, Up: Internal definitions [Contents][Index]
intercom.lisp (file)
structure-object (structure)
touch (method)
(intercom::make-key-value-store)
hydra-body-data (function)
(setf hydra-body-data) (function)
(get-universal-time)
hydra-body-atime (function)
(setf hydra-body-atime) (function)
hydra-body-heads (function)
(setf hydra-body-heads) (function)
hydra-body-gc-callbacks (function)
(setf hydra-body-gc-callbacks) (function)
hydra-body-garbage-collected-body-p (function)
(setf hydra-body-garbage-collected-body-p) (function)
intercom.lisp (file)
structure-object (structure)
touch (method)
hydra-head-id (function)
(setf hydra-head-id) (function)
(intercom::make-key-value-store)
hydra-head-data (function)
(setf hydra-head-data) (function)
(get-universal-time)
hydra-head-atime (function)
(setf hydra-head-atime) (function)
hydra-head-gc-callbacks (function)
(setf hydra-head-gc-callbacks) (function)
hydra-head-garbage-collected-body-p (function)
(setf hydra-head-garbage-collected-body-p) (function)
intercom.lisp (file)
structure-object (structure)
(bordeaux-threads:make-recursive-lock "key-value-lock")
key-value-store-lock (function)
(setf key-value-store-lock) (function)
(make-hash-table)
key-value-store-hash (function)
(setf key-value-store-hash) (function)
intercom.lisp (file)
structure-object (structure)
string
""
session-validation-hydra-id (function)
(setf session-validation-hydra-id) (function)
string
""
session-validation-host (function)
(setf session-validation-host) (function)
string
""
session-validation-user-agent (function)
(setf session-validation-user-agent) (function)
(or intercom::hydra-body null)
session-validation-hydra-body (function)
(setf session-validation-hydra-body) (function)
Previous: Definitions, Up: Top [Contents][Index]
• Concept index: | ||
• Function index: | ||
• Variable index: | ||
• Data type index: |
Next: Function index, Previous: Indexes, Up: Indexes [Contents][Index]
Jump to: | F I L |
---|
Jump to: | F I L |
---|
Next: Variable index, Previous: Concept index, Up: Indexes [Contents][Index]
Jump to: | (
A B C D E F G H I K M P R S T V W |
---|
Jump to: | (
A B C D E F G H I K M P R S T V W |
---|
Next: Data type index, Previous: Function index, Up: Indexes [Contents][Index]
Jump to: | *
A D G H I L S U |
---|
Jump to: | *
A D G H I L S U |
---|
Previous: Variable index, Up: Indexes [Contents][Index]
Jump to: | H I K P S |
---|
Jump to: | H I K P S |
---|