Skip to content

Commit 9aa077e

Browse files
authored
Update air (#47)
* Migrate to the new version of air-interpreter package * Add pipeline with integration tests * Fix issues which prevented tests to finish normally
1 parent 2d46fd4 commit 9aa077e

13 files changed

+114
-519
lines changed

.github/workflows/js_sdk_ci.yml

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,40 @@
1-
name: Node.js CI
1+
name: Run tests
22

33
defaults:
4-
run:
5-
working-directory: .
4+
run:
5+
working-directory: .
66

77
on:
8-
push:
8+
push:
99

1010
jobs:
11-
build:
12-
13-
runs-on: ubuntu-latest
14-
15-
strategy:
16-
matrix:
17-
node-version: [14.x, 15.x]
18-
19-
steps:
20-
- uses: actions/checkout@v2
21-
22-
- uses: actions/cache@v2
23-
with:
24-
path: ~/.npm
25-
key: ${{ runner.os }}-v1-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
26-
restore-keys: |
27-
${{ runner.os }}-v1-node-${{ matrix.node-version }}
28-
29-
- name: Setup Node.js ${{ matrix.node-version }}
30-
uses: actions/setup-node@v1
31-
with:
32-
node-version: ${{ matrix.node-version }}
33-
34-
- run: npm install
35-
- run: npm run test:unit
36-
env:
37-
CI: true
38-
39-
11+
build:
12+
runs-on: ubuntu-latest
13+
14+
strategy:
15+
matrix:
16+
node-version: [14.x, 15.x]
17+
node-env: ['', ':node']
18+
19+
steps:
20+
- uses: actions/checkout@v2
21+
22+
- uses: actions/cache@v2
23+
with:
24+
path: ~/.npm
25+
key: ${{ runner.os }}-v1-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
26+
restore-keys: |
27+
${{ runner.os }}-v1-node-${{ matrix.node-version }}
28+
29+
- name: Setup Node.js ${{ matrix.node-version }}
30+
uses: actions/setup-node@v1
31+
with:
32+
node-version: ${{ matrix.node-version }}
33+
34+
- name: Run container with Fluence node
35+
run: docker run -d --rm -e RUST_LOG="info" -p 1210:1210 -p 4310:4310 fluencelabs/fluence -t 1210 -w 4310 -k gKdiCSUr1TFGFEgu2t8Ch1XEUsrN5A2UfBLjSZvfci9SPR3NvZpACfcpPGC3eY4zma1pk7UvYv5zb1VjvPHwCjj --local
36+
37+
- run: npm install
38+
- run: npm run test${{ matrix.node-env }}:all
39+
env:
40+
CI: true

jest-patched-jsdom.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const Environment = require('jest-environment-jsdom');
2+
3+
module.exports = class CustomTestEnvironment extends Environment {
4+
async setup() {
5+
await super.setup();
6+
if (typeof this.global.TextEncoder === 'undefined') {
7+
const { TextEncoder, TextDecoder } = require('util');
8+
this.global.TextEncoder = TextEncoder;
9+
this.global.TextDecoder = TextDecoder;
10+
this.global.Uint8Array = Uint8Array;
11+
this.global.ArrayBuffer = ArrayBuffer;
12+
}
13+
}
14+
};

jest.config.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
module.exports = {
2-
preset: 'ts-jest',
3-
testEnvironment: 'node',
4-
};
2+
preset: 'ts-jest',
3+
testEnvironment: './jest-patched-jsdom.js',
4+
};

package-lock.json

Lines changed: 14 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,21 @@
55
"main": "./dist/index.js",
66
"typings": "./dist/index.d.ts",
77
"scripts": {
8-
"test": "jest --env=jsdom --watch",
9-
"test:all": "jest --env=jsdom",
10-
"test:unit": "jest --env=jsdom --testPathPattern=src/__test__/unit",
11-
"test:integration": "jest --env=jsdom --testPathPattern=src/__test__/integration",
8+
"test": "jest --watch",
9+
"test:all": "jest",
10+
"test:unit": "jest --testPathPattern=src/__test__/unit",
11+
"test:integration": "jest --testPathPattern=src/__test__/integration",
12+
"test:node": "jest --env=node --watch",
13+
"test:node:all": "jest --env=node",
14+
"test:node:unit": "jest --env=node --testPathPattern=src/__test__/unit",
15+
"test:node:integration": "jest --env=node --testPathPattern=src/__test__/integration",
1216
"build": "tsc"
1317
},
1418
"repository": "https://github.com/fluencelabs/fluence-js",
1519
"author": "Fluence Labs",
1620
"license": "Apache-2.0",
1721
"dependencies": {
18-
"@fluencelabs/aquamarine-interpreter": "0.8.2",
22+
"@fluencelabs/air-interpreter": "0.9.7",
1923
"async": "3.2.0",
2024
"base64-js": "1.3.1",
2125
"bs58": "4.0.1",

src/__test__/connection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
/*
1414
* start docker container to run integration tests locally:
1515
16-
docker run --rm -e RUST_LOG="info" -p 1210:1210 -p 4310:4310 fluencelabs/fluence -t 1210 -w 4310 -k gKdiCSUr1TFGFEgu2t8Ch1XEUsrN5A2UfBLjSZvfci9SPR3NvZpACfcpPGC3eY4zma1pk7UvYv5zb1VjvPHwCjj
16+
docker run --rm -e RUST_LOG="info" -p 1210:1210 -p 4310:4310 fluencelabs/fluence -t 1210 -w 4310 -k gKdiCSUr1TFGFEgu2t8Ch1XEUsrN5A2UfBLjSZvfci9SPR3NvZpACfcpPGC3eY4zma1pk7UvYv5zb1VjvPHwCjj --local
1717
1818
*/
1919
export const nodes = [

src/__test__/integration/legacy.api.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ import { nodes } from '../connection';
55
let client: FluenceClient;
66

77
describe('Legacy api suite', () => {
8+
afterEach(async () => {
9+
if (client) {
10+
await client.disconnect();
11+
}
12+
});
13+
814
it('sendParticle', async () => {
915
client = await createClient(nodes[0]);
1016

src/__test__/unit/air.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ describe('== AIR suite', () => {
6767
await client.initiateFlow(request);
6868

6969
// assert
70-
await expect(error).rejects.toContain("aqua script can't be parsed");
70+
await expect(error).rejects.toContain("air can't be parsed");
7171
});
7272

7373
it('call script without ttl', async function () {

src/__test__/unit/ast.spec.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
import { AquamarineInterpreter } from '../../internal/aqua/interpreter';
1+
import { AirInterpreter } from '@fluencelabs/air-interpreter';
2+
import { genUUID } from '../../internal/particle';
23

34
describe('== AST parsing suite', () => {
45
it('parse simple script and return ast', async function () {
5-
const interpreter = await AquamarineInterpreter.create({} as any);
6+
const interpreter = await AirInterpreter.create(
7+
undefined as any,
8+
undefined as any,
9+
undefined as any,
10+
undefined as any,
11+
);
612
let ast = interpreter.parseAir(`
713
(call "node" ("service" "function") [1 2 3] output)
814
`);
915

10-
console.log(ast);
1116
ast = JSON.parse(ast);
1217

1318
expect(ast).toEqual({

src/internal/ClientImpl.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { AquaCallHandler, errorHandler, fnHandler } from './AquaHandler';
2525
import { loadRelayFn, loadVariablesService } from './RequestFlowBuilder';
2626
import { logParticle, Particle } from './particle';
2727
import log from 'loglevel';
28-
import { AquamarineInterpreter } from './aqua/interpreter';
28+
import { AirInterpreter } from '@fluencelabs/air-interpreter';
2929

3030
const makeDefaultClientHandler = (): AquaCallHandler => {
3131
const res = new AquaCallHandler();
@@ -54,7 +54,7 @@ export class ClientImpl implements FluenceClient {
5454
}
5555

5656
private connection: FluenceConnection;
57-
private interpreter: AquamarineInterpreter;
57+
private interpreter: AirInterpreter;
5858

5959
constructor(selfPeerIdFull: PeerId) {
6060
this.selfPeerIdFull = selfPeerIdFull;
@@ -68,13 +68,18 @@ export class ClientImpl implements FluenceClient {
6868
await this.connection.disconnect();
6969
}
7070
this.clearWathcDog();
71+
this.requests.forEach((r) => {
72+
r.cancel();
73+
});
7174
}
7275

7376
async initAquamarineRuntime(): Promise<void> {
74-
this.interpreter = await AquamarineInterpreter.create({
75-
particleHandler: this.interpreterCallback.bind(this),
76-
peerId: this.selfPeerIdFull,
77-
});
77+
this.interpreter = await AirInterpreter.create(
78+
this.interpreterCallback.bind(this),
79+
this.selfPeerId,
80+
'trace',
81+
log.log,
82+
);
7883
}
7984

8085
async connect(multiaddr: string | Multiaddr, options?: FluenceConnectionOptions): Promise<void> {

src/internal/RequestFlow.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import log, { trace } from 'loglevel';
22
import PeerId from 'peer-id';
3-
import { AquamarineInterpreter } from './aqua/interpreter';
3+
import { AirInterpreter } from '@fluencelabs/air-interpreter';
44
import { AquaCallHandler } from './AquaHandler';
55
import { InterpreterOutcome, PeerIdB58 } from './commonTypes';
66
import { FluenceConnection } from './FluenceConnection';
@@ -20,6 +20,7 @@ export class RequestFlow {
2020
private prevData: Uint8Array = Buffer.from([]);
2121
private onTimeoutHandlers = [];
2222
private onErrorHandlers = [];
23+
private timeoutHandle?: NodeJS.Timeout;
2324

2425
readonly id: string;
2526
readonly isExternal: boolean;
@@ -33,7 +34,7 @@ export class RequestFlow {
3334
const res = new RequestFlow(true, particle.id, particle.script);
3435
res.ttl = particle.ttl;
3536
res.state = particle;
36-
setTimeout(res.raiseTimeout.bind(res), particle.ttl);
37+
res.timeoutHandle = setTimeout(res.raiseTimeout.bind(res), particle.ttl);
3738
return res;
3839
}
3940

@@ -57,7 +58,7 @@ export class RequestFlow {
5758
this.onErrorHandlers.push(handler);
5859
}
5960

60-
async execute(interpreter: AquamarineInterpreter, connection: FluenceConnection, relayPeerId?: PeerIdB58) {
61+
async execute(interpreter: AirInterpreter, connection: FluenceConnection, relayPeerId?: PeerIdB58) {
6162
if (this.hasExpired()) {
6263
return;
6364
}
@@ -97,11 +98,18 @@ export class RequestFlow {
9798

9899
if (!connection) {
99100
this.raiseError('Cannot send particle: non connected');
101+
return;
100102
}
101103

102104
this.sendIntoConnection(connection);
103105
}
104106

107+
public cancel() {
108+
if (this.timeoutHandle) {
109+
clearTimeout(this.timeoutHandle);
110+
}
111+
}
112+
105113
private throwIncorrectNextPeerPks(nextPeers: PeerIdB58[]) {
106114
this.raiseError(
107115
`Particle is expected to be sent to only the single peer (relay which client is connected to).
@@ -127,7 +135,7 @@ relay peer id: ${this.relayPeerId}
127135
};
128136

129137
this.state = particle;
130-
setTimeout(this.raiseTimeout.bind(this), particle.ttl);
138+
this.timeoutHandle = setTimeout(this.raiseTimeout.bind(this), particle.ttl);
131139
}
132140

133141
receiveUpdate(particle: Particle) {
@@ -145,7 +153,7 @@ relay peer id: ${this.relayPeerId}
145153
}
146154
}
147155

148-
runInterpreter(interpreter: AquamarineInterpreter) {
156+
runInterpreter(interpreter: AirInterpreter) {
149157
const interpreterOutcomeStr = interpreter.invoke(
150158
this.state.init_peer_id,
151159
this.state.script,

0 commit comments

Comments
 (0)