You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Mattia Belletti cacbf6a50e Full test pass. 3 months ago
.vscode Chained calls. 4 months ago
implementation-docs Initial import. 4 months ago
src Full test pass. 3 months ago
testdata Full testing of TCP/SSL connection. 3 months ago
.gitignore More testing work. 4 months ago
README.md Initial import. 4 months ago
package.json Full testing of TCP/SSL connection. 3 months ago
tsconfig.json Mini test suite. 4 months ago
yarn.lock Base code for chaining. 4 months ago

README.md

Theater and Actors

Theater is a simple JavaScript-based distributed system for seemless, secure interaction and (optional) persistence between entities knows as actors. It is heavily inspired by projects like the E language and its successors.

Actors

An actor is the sum of:

  • an internal private state
  • a list of actions, implementing behaviours completely defined by the parameters passed (possibly including other actors, also remote) and the internal state, and optionally returning one of more values (possibly including other actors, also remote).

Actors are the building block of the system. Under an object-oriented perspective, they are object instances without any specific class associated (we can think that each object is the sole instance of their own class). Under a functional perspective, actors implement a Reader + Writer monad, or, expressed in another way, a function (state: PrivateState, methodName: string, ...params) => [returnValue, newState: PrivateState].

Seemless interaction

Interaction with actors is the same when performed on local objects and on remote objects. Because of this, all actor's actions return value is a chainable promise (more on that later, but right now we can think of it as a standard promise).

This means that the implementation of an actor's action could be something like:

{
  ...
  add: (a, b) => { return a + b; }
  ...
}

But when an actor based upon such definition is called, what it will return is a promise:

a.add(3, 6).then(result =>
  console.log("The sum of 3 and 6 is", result)
);

This forces us to think about promises in terms of asynchronous interaction, so that the programs we write don't care if the actors are local or remote. The code can be highly simplified back to a standard flow of control if we take advantage of JavaScript's async and await constructs:

const name1 = await a.getName();
const name2 = await b.getName();
console.log(`a's name is ${name1}, and b's name is ${name2}.`);

Care must be taken because this approach can be inefficient: for example, in the above situation, if a is a remote object, then b‘s getName is not called until a‘s getName returns. Because of this, Promise‘s helper methods can be used:

const [name1, name2] = Promise.all([
  a.getName(),
  b.getName()
]);
console.log(`a's name is ${name1}, and b's name is ${name2}.`);

More advanced techniques that can help clean up the code are given in the Chainable Promises section.

Secure interactions

Actors support so-called object capabilities, whose idea is to extend the usage of the object scoping in the language, which allows objects inside the language to show or hide the data and methods they want to other objects by passing or not passing references, and export it on the wire, passing references of objects to allow other systems to access data through well-defined interfaces.

Secure interactions are defined between VATs. A VAT is a system containing objects that can talk to each other through direct reference in the language. Different VATs are connected through any protocol that makes middle men's attacks impossible: whether is SSL over TCP or HTTPS or any other form of cryptographic connection, is not important.

Once this is possible, the object capabitilies system makes it possible for each VAT to expose only the actor's behaviour which each one is interested in.

Chainable Promises

Sometimes, one needs to call methods in a chain. E.g., if we have a local object:

a.getPlayer(2).getScore().addOne();

If the player and the score objects were both actors, calling this method chain would amount to:

const player = await a.getPlayer(2);
const score = await player.getScore();
await score.addOne();

This would require three round trips between the local system and the remote one. But the three calls can actually be chained one to the other like this:

await a.getPlayer(2).getScore().addOne()

Here we can see that both a.getPlayer(2) and .getScore() not only return a promise, but a special kind of promise which supports extra methods: the ones of the actor which will eventually be returned. These are called chainable promises.

Chainable promises allow us to pack together multiple chained calls, in order to perform them in order avoiding useless round trips, and once again return promises.