Skip to content
Snippets Groups Projects
Commit 60481361 authored by Zdravko Iliev's avatar Zdravko Iliev
Browse files

feat: implement connection micro service

parent 8052e27a
No related branches found
No related tags found
1 merge request!12feat: implement connection micro service
Pipeline #62717 passed with stages
in 8 minutes and 47 seconds
Showing
with 436 additions and 27 deletions
......@@ -39,3 +39,4 @@ Thumbs.db
#compose
compose/data
compose/dist
......@@ -2,18 +2,31 @@ import { Module } from "@nestjs/common";
import { AskerDynamicModule } from "@ocm-engine/asker";
import { ConfigModule } from "@nestjs/config";
import {
agentConfig,
agentSchema,
gatewayConfig,
gatewaySchema,
ledgersConfig,
ledgersSchema,
natsConfig,
natsSchema,
} from "@ocm-engine/config";
import Joi from "joi";
import agentConfig from "../config/agent.config";
import ledgersConfig from "../config/ledgers.config";
import validationSchema from "../config/validation";
import NatsConfig from "../config/nats.config";
const validationSchema = Joi.object({
agent: agentSchema,
ledgers: ledgersSchema,
nats: natsSchema,
gateway: gatewaySchema,
});
@Module({
imports: [
AskerDynamicModule.forRootAsync(),
ConfigModule.forRoot({
isGlobal: true,
load: [agentConfig, ledgersConfig, NatsConfig],
load: [agentConfig, ledgersConfig, natsConfig, gatewayConfig],
validationSchema,
}),
],
......
import { registerAs } from "@nestjs/config";
import { IConfAgent } from "@ocm-engine/asker";
import * as process from "process";
export default registerAs(
"agent",
(): IConfAgent => ({
agentPeerPort: parseInt(process.env.AGENT_PEER_URL.split(":")[2]),
agentPeerAddress: process.env.AGENT_PEER_URL,
agentName: process.env.AGENT_NAME,
agentKey: process.env.AGENT_KEY,
agentDidSeed: process.env.AGENT_DID_SEED,
agentDbHost: process.env.AGENT_DB_HOST,
agentDbUser: process.env.AGENT_DB_USER,
agentDbPass: process.env.AGENT_DB_PASS,
agentIsRest: process.env.AGENT_IS_REST === "true",
agentConsumerName: process.env.AGENT_CONSUMER_NAME,
agentConsumerMaxMessagess: parseInt(process.env.AGENT_MAX_MESSAGES),
agentConsumerRateLimit: parseInt(process.env.AGENT_RETE_LIMIT),
}),
);
......@@ -13,7 +13,7 @@ async function bootstrap() {
const app = await NestFactory.create(AppModule);
const globalPrefix = "api";
app.setGlobalPrefix(globalPrefix);
const port = process.env.PORT || 3001;
const port = process.env.AGENT_PORT || 3001;
app.enableShutdownHooks();
const config = new DocumentBuilder()
......
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
FROM node:18.16.0-buster-slim
RUN apt update -y && apt install python3 git make build-essential -y
WORKDIR app
COPY ./dist/apps/connection-manager .
COPY package.json yarn.lock ./
RUN yarn install
EXPOSE 8882
CMD ["node", "main.js"]
/* eslint-disable */
export default {
displayName: "connection-manager",
preset: "../../jest.preset.js",
testEnvironment: "node",
transform: {
"^.+\\.[tj]s$": ["ts-jest", { tsconfig: "<rootDir>/tsconfig.spec.json" }],
},
moduleFileExtensions: ["ts", "js", "html"],
coverageDirectory: "../../coverage/apps/connection-manager",
};
{
"name": "connection-manager",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/connection-manager/src",
"projectType": "application",
"targets": {
"build": {
"executor": "@nx/webpack:webpack",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": {
"target": "node",
"compiler": "tsc",
"outputPath": "dist/apps/connection-manager",
"main": "apps/connection-manager/src/main.ts",
"tsConfig": "apps/connection-manager/tsconfig.app.json",
"isolatedConfig": true,
"webpackConfig": "apps/connection-manager/webpack.config.js"
},
"configurations": {
"development": {},
"production": {}
}
},
"serve": {
"executor": "@nx/js:node",
"defaultConfiguration": "development",
"options": {
"buildTarget": "connection-manager:build"
},
"configurations": {
"development": {
"buildTarget": "connection-manager:build:development"
},
"production": {
"buildTarget": "connection-manager:build:production"
}
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/connection-manager/**/*.ts"]
}
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "apps/connection-manager/jest.config.ts",
"passWithNoTests": true
},
"configurations": {
"ci": {
"ci": true,
"codeCoverage": true
}
}
}
},
"tags": []
}
import { Body, Controller, Logger } from "@nestjs/common";
import { ProducerService } from "@ocm-engine/nats";
import { MessagePattern, RpcException } from "@nestjs/microservices";
import { AppService } from "./app.service";
import {
ConnectionEvent,
CreateInvitationResponseDto,
GetConnectionRequestDto,
} from "@ocm-engine/dtos";
@Controller()
export class AppController {
private readonly logger: Logger = new Logger(AppController.name);
constructor(
private readonly producerService: ProducerService,
private readonly appService: AppService,
) {}
@MessagePattern("connections")
async create(
@Body()
payload: {
data: null | CreateInvitationResponseDto | GetConnectionRequestDto;
type: ConnectionEvent;
source: string;
},
): Promise<{ id: string }> {
this.logger.debug(JSON.stringify(payload, null, 2));
try {
const event = this.appService.toEvent(payload);
this.logger.debug(JSON.stringify(event, null, 2));
await this.producerService.publish<typeof payload.data>(
payload.type,
event,
);
return { id: event.id };
} catch (e) {
this.logger.debug(JSON.stringify(e, null, 2));
if (e instanceof Error) {
throw new RpcException(e.message);
}
throw new RpcException("Internal server error");
}
}
}
import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { ProducerService } from "@ocm-engine/nats";
import { ConfigModule } from "@nestjs/config";
import { cmConfig, cmSchema, natsConfig, natsSchema } from "@ocm-engine/config";
import Joi from "joi";
import { AppService } from "./app.service";
const validationSchema = Joi.object({
nats: natsSchema,
cm: cmSchema,
});
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [natsConfig, cmConfig],
validationSchema,
}),
],
controllers: [AppController],
providers: [ProducerService, AppService],
})
export class AppModule {}
import { Injectable } from "@nestjs/common";
import {
CloudEventDto,
CONNECTION_EVENTS,
ConnectionEvent,
ConnectionUnsupportedTypeError,
CreateInvitationResponseDto,
GetConnectionRequestDto,
} from "@ocm-engine/dtos";
@Injectable()
export class AppService {
toEvent = (payload: {
data: null | CreateInvitationResponseDto | GetConnectionRequestDto;
type: ConnectionEvent;
source: string;
}) => {
if (!CONNECTION_EVENTS.includes(payload.type)) {
throw new ConnectionUnsupportedTypeError();
}
const event = new CloudEventDto<typeof payload.data>();
event.subject = payload.type;
event.source = payload.source;
event.type = payload.type;
event.data = payload.data;
return event;
};
}
/**
* This is not a production server yet!
* This is only a minimal backend to get started.
*/
import { Logger } from "@nestjs/common";
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app/app.module";
import { MicroserviceOptions, Transport } from "@nestjs/microservices";
import { ConfigService } from "@nestjs/config";
import { IConnectionManager, IGateway } from "@ocm-engine/config";
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const configService = app.get(ConfigService);
const gatewayConfig = configService.get<IConnectionManager>("cm")!;
app.enableShutdownHooks();
const microservice = app.connectMicroservice<MicroserviceOptions>({
transport: Transport.TCP,
options: {
host: gatewayConfig.host,
port: gatewayConfig.port,
},
});
await app.startAllMicroservices();
app.enableShutdownHooks();
Logger.log("Application is running");
}
bootstrap();
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["node"],
"emitDecoratorMetadata": true,
"target": "es2015"
},
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
"include": ["src/**/*.ts"]
}
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"compilerOptions": {
"esModuleInterop": true
}
}
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"jest.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}
const { composePlugins, withNx } = require("@nx/webpack");
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), (config) => {
// Update the webpack config as needed here.
// e.g. `config.plugins.push(new MyPlugin())`
return config;
});
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
FROM node:18.16.0-buster-slim
RUN apt update -y && apt install python3 git make build-essential -y
WORKDIR app
COPY ./dist/apps/gateway .
COPY package.json yarn.lock ./
RUN yarn install
EXPOSE 8081
EXPOSE 8881
CMD ["node", "main.js"]
/* eslint-disable */
export default {
displayName: "gateway",
preset: "../../jest.preset.js",
testEnvironment: "node",
transform: {
"^.+\\.[tj]s$": ["ts-jest", { tsconfig: "<rootDir>/tsconfig.spec.json" }],
},
moduleFileExtensions: ["ts", "js", "html"],
coverageDirectory: "../../coverage/apps/gateway",
};
{
"name": "gateway",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/gateway/src",
"projectType": "application",
"targets": {
"build": {
"executor": "@nx/webpack:webpack",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": {
"target": "node",
"compiler": "tsc",
"outputPath": "dist/apps/gateway",
"main": "apps/gateway/src/main.ts",
"tsConfig": "apps/gateway/tsconfig.app.json",
"isolatedConfig": true,
"webpackConfig": "apps/gateway/webpack.config.js",
"transformers": [
{
"name": "@nestjs/swagger/plugin",
"options": {
"introspectComments": true
}
}
]
},
"configurations": {
"development": {},
"production": {}
}
},
"serve": {
"executor": "@nx/js:node",
"defaultConfiguration": "development",
"options": {
"buildTarget": "gateway:build"
},
"configurations": {
"development": {
"buildTarget": "gateway:build:development"
},
"production": {
"buildTarget": "gateway:build:production"
}
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/gateway/**/*.ts"]
}
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "apps/gateway/jest.config.ts",
"passWithNoTests": true
},
"configurations": {
"ci": {
"ci": true,
"codeCoverage": true
}
}
}
},
"tags": []
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment