
Eider Documentation Release 1.0.0 Bart Robinson Oct 09, 2019 Contents 1 Installation 3 1.1 Python..................................................3 1.2 JavaScript.................................................3 1.3 C++....................................................4 2 Getting Started 5 2.1 Python..................................................5 2.2 JavaScript.................................................6 2.3 C++....................................................7 3 Contents 9 3.1 Justification................................................9 3.2 Concepts................................................. 10 3.3 Protocol.................................................. 13 3.4 Conventions............................................... 18 4 Blame 23 Index 25 i ii Eider Documentation, Release 1.0.0 Eider is an object-oriented, asynchronous, late-binding, web-first, polyglot RPC protocol. Eider is also the name of the reference implementations in Python and JavaScript. Out of the box, Eider uses WebSockets for transport and JSON or MessagePack for serialization. The core protocol and concepts are transport- and format-neutral. With Eider, developing applications that combine server-side, client-side, and in-browser code is duck soup! Contents 1 Eider Documentation, Release 1.0.0 2 Contents CHAPTER 1 Installation 1.1 Python Works in CPython 3.4+ and PyPy3. Requires either aiohttp or websockets. Includes elective support for MessagePack using msgpack-python, if available. pip install eider # either: pip install aiohttp # recommended pip install websockets # slower # optional: pip install msgpack You can also check out the source code on GitHub. 1.2 JavaScript Works in Node.js 6+, modern browsers, and any other environment that supports ES6. For clients, no external libraries are strictly required. Node.js servers need the ws package. Other optional dependen- cies are msgpack-lite for MessagePack encoding and weak for implicit remote garbage collection. npm install eider-rpc # for servers: npm install ws # optional: npm install msgpack-lite npm install weak 3 Eider Documentation, Release 1.0.0 For the browser: eider-rpc.min.js. You can also check out the source code on GitHub. 1.3 C++ The eider-pybind11 project provides a simple header file that can enable classes implemented in C++ to be served over Eider connections using pybind11. 4 Chapter 1. Installation CHAPTER 2 Getting Started 2.1 Python Here is a simple server (simple_server.py): 1 import eider 2 3 class DuckTester(eider.LocalRoot): 4 5 def is_it_a_duck(self, obj): 6 return ( 7 obj['looks'] =='like a duck' and 8 obj['swims'] =='like a duck' and 9 obj['quacks'] =='like a duck') 10 11 eider.serve(12345, root=DuckTester) And here is a corresponding client (simple_client.py): 1 import eider 2 3 how='like a duck' 4 obj={'looks': how,'swims': how,'quacks': how} 5 6 with eider.BlockingConnection('ws://localhost:12345') as conn: 7 with conn.create_session() as duck_tester: 8 is_duck= duck_tester.is_it_a_duck(obj) 9 print("It's probably"+("" if is_duck else "NOT")+"a duck.") And here is an equivalent client using non-blocking APIs: (simple_client_async.py): 1 import asyncio, eider 2 3 how='like a duck' (continues on next page) 5 Eider Documentation, Release 1.0.0 (continued from previous page) 4 obj={'looks': how,'swims': how,'quacks': how} 5 6 async def ducktest(): 7 async with eider.Connection('ws://localhost:12345') as conn: 8 async with conn.create_session() as duck_tester: 9 is_duck= await duck_tester.is_it_a_duck(obj) 10 print("It's probably"+("" if is_duck else "NOT")+"a duck.") 11 12 asyncio.run(ducktest()) 2.2 JavaScript Here is an equivalent server in JavaScript (simple_server.js): 1 const Eider= require('eider-rpc'); 2 3 class DuckTester extends Eider.LocalRoot { 4 is_it_a_duck(obj) { 5 return obj.looks === 'like a duck'&& 6 obj.swims === 'like a duck'&& 7 obj.quacks === 'like a duck'; 8 } 9 } 10 11 Eider.serve(12345, {root: DuckTester}); And here is an equivalent client (simple_client.html): 1 <script src="eider-rpc.min.js"></script> 2 <script type="text/javascript"> 3 const how= 'like a duck'; 4 const obj= {looks: how, swims: how, quacks: how}; 5 Eider.using(Eider.connect('ws://localhost:12345'), conn => 6 Eider.using(conn.createSession(), duckTester => 7 duckTester.is_it_a_duck(obj).then(isDuck => { 8 alert("It's probably "+ (isDuck?'': 'NOT ')+ 'a duck.'); 9 }) 10 ) 11 ); 12 </script> And here is an equivalent client using async/await syntax (simple_client_async.html): 1 <script src="eider-rpc.min.js"></script> 2 <script type="text/javascript"> 3 const how= 'like a duck'; 4 const obj= {looks: how, swims: how, quacks: how}; 5 (async () => 6 await Eider.using(Eider.connect('ws://localhost:12345'), async conn => 7 await Eider.using(conn.createSession(), async duckTester => { 8 const isDuck= await duckTester.is_it_a_duck(obj); 9 alert("It's probably "+ (isDuck?'': 'NOT ')+ 'a duck.'); 10 }) 11 ) (continues on next page) 6 Chapter 2. Getting Started Eider Documentation, Release 1.0.0 (continued from previous page) 12 )(); 13 </script> 2.3 C++ Here is how the core of the Python server could be written in C++ (simple_server.cpp): 1 #include <eider_pybind11.hpp> 2 3 using namespace eider_pybind11; 4 5 struct DuckTester : LocalRoot { 6 using LocalRoot::LocalRoot; 7 8 bool is_it_a_duck(py::object obj) { 9 return std::string(py::str(obj["looks"]))=="like a duck"&& 10 std::string(py::str(obj["swims"]))=="like a duck"&& 11 std::string(py::str(obj["quacks"]))=="like a duck"; 12 } 13 }; 14 15 PYBIND11_MODULE(ducktest, m) { 16 bind(m); 17 18 py::class_<DuckTester, LocalRoot>(m,"DuckTester") 19 .def(py::init<LocalSession>()) 20 .def("is_it_a_duck",&DuckTester::is_it_a_duck); 21 } 2.3. C++ 7 Eider Documentation, Release 1.0.0 8 Chapter 2. Getting Started CHAPTER 3 Contents 3.1 Justification (a.k.a. Yet another RPC protocol?) There are many Remote Procedure Call mechanisms out there. Some of them are very nice. Eider was developed because, as far as the author could tell, no single one of them meets all five of these criteria: • Object-oriented. Many RPC protocols only allow you to call a flat list of exposed functions. Eider lets you work with remote objects and their exposed methods. • Asynchronous. Many RPC protocols require that responses be returned in the same order as requests were sent. Eider allows responses to be returned in any order, using asynchronous fulfillment mechanisms such as Promises (in JavaScript) and Futures (in Python). • Late-binding. Many RPC protocols require invokable function signatures to be declared ahead of time in some special way. Eider has no such requirement; instead it follows the Python tradition of duck typing (if it looks like a duck, swims like a duck, and quacks like a duck. it’s probably a duck). There is no interface description language; exposed objects and methods are coded using the natural syntax of their native language. Type mismatches are reported via exceptions at runtime.1 • Web-first. Many RPC protocols use direct TCP or pipe connections and rely on custom binary formats or overly-verbose XML, all of which make them difficult-to-impossible to use from JavaScript running inside the browser. Eider uses web standards like WebSockets and JSON, so client-side web apps can be first-class participants in an Eider-based system. • Polyglot. Many RPC protocols are tied to a single programming language. Eider is language-agnostic. Eider also has these nice features: • Lightweight. The Python and JavaScript implementations are just a few kilobytes each and have minimal external dependencies. Transmitted messages are nearly as compact as in JSON-RPC. 1 It is important not to confuse late binding with weak typing. Eider methods are precisely as strongly typed as the language used to implement them. To assist with coding discipline, Eider has built-in support for function annotation, interactive help, and runtime object inspection. 9 Eider Documentation, Release 1.0.0 • Natural syntax. Syntactic sugar is used to make calling remote methods and accessing remote properties as natural as possible. The Python implementation also provides blocking versions of client functions, so simple clients can avoid the complexity of Futures and callbacks. • Peer-to-peer. After the initial connection, there is no functional difference between client and server applica- tions. Each peer can be both a provider and consumer of remote interfaces. Callbacks are even supported, where a locally-provided object or method is passed to a remote interface. • Built-in proxying. Any Eider peer can act as a bridge between any two of its peers, allowing them to call each other’s methods without connecting directly. • Cancellation. Eider consumers can request the graceful cancellation of long-running remote method calls without terminating the connection or losing session state. 3.2 Concepts Note: For simplicity, in this document we will prefer the Python blocking (synchronous) API. The asynchronous JavaScript and Python APIs are very similar. 3.2.1 Outline Typical Eider communication follows this basic pattern: 1. Establish a connection. 2. Create a remote session to contain object references. 3. Call a method on the root object of the session. 4. Call any other desired methods on the root object or on returned objects. 5. Close session(s) to reclaim memory. 6. Repeat 2-5 as desired. 7. (concurrently with 2-6) Execute any incoming method calls requested by the connection peer. 8. Close the connection. Steps 2-7 are entirely optional; remember, every Eider peer can be a
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages29 Page
-
File Size-