Skip to content

Commit

Permalink
IMN-796 Add scaffold for catalog-platformstate-writer (#937)
Browse files Browse the repository at this point in the history
  • Loading branch information
taglioni-r authored Oct 3, 2024
1 parent c8785c2 commit 74ff2b8
Show file tree
Hide file tree
Showing 34 changed files with 3,200 additions and 1,657 deletions.
50 changes: 50 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,56 @@ services:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example

token-generation-readmodel:
command: "-jar DynamoDBLocal.jar -inMemory -sharedDb"
image: "amazon/dynamodb-local:latest"
ports:
- 8085:8000

platform-states-table-init:
depends_on:
- token-generation-readmodel
restart: on-failure
image: amazon/aws-cli
working_dir: /home/tables
volumes:
- ./dynamo-db/schema:/home/tables
environment:
AWS_ACCESS_KEY_ID: keyid
AWS_SECRET_ACCESS_KEY: key
command: dynamodb create-table
--cli-input-json file://./platform-states.json
--endpoint-url http://token-generation-readmodel:8000
--region eu-south-1

token-generation-states-table-init:
depends_on:
- token-generation-readmodel
restart: on-failure
image: amazon/aws-cli
working_dir: /home/tables
volumes:
- ./dynamoDB-tables:/home/tables
environment:
AWS_ACCESS_KEY_ID: keyid
AWS_SECRET_ACCESS_KEY: key
command: dynamodb create-table
--cli-input-json file://./token-generation-states.json
--endpoint-url http://token-generation-readmodel:8000
--region eu-south-1

dynamodb-admin:
image: "aaronshaf/dynamodb-admin"
container_name: dynamodb-admin_token-generation-readmodel
depends_on:
- token-generation-readmodel
restart: always
ports:
- "8001:8001"
environment:
- DYNAMO_ENDPOINT=http://token-generation-readmodel:8000
- AWS_REGION=eu-west-1

# Mongo Express is a web-based MongoDB admin interface, included for convenience
mongo-express:
image: mongo-express:1.0.2-20
Expand Down
24 changes: 24 additions & 0 deletions docker/dynamo-db/schema/platform-states.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"TableName": "platform-states",
"AttributeDefinitions": [
{ "AttributeName": "PK", "AttributeType": "S" },
{ "AttributeName": "GSIPK_consumerId_eserviceId", "AttributeType": "S" },
{ "AttributeName": "GSISK_agreementTimestamp", "AttributeType": "S" }
],
"KeySchema": [{ "AttributeName": "PK", "KeyType": "HASH" }],
"GlobalSecondaryIndexes": [
{
"IndexName": "Agreement",
"KeySchema": [
{ "AttributeName": "GSIPK_consumerId_eserviceId", "KeyType": "HASH" },
{ "AttributeName": "GSISK_agreementTimestamp", "KeyType": "HASH" }
],
"Projection": { "ProjectionType": "ALL" }
}
],
"ProvisionedThroughput": {
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 5
},
"BillingMode": "PAY_PER_REQUEST"
}
59 changes: 59 additions & 0 deletions docker/dynamo-db/schema/token-generation-states.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"TableName": "token-generation-states",
"AttributeDefinitions": [
{ "AttributeName": "PK", "AttributeType": "S" },
{ "AttributeName": "GSIPK_eserviceId_descriptorId", "AttributeType": "S" },
{ "AttributeName": "GSIPK_consumerId_eserviceId", "AttributeType": "S" },
{ "AttributeName": "GSIPK_purposeId", "AttributeType": "S" },
{ "AttributeName": "GSIPK_clientId", "AttributeType": "S" },
{ "AttributeName": "GSIPK_kid", "AttributeType": "S" },
{ "AttributeName": "GSIPK_clientId_purposeId", "AttributeType": "S" }
],
"KeySchema": [{ "AttributeName": "PK", "KeyType": "HASH" }],
"GlobalSecondaryIndexes": [
{
"IndexName": "Descriptor",
"KeySchema": [
{ "AttributeName": "GSIPK_eserviceId_descriptorId", "KeyType": "HASH" }
],
"Projection": { "ProjectionType": "ALL" }
},
{
"IndexName": "Agreement",
"KeySchema": [
{
"AttributeName": "GSIPK_consumerId_eserviceId",
"KeyType": "HASH"
}
],
"Projection": { "ProjectionType": "ALL" }
},
{
"IndexName": "Purpose",
"KeySchema": [{ "AttributeName": "GSIPK_purposeId", "KeyType": "HASH" }],
"Projection": { "ProjectionType": "ALL" }
},
{
"IndexName": "Client",
"KeySchema": [{ "AttributeName": "GSIPK_clientId", "KeyType": "HASH" }],
"Projection": { "ProjectionType": "ALL" }
},
{
"IndexName": "Kid",
"KeySchema": [{ "AttributeName": "GSIPK_kid", "KeyType": "HASH" }],
"Projection": { "ProjectionType": "ALL" }
},
{
"IndexName": "ClientPurpose",
"KeySchema": [
{ "AttributeName": "GSIPK_clientId_purposeId", "KeyType": "HASH" }
],
"Projection": { "ProjectionType": "ALL" }
}
],
"ProvisionedThroughput": {
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 5
},
"BillingMode": "PAY_PER_REQUEST"
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"scripts": {
"start:catalog": "turbo start --filter pagopa-interop-catalog-process",
"start:catalog-readmodel-writer": "turbo start --filter pagopa-interop-catalog-readmodel-writer",
"start:catalog-platformstate-writer": "turbo start --filter pagopa-interop-catalog-platformstate-writer",
"start:agreement": "turbo start --filter pagopa-interop-agreement-process",
"start:agreement-readmodel-writer": "turbo start --filter pagopa-interop-agreement-readmodel-writer",
"start:agreement-email-sender": "turbo start --filter pagopa-interop-agreement-email-sender",
Expand Down
12 changes: 12 additions & 0 deletions packages/catalog-platformstate-writer/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
LOG_LEVEL=info

KAFKA_CLIENT_ID="catalog"
KAFKA_GROUP_ID="catalog-group-local"
KAFKA_BROKERS="localhost:9092"
KAFKA_DISABLE_AWS_IAM_AUTH="true"
CATALOG_TOPIC="event-store.catalog.events"
AWS_CONFIG_FILE=aws.config.local
TOKEN_GENERATION_READMODEL_TABLE_NAME_PLATFORM="platform-states"
TOKEN_GENERATION_READMODEL_TABLE_NAME_TOKEN_GENERATION="token-generation-states"

AWS_REGION="eu-south-1"
44 changes: 44 additions & 0 deletions packages/catalog-platformstate-writer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
FROM node:20.14.0-slim@sha256:5e8ac65a0231d76a388683d07ca36a9769ab019a85d85169fe28e206f7a3208e as build

RUN corepack enable

WORKDIR /app
COPY package.json /app/
COPY pnpm-lock.yaml /app/
COPY pnpm-workspace.yaml /app/

COPY ./packages/catalog-platformstate-writer/package.json /app/packages/catalog-platformstate-writer/package.json
COPY ./packages/commons/package.json /app/packages/commons/package.json
COPY ./packages/models/package.json /app/packages/models/package.json
COPY ./packages/kafka-iam-auth/package.json /app/packages/kafka-iam-auth/package.json

RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile

COPY tsconfig.json /app/
COPY turbo.json /app/
COPY ./packages/catalog-platformstate-writer /app/packages/catalog-platformstate-writer
COPY ./packages/commons /app/packages/commons
COPY ./packages/models /app/packages/models
COPY ./packages/kafka-iam-auth /app/packages/kafka-iam-auth

RUN pnpm build && \
rm -rf /app/node_modules/.modules.yaml && \
rm -rf /app/node_modules/.cache && \
mkdir /out && \
cp -a --parents -t /out \
node_modules packages/catalog-platformstate-writer/node_modules \
package*.json packages/catalog-platformstate-writer/package*.json \
packages/commons \
packages/models \
packages/kafka-iam-auth \
packages/catalog-platformstate-writer/dist && \
find /out -exec touch -h --date=@0 {} \;

FROM node:20.14.0-slim@sha256:5e8ac65a0231d76a388683d07ca36a9769ab019a85d85169fe28e206f7a3208e as final

COPY --from=build /out /app

WORKDIR /app/packages/catalog-platformstate-writer
EXPOSE 3000

CMD ["node", "."]
9 changes: 9 additions & 0 deletions packages/catalog-platformstate-writer/aws.config.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[default]
aws_access_key_id=key
aws_secret_access_key=secret
region=eu-south-1
services=local

[services local]
dynamodb=
endpoint_url=http://localhost:8085
48 changes: 48 additions & 0 deletions packages/catalog-platformstate-writer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "pagopa-interop-catalog-platformstate-writer",
"private": true,
"version": "1.0.0",
"description": "PagoPA Interoperability catalog consumer service that updates the token-generation-read-model",
"main": "dist",
"type": "module",
"scripts": {
"test": "vitest",
"test:it": "vitest integration",
"lint": "eslint . --ext .ts,.tsx",
"lint:autofix": "eslint . --ext .ts,.tsx --fix",
"format:check": "prettier --check src",
"format:write": "prettier --write src",
"start": "node --loader ts-node/esm -r 'dotenv-flow/config' --watch ./src/index.ts",
"build": "tsc",
"check": "tsc --project tsconfig.check.json"
},
"keywords": [],
"author": "",
"license": "Apache-2.0",
"devDependencies": {
"@pagopa/eslint-config": "3.0.0",
"@types/node": "20.14.6",
"@types/uuid": "9.0.8",
"date-fns": "3.6.0",
"pagopa-interop-commons-test": "workspace:*",
"prettier": "2.8.8",
"testcontainers": "10.9.0",
"ts-node": "10.9.2",
"typescript": "5.4.5",
"uuid": "10.0.0",
"vitest": "1.6.0"
},
"dependencies": {
"@aws-sdk/client-dynamodb": "3.637.0",
"@aws-sdk/util-dynamodb": "3.637.0",
"@protobuf-ts/runtime": "2.9.4",
"connection-string": "4.4.0",
"dotenv-flow": "4.1.0",
"kafka-iam-auth": "workspace:*",
"kafkajs": "2.2.4",
"pagopa-interop-commons": "workspace:*",
"pagopa-interop-models": "workspace:*",
"ts-pattern": "5.2.0",
"zod": "3.23.8"
}
}
15 changes: 15 additions & 0 deletions packages/catalog-platformstate-writer/src/config/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {
CatalogTopicConfig,
PlatformStateWriterConfig,
} from "pagopa-interop-commons";
import { z } from "zod";

export const CatalogPlatformStateWriterConfig =
PlatformStateWriterConfig.and(CatalogTopicConfig);

export type CatalogPlatformStateWriterConfig = z.infer<
typeof CatalogPlatformStateWriterConfig
>;

export const config: CatalogPlatformStateWriterConfig =
CatalogPlatformStateWriterConfig.parse(process.env);
28 changes: 28 additions & 0 deletions packages/catalog-platformstate-writer/src/consumerServiceV1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { match } from "ts-pattern";
import { EServiceEventEnvelopeV1 } from "pagopa-interop-models";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";

export async function handleMessageV1(
message: EServiceEventEnvelopeV1,
_dynamoDBClient: DynamoDBClient
): Promise<void> {
await match(message)
.with(
{ type: "EServiceAdded" },
{ type: "ClonedEServiceAdded" },
{ type: "EServiceUpdated" },
{ type: "EServiceRiskAnalysisAdded" },
{ type: "MovedAttributesFromEserviceToDescriptors" },
{ type: "EServiceRiskAnalysisUpdated" },
{ type: "EServiceWithDescriptorsDeleted" },
{ type: "EServiceDocumentUpdated" },
{ type: "EServiceDeleted" },
{ type: "EServiceDocumentAdded" },
{ type: "EServiceDocumentDeleted" },
{ type: "EServiceDescriptorAdded" },
{ type: "EServiceDescriptorUpdated" },
{ type: "EServiceRiskAnalysisDeleted" },
() => Promise.resolve()
)
.exhaustive();
}
36 changes: 36 additions & 0 deletions packages/catalog-platformstate-writer/src/consumerServiceV2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { EServiceEventEnvelopeV2 } from "pagopa-interop-models";
import { match } from "ts-pattern";

