FluencePeer: add option to specify default TTL for all new particles (#91)

This commit is contained in:
Pavel 2021-10-21 17:56:21 +03:00 committed by GitHub
parent 9d00b70897
commit 79ad43315b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 35 deletions

View File

@ -189,7 +189,7 @@ describe('Typescript usage suite', () => {
const isConnected = await checkConnection(anotherPeer); const isConnected = await checkConnection(anotherPeer);
// assert // assert
expect(isConnected).toBeTruthy; expect(isConnected).toBeTruthy();
}); });
it('address as multiaddr', async () => { it('address as multiaddr', async () => {
@ -201,7 +201,7 @@ describe('Typescript usage suite', () => {
const isConnected = await checkConnection(anotherPeer); const isConnected = await checkConnection(anotherPeer);
// assert // assert
expect(isConnected).toBeTruthy; expect(isConnected).toBeTruthy();
}); });
it('address as node', async () => { it('address as node', async () => {
@ -213,7 +213,7 @@ describe('Typescript usage suite', () => {
const isConnected = await checkConnection(anotherPeer); const isConnected = await checkConnection(anotherPeer);
// assert // assert
expect(isConnected).toBeTruthy; expect(isConnected).toBeTruthy();
}); });
it('peerid as peer id', async () => { it('peerid as peer id', async () => {
@ -225,7 +225,7 @@ describe('Typescript usage suite', () => {
const isConnected = await checkConnection(anotherPeer); const isConnected = await checkConnection(anotherPeer);
// assert // assert
expect(isConnected).toBeTruthy; expect(isConnected).toBeTruthy();
}); });
it('peerid as seed', async () => { it('peerid as seed', async () => {
@ -237,7 +237,7 @@ describe('Typescript usage suite', () => {
const isConnected = await checkConnection(anotherPeer); const isConnected = await checkConnection(anotherPeer);
// assert // assert
expect(isConnected).toBeTruthy; expect(isConnected).toBeTruthy();
}); });
it('With connection options: dialTimeout', async () => { it('With connection options: dialTimeout', async () => {
@ -249,7 +249,7 @@ describe('Typescript usage suite', () => {
const isConnected = await checkConnection(anotherPeer); const isConnected = await checkConnection(anotherPeer);
// assert // assert
expect(isConnected).toBeTruthy; expect(isConnected).toBeTruthy();
}); });
it('With connection options: skipCheckConnection', async () => { it('With connection options: skipCheckConnection', async () => {
@ -261,7 +261,7 @@ describe('Typescript usage suite', () => {
const isConnected = await checkConnection(anotherPeer); const isConnected = await checkConnection(anotherPeer);
// assert // assert
expect(isConnected).toBeTruthy; expect(isConnected).toBeTruthy();
}); });
it('With connection options: checkConnectionTTL', async () => { it('With connection options: checkConnectionTTL', async () => {
@ -273,7 +273,19 @@ describe('Typescript usage suite', () => {
const isConnected = await checkConnection(anotherPeer); const isConnected = await checkConnection(anotherPeer);
// assert // assert
expect(isConnected).toBeTruthy; expect(isConnected).toBeTruthy();
});
it('With connection options: defaultTTL', async () => {
// arrange
const addr = nodes[0];
// act
await anotherPeer.start({ connectTo: addr, defaultTtlMs: 1 });
const isConnected = await checkConnection(anotherPeer);
// assert
expect(isConnected).toBeFalsy();
}); });
}); });
@ -297,9 +309,6 @@ describe('Typescript usage suite', () => {
resolve(res); resolve(res);
}, },
}, },
// op: {
// identity: (req) => {},
// },
_timeout: reject, _timeout: reject,
}); });

View File

@ -94,6 +94,14 @@ export interface PeerConfig {
* The dialing timeout in milliseconds * The dialing timeout in milliseconds
*/ */
dialTimeoutMs?: number; dialTimeoutMs?: number;
/**
* Sets the default TTL for all particles originating from the peer with no TTL specified.
* If the originating particle's TTL is defined then that value will be used
* If the option is not set default TTL will be 7000
* Value 0 (zero) is treated as if the option was not set
*/
defaultTtlMs?: number;
} }
/** /**
@ -169,6 +177,8 @@ export class FluencePeer {
this._keyPair = await KeyPair.randomEd25519(); this._keyPair = await KeyPair.randomEd25519();
} }
this._defaultTTL = config?.defaultTtlMs || DEFAULT_TTL;
this._interpreter = await createInterpreter(config?.avmLogLevel || 'off'); this._interpreter = await createInterpreter(config?.avmLogLevel || 'off');
if (config?.connectTo) { if (config?.connectTo) {
@ -234,7 +244,7 @@ export class FluencePeer {
} }
if (particle.ttl === undefined) { if (particle.ttl === undefined) {
particle.ttl = DEFAULT_TTL; particle.ttl = this._defaultTTL;
} }
this._incomingParticles.next(particle); this._incomingParticles.next(particle);
@ -333,37 +343,29 @@ export class FluencePeer {
// Internal peer state // Internal peer state
private _defaultTTL: number;
private _relayPeerId: PeerIdB58 | null = null; private _relayPeerId: PeerIdB58 | null = null;
private _keyPair: KeyPair; private _keyPair: KeyPair;
private _connection: FluenceConnection; private _connection: FluenceConnection;
private _interpreter: AirInterpreter; private _interpreter: AirInterpreter;
private _timeouts: Array<NodeJS.Timeout> = []; private _timeouts: Array<NodeJS.Timeout> = [];
private _particleQueues = new Map<string, Subject<Particle>>();
private _startParticleProcessing() { private _startParticleProcessing() {
const particleQueues = new Map<string, Subject<Particle>>();
this._incomingParticles this._incomingParticles
.pipe( .pipe(
tap((x) => x.logTo('debug', 'particle received:')), tap((x) => x.logTo('debug', 'particle received:')),
filterExpiredParticles(), filterExpiredParticles(this._expireParticle.bind(this)),
) )
.subscribe((p) => { .subscribe((p) => {
let particlesQueue = particleQueues.get(p.id); let particlesQueue = this._particleQueues.get(p.id);
if (!particlesQueue) { if (!particlesQueue) {
particlesQueue = this._createParticlesProcessingQueue(); particlesQueue = this._createParticlesProcessingQueue();
particleQueues.set(p.id, particlesQueue); this._particleQueues.set(p.id, particlesQueue);
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
log.debug(`particle ${p.id} has expired. Deleting particle-related queues and handlers`); this._expireParticle(p.id);
particleQueues.delete(p.id);
const timeoutHandler = this._timeoutHandlers.get(p.id);
if (timeoutHandler) {
timeoutHandler();
}
this._particleSpecificHandlers.delete(p.id);
this._timeoutHandlers.delete(p.id);
}, p.actualTtl()); }, p.actualTtl());
this._timeouts.push(timeout); this._timeouts.push(timeout);
@ -377,6 +379,18 @@ export class FluencePeer {
}); });
} }
private _expireParticle(particleId: string) {
log.debug(`particle ${particleId} has expired. Deleting particle-related queues and handlers`);
this._particleQueues.delete(particleId);
const timeoutHandler = this._timeoutHandlers.get(particleId);
if (timeoutHandler) {
timeoutHandler();
}
this._particleSpecificHandlers.delete(particleId);
this._timeoutHandlers.delete(particleId);
}
private _createParticlesProcessingQueue() { private _createParticlesProcessingQueue() {
let particlesQueue = new Subject<Particle>(); let particlesQueue = new Subject<Particle>();
let prevData: Uint8Array = Buffer.from([]); let prevData: Uint8Array = Buffer.from([]);
@ -384,7 +398,7 @@ export class FluencePeer {
particlesQueue particlesQueue
.pipe( .pipe(
// force new line // force new line
filterExpiredParticles(), filterExpiredParticles(this._expireParticle.bind(this)),
) )
.subscribe((x) => { .subscribe((x) => {
const result = runInterpreter(this.getStatus().peerId, this._interpreter, x, prevData); const result = runInterpreter(this.getStatus().peerId, this._interpreter, x, prevData);
@ -510,6 +524,7 @@ export class FluencePeer {
for (let item of this._timeouts) { for (let item of this._timeouts) {
clearTimeout(item); clearTimeout(item);
} }
this._particleQueues.clear();
} }
/** /**
@ -569,11 +584,11 @@ function runInterpreter(
return interpreterResult; return interpreterResult;
} }
function filterExpiredParticles() { function filterExpiredParticles(onParticleExpiration: (particleId: string) => void) {
return pipe( return pipe(
tap((p: Particle) => { tap((p: Particle) => {
if (p.hasExpired) { if (p.hasExpired()) {
log.debug(`particle ${p.id} has expired`); onParticleExpiration(p.id);
} }
}), }),
filter((x: Particle) => !x.hasExpired()), filter((x: Particle) => !x.hasExpired()),

View File

@ -21,8 +21,6 @@ import log from 'loglevel';
import { ParticleContext } from './commonTypes'; import { ParticleContext } from './commonTypes';
import { dataToString } from './utils'; import { dataToString } from './utils';
const DefaultTTL = 7000;
export class Particle { export class Particle {
id: string; id: string;
initPeerId: string; initPeerId: string;
@ -37,7 +35,7 @@ export class Particle {
const res = new Particle(); const res = new Particle();
res.id = genUUID(); res.id = genUUID();
res.script = script; res.script = script;
res.ttl = ttlMs || DefaultTTL; res.ttl = ttlMs;
res.data = Buffer.from([]); res.data = Buffer.from([]);
res.timestamp = Date.now(); res.timestamp = Date.now();

View File

@ -54,7 +54,7 @@ export const MakeServiceCall = (fn: (args: any[]) => CallServiceResultType) => {
}; };
/** /**
* Checks the network connection by sending a ping-like request to relat node * Checks the network connection by sending a ping-like request to relay node
* @param { FluenceClient } peer - The Fluence Client instance. * @param { FluenceClient } peer - The Fluence Client instance.
*/ */
export const checkConnection = async (peer: FluencePeer, ttl?: number): Promise<boolean> => { export const checkConnection = async (peer: FluencePeer, ttl?: number): Promise<boolean> => {
@ -127,11 +127,15 @@ export const checkConnection = async (peer: FluencePeer, ttl?: number): Promise<
}), }),
); );
peer.internals.regHandler.timeout(particle.id, () => {
reject('particle timed out');
});
peer.internals.initiateParticle(particle); peer.internals.initiateParticle(particle);
}); });
try { try {
const [result] = await promise; const result = await promise;
if (result != msg) { if (result != msg) {
log.warn("unexpected behavior. 'identity' must return the passed arguments."); log.warn("unexpected behavior. 'identity' must return the passed arguments.");
} }