Skip to content

Commit 2915844

Browse files
authored
Merge pull request #140 from kaleido-io/eventstrams
Use separate eventstream per namespace
2 parents a189de9 + d6cbee7 commit 2915844

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+546
-386
lines changed

.env

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
PORT=3000
22
ETHCONNECT_URL=http://127.0.0.1:5102
3-
ETHCONNECT_TOPIC=token
4-
FACTORY_CONTRACT_ADDRESS=
5-
AUTO_INIT=true
3+
ETHCONNECT_TOPIC=tokens_0_0
4+
FACTORY_CONTRACT_ADDRESS="0xd85b3fba5552c48389607954e042e7313a9aec6e"
65
USE_LEGACY_ERC20_SAMPLE=false
76
USE_LEGACY_ERC721_SAMPLE=false

.github/workflows/docker_main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
docker:
1010
runs-on: ubuntu-latest
1111
steps:
12-
- uses: actions/checkout@v2
12+
- uses: actions/checkout@v4
1313

1414
- name: Set build tag
1515
id: build_tag_generator

.github/workflows/docker_release.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
docker:
99
runs-on: ubuntu-latest
1010
steps:
11-
- uses: actions/checkout@v2
11+
- uses: actions/checkout@v4
1212
with:
1313
fetch-depth: 0
1414

@@ -30,7 +30,7 @@ jobs:
3030
run: |
3131
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin
3232
docker push ghcr.io/hyperledger/firefly-tokens-erc20-erc721:${GITHUB_REF##*/}
33-
33+
3434
- name: Push head tag
3535
run: |
3636
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin

.github/workflows/test.yml

+8-8
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,22 @@ jobs:
88
test:
99
runs-on: ubuntu-latest
1010
steps:
11-
- uses: actions/checkout@v2
11+
- uses: actions/checkout@v4
1212
- name: Use Node.js
13-
uses: actions/setup-node@v2
13+
uses: actions/setup-node@v3
1414
with:
15-
node-version: '16.x'
15+
node-version: '20.9.0'
1616
- run: npm ci
1717
- run: npm run test
1818
- run: npm run test:e2e
1919
solidity-test:
2020
runs-on: ubuntu-latest
2121
steps:
22-
- uses: actions/checkout@v2
22+
- uses: actions/checkout@v4
2323
- name: Use Node.js
24-
uses: actions/setup-node@v2
24+
uses: actions/setup-node@v3
2525
with:
26-
node-version: '16.x'
26+
node-version: '20.9.0'
2727
- run: npm ci
2828
working-directory: ./samples/solidity
2929
- run: npm run compile
@@ -33,6 +33,6 @@ jobs:
3333
docker:
3434
runs-on: ubuntu-latest
3535
steps:
36-
- uses: actions/checkout@v2
36+
- uses: actions/checkout@v4
3737
- name: Docker build
38-
run: docker build --tag ghcr.io/hyperledger/firefly-tokens-erc20-erc721 .
38+
run: docker build --tag ghcr.io/hyperledger/firefly-tokens-erc20-erc721 .

.vscode/launch.json

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "Run Tests",
9+
"runtimeExecutable": "npm",
10+
"args": ["run", "test"],
11+
"request": "launch",
12+
"type": "node",
13+
"outputCapture": "std"
14+
},
15+
{
16+
"name": "Run E2E Tests",
17+
"runtimeExecutable": "npm",
18+
"args": ["run", "test:e2e"],
19+
"request": "launch",
20+
"type": "node",
21+
"outputCapture": "std"
22+
},
23+
{
24+
"type": "node",
25+
"request": "launch",
26+
"name": "Launch Program",
27+
"skipFiles": ["<node_internals>/**"],
28+
"program": "${file}",
29+
"preLaunchTask": "tsc: build - tsconfig.json",
30+
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
31+
}
32+
]
33+
}

.vscode/settings.json

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
{
22
"solidity.compileUsingRemoteVersion": "v0.6.12+commit.27d51765",
33
"editor.codeActionsOnSave": {
4-
"source.fixAll.eslint": true
4+
"source.fixAll.eslint": "explicit"
55
},
66
"eslint.validate": ["javascript"],
77
"solidity.defaultCompiler": "remote",
8-
"cSpell.words": [
9-
"fftm"
10-
]
8+
"cSpell.words": ["eventstream", "fftm"]
119
}

Dockerfile

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
FROM node:16-alpine3.15 as build
1+
FROM node:20-alpine3.17 as build
22
USER node
33
WORKDIR /home/node
44
ADD --chown=node:node package*.json ./
55
RUN npm install
66
ADD --chown=node:node . .
77
RUN npm run build
88

9-
FROM node:16-alpine3.15 as solidity-build
9+
FROM node:20-alpine3.17 as solidity-build
1010
RUN apk add python3 alpine-sdk
1111
USER node
1212
WORKDIR /home/node
@@ -15,7 +15,7 @@ RUN npm install
1515
ADD --chown=node:node ./samples/solidity .
1616
RUN npx hardhat compile
1717

18-
FROM node:16-alpine3.15
18+
FROM node:20-alpine3.17
1919
RUN apk add curl jq
2020
RUN mkdir -p /app/contracts/source \
2121
&& chgrp -R 0 /app/ \
@@ -31,6 +31,8 @@ COPY --from=solidity-build --chown=1001:0 /home/node/contracts /home/node/packag
3131
RUN npm install --production
3232
WORKDIR /app/contracts
3333
COPY --from=solidity-build --chown=1001:0 /home/node/artifacts/contracts/TokenFactory.sol/TokenFactory.json ./
34+
# We also need to keep copying it to the old location to maintain compatibility with the FireFly CLI
35+
COPY --from=solidity-build --chown=1001:0 /home/node/artifacts/contracts/TokenFactory.sol/TokenFactory.json /home/node/contracts/
3436
WORKDIR /app
3537
COPY --from=build --chown=1001:0 /home/node/dist ./dist
3638
COPY --from=build --chown=1001:0 /home/node/package.json /home/node/package-lock.json ./

