cl-mtgnet

2018-07-11

Client library for the MTGNet RPC protocol.

Upstream URL

github.com/mtstickney/cl-mtgnet

Author

Matthew Stickney <mtstickney@gmail.com>

License

MIT
README

1About

CL-MTGNET is a client library for the MTGNet RPC protocol. The libraryhandles all the details of marshalling and unmarshalling, includingmatching out-of-order responses to the appropriate request.

2Dependencies

This library depends on the CL-NETSTRING+ library, as well as thequicklisp-installable CL-JSON and TRIVIAL-UTF-8 libs.

3API

Remote methods are treated like FFI calls: the client createsdefinitions for the methods it wishes to use, and can then callthose methods as if they were local functions.

3.1Method Definition

Most clients will want to use the high-level macros to definemethod functions that handle the details of calling. The methoddefinition macro is relatively simple:
  (defmacro define-rpc-method ((method &optional service  &key notification) &body args))

method and service are symbols naming the method and the service method belongs to. define-rpc-method will create a function named <method>, which takes a socket stream, a symbol naming the service, and the arguments of the method. If service is provided, the function will be named <service>-<method> and will not take a service symbol as a parameter. Note that both method and service symbols will be processed by CL-JSON, so the standard name-mangling applies (e.g. describe-method will become describeMethod when sent to the server).

If notification is not supplied or is nil, the function will return a future object that will return the value of the method (or signal an error) when wait is called on it. If notification is not nil, the function will return immediately with no value (since no response is expected from the server).

3.1.1Examples

  ;; Define a method without specifying a service
  (define-rpc-method
     ;; Method name
     (describe-method)
     ;; Method arguments
     method-name)
  
  ;; Invoke the method on the 'server' service
  ;; (wait (describe-method sock 'server "version")) => [...]
  
  ;; Define a method on a specific service
  (define-rpc-method (describe-method server) method-name)
  
  ;; (wait (server-describe-method "version")) => [...]
  
  ;; Define a notification method
  (define-rpc-method (poke server :notification t) msg)
  
  ;; Note the lack of a WAIT call here
  ;; (server-poke "Poked for no reason!") => No value

3.2Batched Calls

The MTGNet protocol features the ability to send requests to theserver in a batch, with the guarantee that the server will hold theresponses for those calls until they're all ready before returningthem. Clients can submit a batch of calls using thewith-batch-calls macro:
  ;; With STREAM, DESCRIBE-METHOD and VERSION defined elsewhere...
  (let (describe-future
        version-future)
    (with-batch-calls
        (setf describe-future (server-describe-method sock "version")
              version-future (server-version sock)))
    (values (wait description-future)
            ;; This will return immediately
            (wait version-future)))

Any method calls made within a with-batch-calls macro won't be submitted to the server until the end of the block. Note: since none of the calls in a with-batch-calls block will be submitted until the block is left, calling wait on one of the returned futures will deadlock.

3.3Futures

The non-notification functions created with define-rpc-methodreturn a future object that will hold the return value of themethod or signal an error if there was one. wait can be used toretrieve a completion value or signal an error: it takes a futureobject, and returns when that future completes.

Right now the underlying IO mechanism isn't really asynchronous. wait drives the IO processing, so if a lot of requests are made and wait is never called, the socket buffer could fill and cause the server to block. This shouldn't be an issue under most workloads, however.

4Future TODOs

  • Use an asynch IO mechanism to avoid the need to call wait.
  • Add timeouts and keepalive options for rpc methods.
  • Accept strings as well as symbols for method and service names.
  • Use typespec values from the server to do typechecking wherepossible.
    • This could be a performance issue, so this may need to be adisable-able feature.
  • Allow clients to specify non-mangled names?
  • Document signaled conditions once they're all in place.
  • Give the client some control over the encoding of arguments passedto methods.
    • Either allow client to supply pre-encoded values (potentialbadness here), or supply encoder functions.

Dependencies (6)

  • blackbird
  • cl-async
  • cl-json
  • cl-netstring-plus
  • trivial-utf-8
  • usocket

Dependents (0)

    • GitHub
    • Quicklisp