Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ataraxia-services

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ataraxia-services - npm Package Compare versions

Comparing version 0.4.4 to 0.5.0

194

index.js

@@ -19,2 +19,4 @@ 'use strict';

this.services = new Map();
this.version = 1;
this.nodes = new Map();

@@ -31,17 +33,45 @@ network.on('message', this._handleMessage.bind(this));

_handleNodeAvailable(node) {
/*
* When we connect to a new node, send the node all of the local
* services we provide.
*/
for(const service of this.services.values()) {
if(service instanceof LocalService) {
node.send('service:available', service.definition);
// Setup the node and initialize the version we have
const nodeData = {
node: node,
version: 0
};
this.nodes.set(node.id, nodeData);
// Request a list of services
node.send('service:list', { lastVersion: 0 });
// Schedule listing around every minute
function scheduleList() {
nodeData.listTimer = setTimeout(() => {
debug('Requesting list of services from', node);
node.send('service:list', { lastVersion: nodeData.version });
scheduleList();
}, 60000 + Math.random() * 5000);
}
scheduleList();
// Set a timer to fallback to broadcasting services
nodeData.broadcastTimer = setTimeout(() => {
nodeData.broadcastTimer = null;
for(const service of this.services.values()) {
if(service instanceof LocalService) {
node.send('service:available', service.definition);
}
}
}
}, 2000);
}
_handleNodeUnavailable(node) {
// Remove the node so we no longer query it
const nodeData = this.nodes.get(node.id);
clearTimeout(nodeData.listTimer);
clearTimeout(nodeData.broadcastTimer);
this.nodes.delete(node.id);
// Remove all the remote services of the node
for(const service of this.services.values()) {
if(service instanceof RemoteService && service.node.id === node.id) {
this._handleServiceUnavailable0(service);
this._handleServiceUnavailable0(node, service);
}

@@ -78,6 +108,12 @@ }

register(id, instance) {
// TODO: How should duplicate services be handled?
const service = new LocalService(this, id, instance);
this.services.set(id, service);
this.network.broadcast('service:available', service.definition);
// Update the version and broadcast this new service
this.version++;
const def = Object.assign({ servicesVersion: this.version }, service.definition);
this.network.broadcast('service:available', def);
this.events.emit('available', service.proxy);

@@ -98,4 +134,8 @@

this.services.delete(service.id);
this.network.broadcast('service:unavailable', service.definition);
// Update the version and broadcast that this service is no longer available
this.version++;
const def = Object.assign({ servicesVersion: this.version }, service.definition);
this.network.broadcast('service:unavailable', def);
this.events.emit('unavailable', service.proxy);

@@ -114,4 +154,17 @@ }

_serviceUpdated(service) {
// Update the version and broadcast the service
this.version++;
const def = Object.assign({ servicesVersion: this.version }, service.definition);
this.network.broadcast('service:available', def);
}
_handleMessage(msg) {
switch(msg.type) {
case 'service:list':
this._handleServiceList(msg.returnPath, msg.data);
break;
case 'service:list-result':
this._handleServiceListResult(msg.returnPath, msg.data);
break;
case 'service:available':

@@ -141,14 +194,115 @@ this._handleServiceAvailable(msg.returnPath, msg.data);

/**
* Handle an incoming request to list services.
*
* Will check if anything has changed since the requested version and if
* so sends back a complete list of services.
*/
_handleServiceList(node, data) {
// If the node has seen all of our services, skip reply
if(data.lastVersion === this.version) return;
// Mark that the other other node supports service listing, disable broadcast
const nodeData = this.nodes.get(node.id);
clearTimeout(nodeData.broadcastTimer);
nodeData.broadcastTimer = null;
// Collect the definitions for all of our local services
const services = [];
for(const service of this.services.values()) {
if(service instanceof LocalService) {
services.push(service.definition);
}
}
if(services.length > 0 || data.lastVersion === 0) {
// If we have any services send them back
node.send('service:list-result', {
servicesVersion: this.version,
services: services
});
}
}
/**
* Handle an incoming result from a `service:list` request.
*/
_handleServiceListResult(node, data) {
// Figure out which services belong to the node
const servicesNoLongerAvailable = new Set();
for(const service of this.services.values()) {
if(service instanceof RemoteService && service.node.id === node.id) {
servicesNoLongerAvailable.add(service.id);
}
}
// Handle the incoming list of services
for(const service of data.services) {
// Remove from list of services that are unavailable
servicesNoLongerAvailable.delete(service.id);
// Add or update the service
this._handleServiceAvailable0(node, service);
}
// Remove the remaining services
for(const id of servicesNoLongerAvailable) {
const service = this.services.get(id);
this._handleServiceUnavailable0(service);
}
// Update the version we have seen
const nodeData = this.nodes.get(node.id);
nodeData.version = data.servicesVersion;
}
/**
* Update the last version of a node or request a list of services if
* there is a gap.
*/
_updateNodeVersion(node, data) {
if(! data.servicesVersion) return;
// Check the version being tracked for the node
const nodeData = this.nodes.get(node.id);
if(nodeData.version === data.servicesVersion - 1) {
// The version we have is the previous one, perform a simple update
nodeData.version = data.servicesVersion;
} else {
// There is a gap in our data, request the list of services
node.send('service:list', { lastVersion: nodeData.version });
}
}
/**
* Handle that a new service is available or that it has been updated.
*/
_handleServiceAvailable(node, data) {
debug('Service', data.id, 'available via', node);
// Handle the incoming version information
this._updateNodeVersion(node, data);
// Actually handle the message
this._handleServiceAvailable0(node, data);
}
/**
* Create or update a remote service based on its definition.
*/
_handleServiceAvailable0(node, data) {
let service = this.services.get(data.id);
if(! service) {
// This is a new service, create it and start tracking it
service = new RemoteService(this, node, data);
this.services.set(data.id, service);
debug('Service', data.id, 'available via', node);
this.events.emit('available', service.proxy);
} else {
service.updateDefinition(data);
this.events.emit('available', service.proxy);
// This is an existing service, update the definition
debug('Service', data.id, 'updated via', node);
if(service.updateDefinition(data)) {
this.events.emit('updated', service.proxy);
}
}

@@ -160,2 +314,5 @@ }

// Handle the incoming version information
this._updateNodeVersion(node, data);
// Get the service and protect against unknown service

@@ -165,9 +322,12 @@ let service = this.services.get(data.id);

this._handleServiceUnavailable0(service);
this._handleServiceUnavailable0(node, service);
}
_handleServiceUnavailable0(service) {
debug(service.id, 'is no longer available');
_handleServiceUnavailable0(node, service) {
debug('Service', service.id, 'is no longer available via', node);
this.services.delete(service.id);
this.events.emit('unavailable', service.proxy);
// Destroy the service object
service.destroy();
}

@@ -174,0 +334,0 @@

{
"name": "ataraxia-services",
"version": "0.4.4",
"lockfileVersion": 1,
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"ataraxia": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/ataraxia/-/ataraxia-0.4.4.tgz",
"integrity": "sha1-Zrfocc/YElWUxgB/ls0JrOA/W1Y=",
"requires": {
"debug": "3.1.0",
"deep-equal": "1.0.1",
"end-of-stream": "1.4.0",
"msgpack-lite": "0.1.26"
}
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
"requires": {

@@ -13,2 +26,20 @@ "ms": "2.0.0"

},
"deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
},
"end-of-stream": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz",
"integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=",
"requires": {
"once": "1.4.0"
}
},
"event-lite": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/event-lite/-/event-lite-0.1.1.tgz",
"integrity": "sha1-R88IqNN9C2lM23s7F7UfqsZXYIY="
},
"eventemitter2": {

@@ -19,2 +50,17 @@ "version": "4.1.2",

},
"ieee754": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
"integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q="
},
"int64-buffer": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/int64-buffer/-/int64-buffer-0.1.10.tgz",
"integrity": "sha1-J3siiofZWtd30HwTgyAiQGpHNCM="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"ms": {

@@ -24,4 +70,28 @@ "version": "2.0.0",

"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"msgpack-lite": {
"version": "0.1.26",
"resolved": "https://registry.npmjs.org/msgpack-lite/-/msgpack-lite-0.1.26.tgz",
"integrity": "sha1-3TxQsm8FnyXn7e42REGDWOKprYk=",
"requires": {
"event-lite": "0.1.1",
"ieee754": "1.1.8",
"int64-buffer": "0.1.10",
"isarray": "1.0.0"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1.0.2"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}
}
}

5

package.json
{
"name": "ataraxia-services",
"version": "0.4.4",
"version": "0.5.0",
"description": "Services with RPC and events over Ataraxia mesh network",

@@ -9,6 +9,7 @@ "main": "index.js",

"dependencies": {
"ataraxia": "^0.4.4",
"ataraxia": "^0.5.0",
"debug": "^3.1.0",
"deep-equal": "^1.0.1",
"eventemitter2": "^4.1.2"
}
}

@@ -45,2 +45,40 @@ # ataraxia-services

## Creat
## Creating services
Services are simple objects:
```javascript
services.register('service-id', {
hello(what='world') {
return 'Hello ' + what;
},
property: 1234
});
```
The only special part of services is that the `metadata` property is
automatically distributed througout the network.
```javascript
services.register('service-with-metadata', {
metadata: {
type: 'cookie-factory'
},
cookiesMade: 0,
makeCookie() {
return ++this.cookiesMade;
}
});
```
The metadata can be access on any node:
```javascript
const service = services.get('service-with-metadata');
if(service) {
console.log(service.metadata.type);
}
```

@@ -73,3 +73,3 @@ 'use strict';

[metadataChanged]() {
this.parent.network.broadcast('service:available', this.definition);
this.parent._serviceUpdated(this);
}

@@ -76,0 +76,0 @@

'use strict';
const Service = require('./service');
const deepEqual = require('deep-equal');
const customInspect = require('util').inspect.custom;

@@ -27,3 +28,8 @@

updateDefinition(def) {
this.metadata = def.metadata;
if(! deepEqual(this.metadata, def.metadata)) {
this.metadata = def.metadata;
return true;
}
return false;
}

@@ -126,3 +132,3 @@

remove() {
destroy() {
for(const promise of this.promises.values()) {

@@ -129,0 +135,0 @@ promise.reject(new Error('Service is no longer available'));

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc