Skip to content

Commit

Permalink
feat(Transponder): utils adds Transponder for handling promises
Browse files Browse the repository at this point in the history
affects: @tao.js/utils

Transponders are a cleaner way to implement promises from the Network

additionally Source is more flexible and cleaner
Channel has a clone method
@tao.js/socket.io updated w change to Source

BREAKING CHANGE:
Source's ctor changed the order of the params, making fromSrc optional
  • Loading branch information
eudaimos committed Aug 11, 2019
1 parent e3e562a commit 311f738
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 4 deletions.
2 changes: 1 addition & 1 deletion packages/tao-socket-io/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function decorateNetwork(TAO, socket) {
const fromHandler = handler =>
socket.on(EVENTS[ON_EVENT], ({ tao, data }) => handler(tao, data));
const toEmit = (tao, data) => socket.emit(EVENTS[EMIT_EVENT], { tao, data });
const source = new Source(TAO, fromHandler, toEmit);
const source = new Source(TAO, toEmit, fromHandler);
return source;
}

Expand Down
6 changes: 6 additions & 0 deletions packages/tao-utils/src/Channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ export default class Channel {
this._network = kernel._network;
}

clone(cloneId) {
const clone = new Channel({ _network: this._network }, cloneId);
clone._channel = this._channel;
return clone;
}