src/app.module.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright © 2022 Kaleido, Inc.
1+
// Copyright © 2024 Kaleido, Inc.
22
//
33
// SPDX-License-Identifier: Apache-2.0
44
//

src/event-stream/event-stream.interfaces.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright © 2022 Kaleido, Inc.
1+
// Copyright © 2024 Kaleido, Inc.
22
//
33
// SPDX-License-Identifier: Apache-2.0
44
//

src/event-stream/event-stream.module.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright © 2022 Kaleido, Inc.
1+
// Copyright © 2024 Kaleido, Inc.
22
//
33
// SPDX-License-Identifier: Apache-2.0
44
//

src/event-stream/event-stream.service.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright © 2022 Kaleido, Inc.
1+
// Copyright © 2024 Kaleido, Inc.
22
//
33
// SPDX-License-Identifier: Apache-2.0
44
//

src/event-stream/event-stream.service.ts

+32-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright © 2022 Kaleido, Inc.
1+
// Copyright © 2024 Kaleido, Inc.
22
//
33
// SPDX-License-Identifier: Apache-2.0
44
//
@@ -20,9 +20,9 @@ import { AxiosRequestConfig } from 'axios';
2020
import { lastValueFrom } from 'rxjs';
2121
import WebSocket from 'ws';
2222
import { FFRequestIDHeader } from '../request-context/constants';
23-
import { Context } from '../request-context/request-context.decorator';
23+
import { Context, newContext } from '../request-context/request-context.decorator';
2424
import { IAbiMethod } from '../tokens/tokens.interfaces';
25-
import { getHttpRequestOptions, getWebsocketOptions } from '../utils';
25+
import { eventStreamName, getHttpRequestOptions, getWebsocketOptions } from '../utils';
2626
import {
2727
Event,
2828
EventBatch,
@@ -46,6 +46,7 @@ export class EventStreamSocket {
4646
constructor(
4747
private url: string,
4848
private topic: string,
49+
private namespace: string,
4950
private username: string,
5051
private password: string,
5152
private handleEvents: (events: EventBatch) => void,
@@ -67,7 +68,7 @@ export class EventStreamSocket {
6768
} else {
6869
this.logger.log('Event stream websocket connected');
6970
}
70-
this.produce({ type: 'listen', topic: this.topic });
71+
this.produce({ type: 'listen', topic: eventStreamName(this.topic, this.namespace) });
7172
this.produce({ type: 'listenreplies' });
7273
this.ping();
7374
})
@@ -83,6 +84,7 @@ export class EventStreamSocket {
8384
}
8485
})
8586
.on('message', (message: string) => {
87+
this.logger.verbose(`WS => ${message}`);
8688
this.handleMessage(JSON.parse(message));
8789
})
8890
.on('pong', () => {
@@ -109,7 +111,11 @@ export class EventStreamSocket {
109111
}
110112

111113
ack(batchNumber: number | undefined) {
112-
this.produce({ type: 'ack', topic: this.topic, batchNumber });
114+
this.produce({ type: 'ack', topic: eventStreamName(this.topic, this.namespace), batchNumber });
115+
}
116+
117+
nack(batchNumber: number | undefined) {
118+
this.produce({ type: 'nack', topic: eventStreamName(this.topic, this.namespace), batchNumber });
113119
}
114120

115121
close() {
@@ -193,13 +199,27 @@ export class EventStreamService {
193199
batchSize: 50,
194200
batchTimeoutMS: 500,
195201
type: 'websocket',
196-
websocket: { topic },
202+
websocket: { topic: name },
197203
blockedReryDelaySec: 30, // intentional due to spelling error in ethconnect
198204
inputs: true,
199205
timestamps: true,
200206
};
201207

202208
const existingStreams = await this.getStreams(ctx);
209+
210+
// Check to see if there is a deprecated stream that we should remove
211+
this.logger.debug(`Checking for deprecated event steam with topic '${topic}'`);
212+
const deprecatedStream = existingStreams.find(s => s.name === topic);
213+
if (deprecatedStream) {
214+
this.logger.log(`Purging deprecated eventstream '${deprecatedStream.id}'`);
215+
await lastValueFrom(
216+
this.http.delete(
217+
new URL(`/eventstreams/${deprecatedStream.id}`, this.baseUrl).href,
218+
this.requestOptions(ctx),
219+
),
220+
);
221+
}
222+
203223
const stream = existingStreams.find(s => s.name === streamDetails.name);
204224
if (stream) {
205225
const patchedStreamRes = await lastValueFrom(
@@ -331,15 +351,20 @@ export class EventStreamService {
331351
return true;
332352
}
333353

334-
connect(
354+
async connect(
335355
url: string,
336356
topic: string,
357+
namespace: string,
337358
handleEvents: (events: EventBatch) => void,
338359
handleReceipt: (receipt: EventStreamReply) => void,
339360
) {
361+
const name = eventStreamName(topic, namespace);
362+
await this.createOrUpdateStream(newContext(), name, topic);
363+
340364
return new EventStreamSocket(
341365
url,
342366
topic,
367+
namespace,
343368
this.username,
344369
this.password,
345370
handleEvents,

0 commit comments

Comments
 (0)