Giter Club home page Giter Club logo

tart-ansible's Introduction

tart-ansible

Stability: 1 - Experimental

NPM version

Ansible enables remote message delivery for Tart actors.

Contributors

@dalnefre, @tristanls

Overview

Ansible enables remote message delivery for Tart actors.

Ansible Scheme

URIs used by Ansible are represented in absolute form. The "ansible" scheme is used to locate capabilities via the Ansible protocol. The scheme-specific syntax and semantics of ansible URIs are as follows:

ansible_URI = "ansible:" "//" authority "/#" capability

Example:

ansible://YLKV/ZUYvGnggOTxgDL2jqUWfX0tFa8PRI+ZKw9HUE9gSTG2r5Oi1yZ2/#i3VGpoJPmf7pHxINs6At5IfItEKGgxBV09g2eEcqsaJWTapd26t5J9IO

The semantics are such that the identified authority is the domain containing the specified capability.

When comparing two URIs to decide whether they match or not, comparison must be case-sensitive octet-by-octet comparison with the exception of the scheme, which must be case-insensitive.

Usage

To run the below example run:

npm run readme

To exit ^C.

"use strict";

var ansible = require('../index.js');
var crypto = require('crypto');
var Discover = require('discover');
var DiscoverTcpTransport = require('discover-tcp-transport');
var httpTransport = require('tart-transport-http');
var tart = require('tart');
var udpTransport = require('tart-transport-udp');

var sponsor = tart.minimal();

// This example will demonstrate "magically deliver any message to anywhere". 
// This sort of power takes some setup. The setup is straighforward, but there 
// is quite a bit of it. A lot of redundancy here is due to running multiple
// servers locally to demonstrate the functionality, all from one script. So,
// please, be patient :)

// create discover TCP transports

var discoverTcpTransport1 = new DiscoverTcpTransport({port: 6741});
var discoverTcpTransport2 = new DiscoverTcpTransport({port: 6742});
var discoverTcpTransport3 = new DiscoverTcpTransport({port: 6743});
var discoverTcpTransport4 = new DiscoverTcpTransport({port: 6744});
var discoverTcpTransport5 = new DiscoverTcpTransport({port: 6745});

// create discover-only initial seed domain names
// for internal discover mechanisms, only domain names are needed

var discoverDomain1 = crypto.randomBytes(42).toString('base64');
var discoverDomain2 = crypto.randomBytes(42).toString('base64');
var discoverDomain3 = crypto.randomBytes(42).toString('base64');
var discoverDomain4 = crypto.randomBytes(42).toString('base64');
var discoverDomain5 = crypto.randomBytes(42).toString('base64');

// create discover node contacts

var discoverNode1 = {id: discoverDomain1, transport: {host: 'localhost', port: 6741}};
var discoverNode2 = {id: discoverDomain2, transport: {host: 'localhost', port: 6742}};
var discoverNode3 = {id: discoverDomain3, transport: {host: 'localhost', port: 6743}};
var discoverNode4 = {id: discoverDomain4, transport: {host: 'localhost', port: 6744}};
var discoverNode5 = {id: discoverDomain5, transport: {host: 'localhost', port: 6745}};

// assign seed nodes

var seeds = [discoverNode1, discoverNode2, discoverNode3];

// create discover instances

var discover1 = new Discover({inlineTrace: false, seeds: seeds, transport: discoverTcpTransport1});
var discover2 = new Discover({inlineTrace: false, seeds: seeds, transport: discoverTcpTransport2});
var discover3 = new Discover({inlineTrace: false, seeds: seeds, transport: discoverTcpTransport3});
var discover4 = new Discover({inlineTrace: false, seeds: seeds, transport: discoverTcpTransport4});
var discover5 = new Discover({inlineTrace: false, seeds: seeds, transport: discoverTcpTransport5});

// turn on discover TCP transports

var turnOn = function (transport, next) {
    return function () {
        transport.listen(next);
    };
};

console.log('turning on Discover TCP transports');