export async function handleMessageV2(
message: EServiceEventEnvelopeV2,
_dynamoDBClient: DynamoDBClient
): Promise<void> {
await match(message)
.with(
{ type: "EServiceDeleted" },
{ type: "EServiceAdded" },
{ type: "DraftEServiceUpdated" },
{ type: "EServiceCloned" },
{ type: "EServiceDescriptorAdded" },
{ type: "EServiceDraftDescriptorDeleted" },
{ type: "EServiceDraftDescriptorUpdated" },
{ type: "EServiceDescriptorQuotasUpdated" },
{ type: "EServiceDescriptorActivated" },
{ type: "EServiceDescriptorArchived" },
{ type: "EServiceDescriptorPublished" },
{ type: "EServiceDescriptorSuspended" },
{ type: "EServiceDescriptorInterfaceAdded" },
{ type: "EServiceDescriptorDocumentAdded" },
{ type: "EServiceDescriptorInterfaceUpdated" },
{ type: "EServiceDescriptorDocumentUpdated" },
{ type: "EServiceDescriptorInterfaceDeleted" },
{ type: "EServiceDescriptorDocumentDeleted" },
{ type: "EServiceRiskAnalysisAdded" },
{ type: "EServiceRiskAnalysisUpdated" },
{ type: "EServiceRiskAnalysisDeleted" },
{ type: "EServiceDescriptionUpdated" },
() => Promise.resolve()
)
.exhaustive();
}
37 changes: 37 additions & 0 deletions packages/catalog-platformstate-writer/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { EachMessagePayload } from "kafkajs";
import { logger, decodeKafkaMessage } from "pagopa-interop-commons";
import { runConsumer } from "kafka-iam-auth";
import { EServiceEvent } from "pagopa-interop-models";
import { match } from "ts-pattern";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { handleMessageV1 } from "./consumerServiceV1.js";
import { handleMessageV2 } from "./consumerServiceV2.js";
import { config } from "./config/config.js";

const dynamoDBClient = new DynamoDBClient();

async function processMessage({
message,
partition,
}: EachMessagePayload): Promise<void> {
const decodedMessage = decodeKafkaMessage(message, EServiceEvent);

const loggerInstance = logger({
serviceName: "catalog-platformstate-writer",
eventType: decodedMessage.type,
eventVersion: decodedMessage.event_version,
streamId: decodedMessage.stream_id,
correlationId: decodedMessage.correlation_id,
});

await match(decodedMessage)
.with({ event_version: 1 }, (msg) => handleMessageV1(msg, dynamoDBClient))
.with({ event_version: 2 }, (msg) => handleMessageV2(msg, dynamoDBClient))
.exhaustive();

loggerInstance.info(
`Token-generation read model was updated. Partition number: ${partition}. Offset: ${message.offset}`
);
}

await runConsumer(config, [config.catalogTopic], processMessage);
Loading

0 comments on commit 74ff2b8

Please sign in to comment.