From 0ff10a25ded6f9ad12bb03c7e1401cd042f106e3 Mon Sep 17 00:00:00 2001 From: Pavel Date: Thu, 25 Mar 2021 21:33:27 +0300 Subject: [PATCH] update aqua version (#33) * Bump aquamarine version * Add connection options --- package-lock.json | 6 +-- package.json | 2 +- src/FluenceClient.ts | 17 +++++++-- src/__test__/integration/builtins.spec.ts | 4 +- src/__test__/integration/client.spec.ts | 45 +++++++++++++++++++++++ src/__test__/unit/air.spec.ts | 2 +- src/__test__/unit/ast.spec.ts | 6 +-- src/internal/ClientImpl.ts | 6 +-- src/internal/FluenceConnection.ts | 28 +++++++++++++- src/internal/RequestFlowBuilder.ts | 6 ++- 10 files changed, 101 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index d3d34eda..6b0f7dcd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1088,9 +1088,9 @@ } }, "@fluencelabs/aquamarine-interpreter": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@fluencelabs/aquamarine-interpreter/-/aquamarine-interpreter-0.7.2.tgz", - "integrity": "sha512-4LrcpeG0ONb3/kTFgt1QNERn9e7aAJBJgqbqNnx81NqFFngTi2xypKIuyPOttcxSdZTH5mpbwwn3JKFimvOvNA==" + "version": "0.7.9", + "resolved": "https://registry.npmjs.org/@fluencelabs/aquamarine-interpreter/-/aquamarine-interpreter-0.7.9.tgz", + "integrity": "sha512-VXbHm0d05XMjTSzOTcb+spVRrIuMcrw8/3dl197wH0jx1C3Wou+vAapQLvGNcKzqDhktPOOzJTE4UARYd0lFMw==" }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", diff --git a/package.json b/package.json index fc67dd6b..6ab1dbbf 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "author": "Fluence Labs", "license": "Apache-2.0", "dependencies": { - "@fluencelabs/aquamarine-interpreter": "0.7.2", + "@fluencelabs/aquamarine-interpreter": "0.7.9", "async": "3.2.0", "base64-js": "1.3.1", "bs58": "4.0.1", diff --git a/src/FluenceClient.ts b/src/FluenceClient.ts index 789b43ad..495c07d9 100644 --- a/src/FluenceClient.ts +++ b/src/FluenceClient.ts @@ -5,6 +5,7 @@ import PeerId, { isPeerId } from 'peer-id'; import { AquaCallHandler } from './internal/AquaHandler'; import { ClientImpl } from './internal/ClientImpl'; import { PeerIdB58 } from './internal/commonTypes'; +import { FluenceConnectionOptions } from './internal/FluenceConnection'; import { generatePeerId, seedToPeerId } from './internal/peerIdUtils'; import { RequestFlow } from './internal/RequestFlow'; import { RequestFlowBuilder } from './internal/RequestFlowBuilder'; @@ -63,11 +64,13 @@ type Node = { * Creates a Fluence client. If the `connectTo` is specified connects the client to the network * @param { string | Multiaddr | Node } [connectTo] - Node in Fluence network to connect to. If not specified client will not be connected to the n * @param { PeerId | string } [peerIdOrSeed] - The Peer Id of the created client. Specified either as PeerId structure or as seed string. Will be generated randomly if not specified + * @param { FluenceConnectionOptions } [options] - additional configuraton options for Fluence Connection made with the client * @returns { Promise } Promise which will be resolved with the created FluenceClient */ export const createClient = async ( connectTo?: string | Multiaddr | Node, peerIdOrSeed?: PeerId | string, + options?: FluenceConnectionOptions, ): Promise => { let peerId; if (!peerIdOrSeed) { @@ -92,9 +95,14 @@ export const createClient = async ( theAddress = new Multiaddr(connectTo as string); } - await client.connect(theAddress); - if (!(await checkConnection(client))) { - throw new Error('Connection check failed. Check if the node is working or try to connect to another node'); + await client.connect(theAddress, options); + + if (options?.skipCheckConnection) { + if (!(await checkConnection(client, options.checkConnectionTTL))) { + throw new Error( + 'Connection check failed. Check if the node is working or try to connect to another node', + ); + } } } @@ -105,7 +113,7 @@ export const createClient = async ( * Checks the network connection by sending a ping-like request to relat node * @param { FluenceClient } client - The Fluence Client instance. */ -export const checkConnection = async (client: FluenceClient): Promise => { +export const checkConnection = async (client: FluenceClient, ttl?: number): Promise => { if (!client.isConnected) { return false; } @@ -121,6 +129,7 @@ export const checkConnection = async (client: FluenceClient): Promise = (call %init_peer_id% ("${callbackService}" "${callbackFn}") [result]) )`, ) + .withTTL(ttl) .withVariables({ msg, }) diff --git a/src/__test__/integration/builtins.spec.ts b/src/__test__/integration/builtins.spec.ts index 525f9d6a..a6882ac9 100644 --- a/src/__test__/integration/builtins.spec.ts +++ b/src/__test__/integration/builtins.spec.ts @@ -74,7 +74,7 @@ describe('Builtins usage suite', () => { let bpIdReturned = await addBlueprint(client, 'test_broken_blueprint', ['test_broken_module'], bpId); let allBps = await getBlueprints(client); - const allBpIds = allBps.map(x => x.id); + const allBpIds = allBps.map((x) => x.id); expect(allBpIds).toContain(bpIdReturned); }); @@ -85,7 +85,7 @@ describe('Builtins usage suite', () => { let promise = createService(client, 'test_broken_blueprint'); await expect(promise).rejects.toMatchObject({ - error: expect.stringContaining("Blueprint wasn't found at"), + error: expect.stringContaining("Blueprint 'test_broken_blueprint' wasn't found"), instruction: expect.stringContaining('blueprint_id'), }); }); diff --git a/src/__test__/integration/client.spec.ts b/src/__test__/integration/client.spec.ts index 0968e155..6a7a87c3 100644 --- a/src/__test__/integration/client.spec.ts +++ b/src/__test__/integration/client.spec.ts @@ -42,6 +42,15 @@ describe('Typescript usage suite', () => { expect(isConnected).toEqual(true); }); + it('check connection should work with ttl', async function () { + client = await createClient(); + await client.connect(nodes[0].multiaddr); + + let isConnected = await checkConnection(client, 10000); + + expect(isConnected).toEqual(true); + }); + it('two clients should work inside the same time browser', async () => { // arrange const client1 = await createClient(nodes[0].multiaddr); @@ -136,6 +145,42 @@ describe('Typescript usage suite', () => { // assert expect(isConnected).toBeTruthy; }); + + it('With connection options: dialTimeout', async () => { + // arrange + const addr = nodes[0].multiaddr; + + // act + client = await createClient(addr, undefined, { dialTimeout: 100000 }); + const isConnected = await checkConnection(client); + + // assert + expect(isConnected).toBeTruthy; + }); + + it('With connection options: skipCheckConnection', async () => { + // arrange + const addr = nodes[0].multiaddr; + + // act + client = await createClient(addr, undefined, { skipCheckConnection: true }); + const isConnected = await checkConnection(client); + + // assert + expect(isConnected).toBeTruthy; + }); + + it('With connection options: checkConnectionTTL', async () => { + // arrange + const addr = nodes[0].multiaddr; + + // act + client = await createClient(addr, undefined, { checkConnectionTTL: 1000 }); + const isConnected = await checkConnection(client); + + // assert + expect(isConnected).toBeTruthy; + }); }); it('xor handling should work with connected client', async function () { diff --git a/src/__test__/unit/air.spec.ts b/src/__test__/unit/air.spec.ts index 04723f52..75663fe9 100644 --- a/src/__test__/unit/air.spec.ts +++ b/src/__test__/unit/air.spec.ts @@ -75,7 +75,7 @@ describe('== AIR suite', () => { const script = `(null)`; // prettier-ignore const [request, promise] = new RequestFlowBuilder() - .withTTL(0) + .withTTL(1) .withRawScript(script) .buildAsFetch(); diff --git a/src/__test__/unit/ast.spec.ts b/src/__test__/unit/ast.spec.ts index 6e5b6735..e5814623 100644 --- a/src/__test__/unit/ast.spec.ts +++ b/src/__test__/unit/ast.spec.ts @@ -4,14 +4,15 @@ describe('== AST parsing suite', () => { it('parse simple script and return ast', async function () { const interpreter = await AquamarineInterpreter.create({} as any); let ast = interpreter.parseAir(` - (call node ("service" "function") [1 2 3 arg] output) + (call "node" ("service" "function") [1 2 3] output) `); + console.log(ast); ast = JSON.parse(ast); expect(ast).toEqual({ Call: { - peer_part: { PeerPk: { Variable: 'node' } }, + peer_part: { PeerPk: { Literal: 'node' } }, function_part: { ServiceIdWithFuncName: [{ Literal: 'service' }, { Literal: 'function' }] }, args: [ { @@ -29,7 +30,6 @@ describe('== AST parsing suite', () => { Int: 3, }, }, - { Variable: 'arg' }, ], output: { Scalar: 'output' }, }, diff --git a/src/internal/ClientImpl.ts b/src/internal/ClientImpl.ts index 9a164c4f..88019cf3 100644 --- a/src/internal/ClientImpl.ts +++ b/src/internal/ClientImpl.ts @@ -16,7 +16,7 @@ import * as PeerId from 'peer-id'; import Multiaddr from 'multiaddr'; -import { FluenceConnection } from './FluenceConnection'; +import { FluenceConnection, FluenceConnectionOptions } from './FluenceConnection'; import { CallServiceResult, ParticleHandler, PeerIdB58, SecurityTetraplet } from './commonTypes'; import { FluenceClient } from '../FluenceClient'; @@ -77,7 +77,7 @@ export class ClientImpl implements FluenceClient { }); } - async connect(multiaddr: string | Multiaddr): Promise { + async connect(multiaddr: string | Multiaddr, options?: FluenceConnectionOptions): Promise { multiaddr = Multiaddr(multiaddr); const nodePeerId = multiaddr.getPeerId(); @@ -96,7 +96,7 @@ export class ClientImpl implements FluenceClient { this.selfPeerIdFull, this.executeIncomingParticle.bind(this), ); - await connection.connect(); + await connection.connect(options); this.connection = connection; this.initWatchDog(); } diff --git a/src/internal/FluenceConnection.ts b/src/internal/FluenceConnection.ts index 900a3691..f5c81156 100644 --- a/src/internal/FluenceConnection.ts +++ b/src/internal/FluenceConnection.ts @@ -23,7 +23,8 @@ import * as log from 'loglevel'; import { parseParticle, Particle, toPayload } from './particle'; import { NOISE } from 'libp2p-noise'; import PeerId from 'peer-id'; -import Multiaddr from 'multiaddr' +import Multiaddr from 'multiaddr'; +import { options } from 'libp2p/src/keychain'; export const PROTOCOL_NAME = '/fluence/faas/1.0.0'; @@ -33,6 +34,26 @@ enum Status { Disconnected = 'Disconnected', } +/** + * Options to configure fluence connection + */ +export interface FluenceConnectionOptions { + /** + * @property {number} [checkConnectionTTL] - TTL for the check connection request in ms + */ + checkConnectionTTL?: number; + + /** + * @property {number} [checkConnectionTTL] - set to true to skip check connection request completely + */ + skipCheckConnection?: boolean; + + /** + * @property {number} [dialTimeout] - How long a dial attempt is allowed to take. + */ + dialTimeout?: number; +} + export class FluenceConnection { private readonly selfPeerId: PeerId; private node: Peer; @@ -54,7 +75,7 @@ export class FluenceConnection { this.nodePeerId = hostPeerId; } - async connect() { + async connect(options?: FluenceConnectionOptions) { let peerInfo = this.selfPeerId; this.node = await Peer.create({ peerId: peerInfo, @@ -64,6 +85,9 @@ export class FluenceConnection { streamMuxer: [Mplex], connEncryption: [NOISE], }, + dialer: { + timeout: options?.dialTimeout, + }, }); await this.startReceiving(); diff --git a/src/internal/RequestFlowBuilder.ts b/src/internal/RequestFlowBuilder.ts index 11b63c09..8d729c93 100644 --- a/src/internal/RequestFlowBuilder.ts +++ b/src/internal/RequestFlowBuilder.ts @@ -127,8 +127,10 @@ export class RequestFlowBuilder { return this; } - withTTL(ttl: number): RequestFlowBuilder { - this.ttl = ttl; + withTTL(ttl?: number): RequestFlowBuilder { + if (ttl) { + this.ttl = ttl; + } return this; }