turnOn(discoverTcpTransport1,
    turnOn(discoverTcpTransport2,
        turnOn(discoverTcpTransport3,
            turnOn(discoverTcpTransport4,
                turnOn(discoverTcpTransport5,
                    function () {

console.log('Discover TCP transports are ON');

// bootstrap discover instances with self awareness

discover1.register(discoverNode1);
discover2.register(discoverNode2);
discover3.register(discoverNode3);
discover4.register(discoverNode4);
discover5.register(discoverNode5);

// create ansible node capabilities

var ansibleCaps1 = ansible.capabilities(discover1);
var ansibleCaps2 = ansible.capabilities(discover2);
var ansibleCaps3 = ansible.capabilities(discover3);
var ansibleCaps4 = ansible.capabilities(discover4);
var ansibleCaps5 = ansible.capabilities(discover5);

// create ansible send actors

var ansibleSend1 = sponsor(ansibleCaps1.sendBeh);
var ansibleSend2 = sponsor(ansibleCaps2.sendBeh);
var ansibleSend3 = sponsor(ansibleCaps3.sendBeh);
var ansibleSend4 = sponsor(ansibleCaps4.sendBeh);
var ansibleSend5 = sponsor(ansibleCaps5.sendBeh);

// register Tart transports

var httpSend1 = sponsor(httpTransport.sendBeh);
var httpSend2 = sponsor(httpTransport.sendBeh);
var httpSend3 = sponsor(httpTransport.sendBeh);
var httpSend4 = sponsor(httpTransport.sendBeh);
var httpSend5 = sponsor(httpTransport.sendBeh);

var udpSend1 = sponsor(udpTransport.sendBeh);
var udpSend2 = sponsor(udpTransport.sendBeh);
var udpSend3 = sponsor(udpTransport.sendBeh);
var udpSend4 = sponsor(udpTransport.sendBeh);
var udpSend5 = sponsor(udpTransport.sendBeh);

ansibleCaps1.registerTransport({
    scheme: 'http', 
    send: httpSend1,
    data: 'http://localhost:8081'
});
ansibleCaps2.registerTransport({
    scheme: 'http', 
    send: httpSend2,
    data: 'http://localhost:8082'
});
ansibleCaps3.registerTransport({
    scheme: 'http', 
    send: httpSend3,
    data: 'http://localhost:8083'
});
ansibleCaps4.registerTransport({
    scheme: 'http', 
    send: httpSend4,
    data: 'http://localhost:8084'
});
ansibleCaps5.registerTransport({
    scheme: 'http', 
    send: httpSend5,
    data: 'http://localhost:8085'
});

ansibleCaps1.registerTransport({
    scheme: 'udp', 
    send: udpSend1,
    data: 'udp://localhost:9081'
});
ansibleCaps2.registerTransport({
    scheme: 'udp', 
    send: udpSend2,
    data: 'udp://localhost:9082'
});
ansibleCaps3.registerTransport({
    scheme: 'udp', 
    send: udpSend3,
    data: 'udp://localhost:9083'
});
ansibleCaps4.registerTransport({
    scheme: 'udp', 
    send: udpSend4,
    data: 'udp://localhost:9084'
});
ansibleCaps5.registerTransport({
    scheme: 'udp', 
    send: udpSend5,
    data: 'udp://localhost:9085'
});

// create HTTP transports and direct them to the ansible receptionists

var ansibleReceptionist1 = sponsor(ansibleCaps1.receptionistBeh);
var ansibleReceptionist2 = sponsor(ansibleCaps2.receptionistBeh);
var ansibleReceptionist3 = sponsor(ansibleCaps3.receptionistBeh);
var ansibleReceptionist4 = sponsor(ansibleCaps4.receptionistBeh);
var ansibleReceptionist5 = sponsor(ansibleCaps5.receptionistBeh);

var httpCaps1 = httpTransport.server(ansibleReceptionist1);
var httpCaps2 = httpTransport.server(ansibleReceptionist2);
var httpCaps3 = httpTransport.server(ansibleReceptionist3);
var httpCaps4 = httpTransport.server(ansibleReceptionist4);
var httpCaps5 = httpTransport.server(ansibleReceptionist5);

var udpCaps1 = udpTransport.server(ansibleReceptionist1);
var udpCaps2 = udpTransport.server(ansibleReceptionist2);
var udpCaps3 = udpTransport.server(ansibleReceptionist3);
var udpCaps4 = udpTransport.server(ansibleReceptionist4);
var udpCaps5 = udpTransport.server(ansibleReceptionist5);

var listenHttp1 = sponsor(httpCaps1.listenBeh);
var listenHttp2 = sponsor(httpCaps2.listenBeh);
var listenHttp3 = sponsor(httpCaps3.listenBeh);
var listenHttp4 = sponsor(httpCaps4.listenBeh);
var listenHttp5 = sponsor(httpCaps5.listenBeh);

var listenUdp1 = sponsor(udpCaps1.listenBeh);
var listenUdp2 = sponsor(udpCaps2.listenBeh);
var listenUdp3 = sponsor(udpCaps3.listenBeh);
var listenUdp4 = sponsor(udpCaps4.listenBeh);
var listenUdp5 = sponsor(udpCaps5.listenBeh);

var turnOnTransport = function (listen, port, next) {
    return function () {
        listen({host: 'localhost', port: port, ok: next});
    }
};

console.log('turning on Tart transports');

turnOnTransport(listenHttp1, 8081,
    turnOnTransport(listenHttp2, 8082,
        turnOnTransport(listenHttp3, 8083, 
            turnOnTransport(listenHttp4, 8084, 
                turnOnTransport(listenHttp5, 8085,
                    turnOnTransport(listenUdp1, 9081,
                        turnOnTransport(listenUdp2, 9082,
                            turnOnTransport(listenUdp3, 9083,
                                turnOnTransport(listenUdp4, 9084,
                                    turnOnTransport(listenUdp5, 9085,
                                        function () {

console.log('Tart transports are ON');
console.log('');

// create domains (only need ids again)

var domainName1 = crypto.randomBytes(42).toString('base64');
var domainName2 = crypto.randomBytes(42).toString('base64');
var domainName3 = crypto.randomBytes(42).toString('base64');
var domainName4 = crypto.randomBytes(42).toString('base64');
var domainName5 = crypto.randomBytes(42).toString('base64');

// create domain receptionists

var domainReceptionist1 = sponsor(function (message) {
    console.log('[domain 1====] received message:');
    console.log(message);
    console.log('');
});
var domainReceptionist2 = sponsor(function (message) {
    console.log('[domain =2===] received message:');
    console.log(message);
    console.log('');
});
var domainReceptionist3 = sponsor(function (message) {
    console.log('[domain ==3==] received message:');
    console.log(message);
    console.log('');
});
var domainReceptionist4 = sponsor(function (message) {
    console.log('[domain ===4=] received message:');
    console.log(message);
    console.log('');
});
var domainReceptionist5 = sponsor(function (message) {
    console.log('[domain ====5] received message:');
    console.log(message);
    console.log('');
});

// register domains with ansible

ansibleCaps1.registerDomain(domainName1, domainReceptionist1);
ansibleCaps2.registerDomain(domainName2, domainReceptionist2);
ansibleCaps3.registerDomain(domainName3, domainReceptionist3);
ansibleCaps4.registerDomain(domainName4, domainReceptionist4);
ansibleCaps5.registerDomain(domainName5, domainReceptionist5);

// randomly issue ansible protocol sends locally to each ansible
var ansibleSends = [
    {send: ansibleSend1, ansible: '[ansible 1====]'}, 
    {send: ansibleSend2, ansible: '[ansible =2===]'}, 
    {send: ansibleSend3, ansible: '[ansible ==3==]'},
    {send: ansibleSend4, ansible: '[ansible ===4=]'},
    {send: ansibleSend5, ansible: '[ansible ====5]'}
];
var domains = [
    {log: '[domain 1====]', domain: domainName1},
    {log: '[domain =2===]', domain: domainName2},
    {log: '[domain ==3==]', domain: domainName3},
    {log: '[domain ===4=]', domain: domainName4},
    {log: '[domain ====5]', domain: domainName5}
];

var doRandomSend = function doRandomSend () {
    var origin = ansibleSends[Math.floor(Math.random() * ansibleSends.length)];
    var destDomain = domains[Math.floor(Math.random() * domains.length)];

    console.log(origin.ansible, 'sending: "foo" to', destDomain.log);

    origin.send({
        address: 'ansible://' + destDomain.domain + '/#' + crypto.randomBytes(42).toString('base64'),
        content: JSON.stringify("foo"),
        fail: function (error) { console.dir(error); }
    });

    setTimeout(doRandomSend, Math.floor(Math.random() * 5000));
};

doRandomSend();

}))))))))))(); // turnOnTransport

})))))(); // turnOn