setCtx({ t, term, a, action, o, orient }, data) {
this._network.setCtxControl(
{ t, term, a, action, o, orient },
Expand Down
30 changes: 28 additions & 2 deletions packages/tao-utils/src/Source.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,30 @@ function sourceControl(source) {
}

export default class Source {
constructor(kernel, fromSrc, toSrc, name) {
constructor(kernel, toSrc, name, fromSrc) {
this._network = kernel._network;
this.forwardAppCtx = kernel.forwardAppCtx;
if (!kernel || !kernel._network) {
throw new Error(
'must provide `kernel` to attach the Source to a network'
);
}
if (!toSrc) {
throw new Error('must provide `toSrc` way to send ACs to the source');
}
if (typeof name === 'function') {
fromSrc = name;
name = null;
}
// Make fromSrc optional for binding a handler
// if not passed it is a function exposed by the Source i.e. setCtx
fromSrc((tao, data) =>
this._network.setCtxControl(
tao,
data,
sourceControl(this.name),
(ac, control) => kernel.forwardAppCtx(ac, control)
// (ac, control) => kernel.forwardAppCtx(ac, control)
this.forwardAppCtx
)
);
this._toSrc = toSrc;
Expand All @@ -37,6 +53,16 @@ export default class Source {
}
}

setCtx = ({ t, term, a, action, o, orient }, data) => {
this._network.setCtxControl(
{ t, term, a, action, o, orient },
data,
sourceControl(this.name),
// (ac, control) => kernel.forwardAppCtx(ac, control)
this.forwardAppCtx
);
};

dispose() {
this._network.stop(this._middleware);
}
Expand Down
156 changes: 156 additions & 0 deletions packages/tao-utils/src/Transponder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import { Network } from '@tao.js/core';

let transponderId = 0;
function newTransponderId() {
return ++transponderId;
}

function transponderControl(transponderId, signal) {
return { transponderId, signal };
}

export default class Transponder {
// constructor(kernel, id, first = true, timeoutMs = 0) {
constructor(kernel, id, timeoutMs = 0) {
this._transponderId = id || newTransponderId();
this._timeoutMs = +timeoutMs || 0;
this._channel = new Network();
// if (first) {
this._channel.use(this.handleSignalAppCon);
// } else {
// this._channel.use(this.handleSignalLastAppCon);
// }
this._network = kernel._network;
}

clone(cloneId) {
const clone = new Transponder({ _network: this._network }, cloneId);
clone._channel = this._channel;
return clone;
}

setCtx({ t, term, a, action, o, orient }, data) {
const transponderId = this._transponderId;
const timeoutMs = this._timeoutMs;

return new Promise((resolve, reject) => {
if (timeoutMs) {
setTimeout(() => {
reject(`reached timeout of: ${timeoutMs}ms`);
}, timeoutMs);
}
const control = transponderControl(transponderId, resolve);
this._network.setCtxControl(
{ t, term, a, action, o, orient },
data,
control,
this.forwardAppCtx
);
});
}

setAppCtx(ac) {
const transponderId = this._transponderId;
const timeoutMs = this._timeoutMs;

return new Promise((resolve, reject) => {
if (timeoutMs) {
setTimeout(() => {
reject(`reached timeout of: ${timeoutMs}ms`);
}, timeoutMs);
}
const control = transponderControl(transponderId, resolve);
this._network.setAppCtxControl(ac, control, this.forwardAppCtx);
});
}

forwardAppCtx = (ac, control) => {
console.log(
`transponder{${this._transponderId}}::forwardAppCtx::ac:`,
ac.unwrapCtx()
);
console.log(
`transponder{${this._transponderId}}::forwardAppCtx::control:`,
control
);
if (control.transponderId === this._transponderId) {
console.log(
`transponder{${
this._transponderId
}}::forwardAppCtx::control check passed`
);
this._channel.setAppCtxControl(ac, control, this.forwardAppCtx);
}
console.log(
`transponder{${
this._transponderId
}}::forwardAppCtx::calling network.setAppCtxControl`
);
this._network.setAppCtxControl(ac, control, this.forwardAppCtx);
};

handleSignalAppCon = (handler, ac, forwardAppCtx, control) => {
console.log(
`transponder{${this._transponderId}}::handleSignalFirstAppCon::ac:`,
ac.unwrapCtx()
);
console.log(
`transponder{${this._transponderId}}::handleSignalFirstAppCon::control:`,
control
);
// first matching handler will signal the listener
if (control.transponderId === this._transponderId && control.signal) {
control.signal(ac);
}
return handler.handleAppCon(ac, forwardAppCtx, control);
};

// handleSignalLastAppCon = (handler, ac, forwardAppCtx, control) => {
// // handle the ac using the network first
// console.log(`transponder{${this._transponderId}}::handleSignalLastAppCon::ac:`, ac.unwrapCtx());
// console.log(`transponder{${this._transponderId}}::handleSignalLastAppCon::control:`, control);
// const rv = handler.handleAppCon(ac, forwardAppCtx, control);
// // last matching handler will signal the listener
// if (control.transponderId === this._transponderId && control.signal) {
// console.log(`transponder{${this._transponderId}}::handleSignalLastAppCon::signaling:`, ac.unwrapCtx());
// control.signal(ac);
// }
// return rv;
// }

addInterceptHandler({ t, term, a, action, o, orient }, handler) {
this._channel.addInterceptHandler(
{ t, term, a, action, o, orient },
handler
);
}

addAsyncHandler({ t, term, a, action, o, orient }, handler) {
this._channel.addAsyncHandler({ t, term, a, action, o, orient }, handler);
}

addInlineHandler({ t, term, a, action, o, orient }, handler) {
this._channel.addInlineHandler({ t, term, a, action, o, orient }, handler);
}

removeInterceptHandler({ t, term, a, action, o, orient }, handler) {
this._channel.removeInterceptHandler(
{ t, term, a, action, o, orient },
handler
);
}

removeAsyncHandler({ t, term, a, action, o, orient }, handler) {
this._channel.removeAsyncHandler(
{ t, term, a, action, o, orient },
handler
);
}

removeInlineHandler({ t, term, a, action, o, orient }, handler) {
this._channel.removeInlineHandler(
{ t, term, a, action, o, orient },
handler
);
}
}
3 changes: 2 additions & 1 deletion packages/tao-utils/src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import trigramFilter from './trigram-filter';
import Channel from './Channel';
import Source from './Source';
import Transponder from './Transponder';
import seive from './seive';
export * from './bridge';

export { trigramFilter, Channel, Source, seive };
export { trigramFilter, Channel, Source, Transponder, seive };

0 comments on commit 311f738

Please sign in to comment.