Tests

TODO

Documentation

Public API

ansible.capabilities(discover)

TODO

ansibleCapabilities.receptionistBeh

TODO

ansibleCapabilities.registerDomain(domainName, receptionist)

TODO

ansibleCapabilities.registerTransport(transportInfo)

TODO

ansibleCapabilities.sendBeh

TODO

ansibleCapabilities.unregisterDomain(domainName)

TODO

Sources

tart-ansible's People

Contributors

tristanls avatar

Stargazers

Vitaly Zadorozhny avatar Allain Lalonde avatar

Watchers

 avatar James Cloos avatar Dale Schumacher avatar

Forkers

vitaly-z

tart-ansible's Issues

optimistic DHT population

In case where there is a message that expects a reply (for example, a browser accesses a capability which should return a webpage), it may be useful to have some sort of mechanism that optimistically provides DHT contact information as part of the client-request message.

The difficulty is that if a client is to receive a reply, the client must register its domain with Ansible. This may take time to propagate. Thus, even though the client request could reach the server responsible for handling the request, when a reply is sent, the client's domain (which was "just" created) will most likely not propagate across the DHT yet. If there is DHT contact information piggy backing on the Ansible message, then the server handling the request knows exactly where to route it back. (and if such DHT contact information is not provided, as is usually(?) the case, then proceed as normal).

The intent of this mechanism is not to bypass Ansible and its decentralized manner, but instead facilitate propagation of certain information across some time sensitive routes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.