fix: remove unused even-store from code base (#925)
* fix: remove unused even-store from code base * fix lock
This commit is contained in:
parent
c8bf4ab3a0
commit
8e4e36513a
30 changed files with 0 additions and 1791 deletions
7
.github/dependabot.yml
vendored
7
.github/dependabot.yml
vendored
|
@ -61,13 +61,6 @@ updates:
|
|||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/event-store"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/files"
|
||||
schedule:
|
||||
|
|
47
.pnp.cjs
generated
47
.pnp.cjs
generated
|
@ -41,10 +41,6 @@ const RAW_RUNTIME_STATE =
|
|||
"name": "@standardnotes/domain-events-infra",\
|
||||
"reference": "workspace:packages/domain-events-infra"\
|
||||
},\
|
||||
{\
|
||||
"name": "@standardnotes/event-store",\
|
||||
"reference": "workspace:packages/event-store"\
|
||||
},\
|
||||
{\
|
||||
"name": "@standardnotes/files-server",\
|
||||
"reference": "workspace:packages/files"\
|
||||
|
@ -100,7 +96,6 @@ const RAW_RUNTIME_STATE =
|
|||
["@standardnotes/domain-core", ["workspace:packages/domain-core"]],\
|
||||
["@standardnotes/domain-events", ["workspace:packages/domain-events"]],\
|
||||
["@standardnotes/domain-events-infra", ["workspace:packages/domain-events-infra"]],\
|
||||
["@standardnotes/event-store", ["workspace:packages/event-store"]],\
|
||||
["@standardnotes/files-server", ["workspace:packages/files"]],\
|
||||
["@standardnotes/home-server", ["workspace:packages/home-server"]],\
|
||||
["@standardnotes/predicates", ["workspace:packages/predicates"]],\
|
||||
|
@ -6579,38 +6574,6 @@ const RAW_RUNTIME_STATE =
|
|||
"linkType": "SOFT"\
|
||||
}]\
|
||||
]],\
|
||||
["@standardnotes/event-store", [\
|
||||
["workspace:packages/event-store", {\
|
||||
"packageLocation": "./packages/event-store/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/event-store", "workspace:packages/event-store"],\
|
||||
["@aws-sdk/client-sqs", "npm:3.427.0"],\
|
||||
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
|
||||
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
|
||||
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
|
||||
["@standardnotes/time", "workspace:packages/time"],\
|
||||
["@types/ioredis", "npm:5.0.0"],\
|
||||
["@types/jest", "npm:29.5.2"],\
|
||||
["@types/nodemailer", "npm:6.4.8"],\
|
||||
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||
["dotenv", "npm:16.1.3"],\
|
||||
["eslint", "npm:8.41.0"],\
|
||||
["eslint-plugin-prettier", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.0.0"],\
|
||||
["inversify", "npm:6.0.1"],\
|
||||
["ioredis", "npm:5.3.2"],\
|
||||
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.5.0"],\
|
||||
["mysql2", "npm:3.3.3"],\
|
||||
["prettier", "npm:3.0.3"],\
|
||||
["reflect-metadata", "npm:0.1.13"],\
|
||||
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.0"],\
|
||||
["typeorm", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.17"],\
|
||||
["typescript", "patch:typescript@npm%3A5.0.4#optional!builtin<compat/typescript>::version=5.0.4&hash=b5f058"],\
|
||||
["winston", "npm:3.9.0"]\
|
||||
],\
|
||||
"linkType": "SOFT"\
|
||||
}]\
|
||||
]],\
|
||||
["@standardnotes/features", [\
|
||||
["npm:1.59.7", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-features-npm-1.59.7-27c3e5296e-421af62d1e.zip/node_modules/@standardnotes/features/",\
|
||||
|
@ -7476,16 +7439,6 @@ const RAW_RUNTIME_STATE =
|
|||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@types/nodemailer", [\
|
||||
["npm:6.4.8", {\
|
||||
"packageLocation": "./.yarn/cache/@types-nodemailer-npm-6.4.8-04975b93f9-d5afdd77ef.zip/node_modules/@types/nodemailer/",\
|
||||
"packageDependencies": [\
|
||||
["@types/nodemailer", "npm:6.4.8"],\
|
||||
["@types/node", "npm:20.2.5"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@types/normalize-package-data", [\
|
||||
["npm:2.4.1", {\
|
||||
"packageLocation": "./.yarn/cache/@types-normalize-package-data-npm-2.4.1-c31c56ae6a-e87bccbf11.zip/node_modules/@types/normalize-package-data/",\
|
||||
|
|
Binary file not shown.
|
@ -1,32 +0,0 @@
|
|||
import { Consumer } from 'sqs-consumer'
|
||||
import { Message, SQSClient } from '@aws-sdk/client-sqs'
|
||||
import {
|
||||
DomainEventMessageHandlerInterface,
|
||||
DomainEventSubscriberFactoryInterface,
|
||||
DomainEventSubscriberInterface,
|
||||
} from '@standardnotes/domain-events'
|
||||
|
||||
export class SQSDomainEventSubscriberFactory implements DomainEventSubscriberFactoryInterface {
|
||||
constructor(
|
||||
private sqs: SQSClient,
|
||||
private queueUrl: string,
|
||||
private domainEventMessageHandler: DomainEventMessageHandlerInterface,
|
||||
) {}
|
||||
|
||||
create(): DomainEventSubscriberInterface {
|
||||
const sqsConsumer = Consumer.create({
|
||||
attributeNames: ['All'],
|
||||
messageAttributeNames: ['All'],
|
||||
queueUrl: this.queueUrl,
|
||||
sqs: this.sqs,
|
||||
handleMessage:
|
||||
/* istanbul ignore next */
|
||||
async (message: Message) => await this.domainEventMessageHandler.handleMessage(<string>message.Body),
|
||||
})
|
||||
|
||||
sqsConsumer.on('error', this.domainEventMessageHandler.handleError.bind(this.domainEventMessageHandler))
|
||||
sqsConsumer.on('processing_error', this.domainEventMessageHandler.handleError.bind(this.domainEventMessageHandler))
|
||||
|
||||
return sqsConsumer
|
||||
}
|
||||
}
|
|
@ -14,6 +14,5 @@ export * from './SNS/SNSOpenTelemetryDomainEventPublisher'
|
|||
|
||||
export * from './SQS/SQSBounceNotificiationHandler'
|
||||
export * from './SQS/SQSDomainEventSubscriber'
|
||||
export * from './SQS/SQSDomainEventSubscriberFactory'
|
||||
export * from './SQS/SQSEventMessageHandler'
|
||||
export * from './SQS/SQSOpenTelemetryDomainEventSubscriber'
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import { DomainEventSubscriberInterface } from './DomainEventSubscriberInterface'
|
||||
|
||||
export interface DomainEventSubscriberFactoryInterface {
|
||||
create(): DomainEventSubscriberInterface
|
||||
}
|
|
@ -122,5 +122,4 @@ export * from './Handler/DomainEventMessageHandlerInterface'
|
|||
|
||||
export * from './Publisher/DomainEventPublisherInterface'
|
||||
|
||||
export * from './Subscriber/DomainEventSubscriberFactoryInterface'
|
||||
export * from './Subscriber/DomainEventSubscriberInterface'
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
LOG_LEVEL=debug
|
||||
NODE_ENV=development
|
||||
VERSION=development
|
||||
|
||||
DB_HOST=127.0.0.1
|
||||
DB_REPLICA_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_USERNAME=store
|
||||
DB_PASSWORD=changeme123
|
||||
DB_DATABASE=store
|
||||
DB_DEBUG_LEVEL=all # "all" | "query" | "schema" | "error" | "warn" | "info" | "log" | "migration"
|
||||
DB_MIGRATIONS_PATH=dist/migrations/*.js
|
||||
|
||||
SQS_QUEUE_URL=
|
||||
SQS_AWS_REGION=
|
|
@ -1,2 +0,0 @@
|
|||
dist
|
||||
test-setup.ts
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"extends": "../../.eslintrc",
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./linter.tsconfig.json"
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,17 +0,0 @@
|
|||
FROM node:20.6.1-alpine
|
||||
|
||||
RUN apk add --update \
|
||||
curl \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
ENV NODE_ENV production
|
||||
|
||||
RUN corepack enable
|
||||
|
||||
COPY ./ /workspace
|
||||
|
||||
WORKDIR /workspace/packages/event-store
|
||||
|
||||
ENTRYPOINT [ "/workspace/packages/event-store/docker/entrypoint.sh" ]
|
||||
|
||||
CMD [ "start-worker" ]
|
|
@ -1,21 +0,0 @@
|
|||
import 'reflect-metadata'
|
||||
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||
import TYPES from '../src/Bootstrap/Types'
|
||||
import { Env } from '../src/Bootstrap/Env'
|
||||
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
||||
|
||||
const container = new ContainerConfigLoader()
|
||||
void container.load().then((container) => {
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
|
||||
const logger: Logger = container.get(TYPES.Logger)
|
||||
|
||||
logger.info('Starting worker...')
|
||||
|
||||
const subscriberFactory: DomainEventSubscriberFactoryInterface = container.get(TYPES.DomainEventSubscriberFactory)
|
||||
subscriberFactory.create().start()
|
||||
})
|
|
@ -1,11 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
|
||||
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||
|
||||
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/worker.js')))
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true })
|
||||
|
||||
exports.default = index
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
COMMAND=$1 && shift 1
|
||||
|
||||
case "$COMMAND" in
|
||||
'start-worker' )
|
||||
echo "Starting Worker..."
|
||||
exec node docker/entrypoint-worker.js
|
||||
;;
|
||||
|
||||
* )
|
||||
echo "Unknown command"
|
||||
;;
|
||||
esac
|
||||
|
||||
exec "$@"
|
|
@ -1,12 +0,0 @@
|
|||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const base = require('../../jest.config')
|
||||
const { defaults: tsjPreset } = require('ts-jest/presets')
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
transform: {
|
||||
...tsjPreset.transform,
|
||||
},
|
||||
coveragePathIgnorePatterns: ['/Bootstrap/'],
|
||||
setupFilesAfterEnv: ['./test-setup.ts'],
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["dist", "test-setup.ts"]
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class initDatabase1639394147420 implements MigrationInterface {
|
||||
name = 'initDatabase1639394147420'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `events` (`uuid` varchar(36) NOT NULL, `user_identifier` varchar(255) NOT NULL, `user_identifier_type` varchar(255) NOT NULL, `event_type` varchar(255) NOT NULL, `event_payload` text NOT NULL, `timestamp` bigint NOT NULL, INDEX `index_events_on_user_identifier` (`user_identifier`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `index_events_on_user_identifier` ON `events`')
|
||||
await queryRunner.query('DROP TABLE `events`')
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
{
|
||||
"name": "@standardnotes/event-store",
|
||||
"version": "1.14.0",
|
||||
"description": "Event Store Service",
|
||||
"private": true,
|
||||
"main": "dist/src/index.js",
|
||||
"typings": "dist/src/index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rm -fr dist",
|
||||
"build": "tsc --build",
|
||||
"lint": "eslint . --ext .ts",
|
||||
"pretest": "yarn lint && yarn build",
|
||||
"test": "jest --coverage --no-cache --config=./jest.config.js --maxWorkers=50%",
|
||||
"worker": "yarn node dist/bin/worker.js"
|
||||
},
|
||||
"author": "Karol Sójko <karol@standardnotes.com>",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"devDependencies": {
|
||||
"@types/ioredis": "^5.0.0",
|
||||
"@types/jest": "^29.5.1",
|
||||
"@types/nodemailer": "^6.4.1",
|
||||
"@typescript-eslint/eslint-plugin": "^6.5.0",
|
||||
"@typescript-eslint/parser": "^6.5.0",
|
||||
"eslint": "^8.39.0",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"jest": "^29.5.0",
|
||||
"prettier": "^3.0.3",
|
||||
"ts-jest": "^29.1.0",
|
||||
"typescript": "^5.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sqs": "^3.427.0",
|
||||
"@standardnotes/domain-core": "workspace:^",
|
||||
"@standardnotes/domain-events": "workspace:*",
|
||||
"@standardnotes/domain-events-infra": "workspace:*",
|
||||
"@standardnotes/time": "workspace:*",
|
||||
"dotenv": "^16.0.1",
|
||||
"inversify": "^6.0.1",
|
||||
"ioredis": "^5.2.4",
|
||||
"mysql2": "^3.0.1",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"typeorm": "^0.3.17",
|
||||
"winston": "^3.8.1"
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
import * as winston from 'winston'
|
||||
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
|
||||
import { Container } from 'inversify'
|
||||
import { Event } from '../Domain/Event/Event'
|
||||
import { Env } from './Env'
|
||||
import TYPES from './Types'
|
||||
import {
|
||||
DomainEventHandlerInterface,
|
||||
DomainEventMessageHandlerInterface,
|
||||
DomainEventSubscriberFactoryInterface,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { SQSDomainEventSubscriberFactory, SQSEventMessageHandler } from '@standardnotes/domain-events-infra'
|
||||
import { Timer, TimerInterface } from '@standardnotes/time'
|
||||
import { EventHandler } from '../Domain/Handler/EventHandler'
|
||||
import { AppDataSource } from './DataSource'
|
||||
import { Repository } from 'typeorm'
|
||||
|
||||
export class ContainerConfigLoader {
|
||||
async load(): Promise<Container> {
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
|
||||
const container = new Container()
|
||||
|
||||
await AppDataSource.initialize()
|
||||
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
const sqsConfig: SQSClientConfig = {
|
||||
region: env.get('SQS_AWS_REGION', true),
|
||||
}
|
||||
if (env.get('SQS_ENDPOINT', true)) {
|
||||
sqsConfig.endpoint = env.get('SQS_ENDPOINT', true)
|
||||
}
|
||||
if (env.get('SQS_ACCESS_KEY_ID', true) && env.get('SQS_SECRET_ACCESS_KEY', true)) {
|
||||
sqsConfig.credentials = {
|
||||
accessKeyId: env.get('SQS_ACCESS_KEY_ID', true),
|
||||
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
|
||||
}
|
||||
}
|
||||
container.bind<SQSClient>(TYPES.SQS).toConstantValue(new SQSClient(sqsConfig))
|
||||
}
|
||||
|
||||
const logger = winston.createLogger({
|
||||
level: env.get('LOG_LEVEL', true) || 'info',
|
||||
format: winston.format.combine(winston.format.splat(), winston.format.json()),
|
||||
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL', true) || 'info' })],
|
||||
})
|
||||
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(logger)
|
||||
|
||||
container.bind<TimerInterface>(TYPES.Timer).toConstantValue(new Timer())
|
||||
|
||||
// env vars
|
||||
container.bind(TYPES.SQS_AWS_REGION).toConstantValue(env.get('SQS_AWS_REGION'))
|
||||
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
|
||||
|
||||
// ORM
|
||||
container.bind<Repository<Event>>(TYPES.ORMEventRepository).toConstantValue(AppDataSource.getRepository(Event))
|
||||
|
||||
// Handlers
|
||||
container.bind<EventHandler>(TYPES.EventHandler).to(EventHandler)
|
||||
|
||||
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
||||
['USER_REGISTERED', container.get(TYPES.EventHandler)],
|
||||
['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['SUBSCRIPTION_PURCHASED', container.get(TYPES.EventHandler)],
|
||||
['SUBSCRIPTION_CANCELLED', container.get(TYPES.EventHandler)],
|
||||
['SUBSCRIPTION_RENEWED', container.get(TYPES.EventHandler)],
|
||||
['SUBSCRIPTION_REFUNDED', container.get(TYPES.EventHandler)],
|
||||
['SUBSCRIPTION_SYNC_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['SUBSCRIPTION_EXPIRED', container.get(TYPES.EventHandler)],
|
||||
['EXTENSION_KEY_GRANTED', container.get(TYPES.EventHandler)],
|
||||
['SUBSCRIPTION_REASSIGNED', container.get(TYPES.EventHandler)],
|
||||
['USER_EMAIL_CHANGED', container.get(TYPES.EventHandler)],
|
||||
['FILE_UPLOADED', container.get(TYPES.EventHandler)],
|
||||
['FILE_REMOVED', container.get(TYPES.EventHandler)],
|
||||
['LISTED_ACCOUNT_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['LISTED_ACCOUNT_CREATED', container.get(TYPES.EventHandler)],
|
||||
['LISTED_ACCOUNT_DELETED', container.get(TYPES.EventHandler)],
|
||||
['EMAIL_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['EMAIL_SENT', container.get(TYPES.EventHandler)],
|
||||
['SHARED_SUBSCRIPTION_INVITATION_CREATED', container.get(TYPES.EventHandler)],
|
||||
['EMAIL_BACKUP_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['PAYMENT_FAILED', container.get(TYPES.EventHandler)],
|
||||
['PAYMENT_SUCCESS', container.get(TYPES.EventHandler)],
|
||||
['SUBSCRIPTION_REVERT_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['REFUND_PROCESSED', container.get(TYPES.EventHandler)],
|
||||
['DISCOUNT_APPLY_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['DISCOUNT_WITHDRAW_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['SUBSCRIPTION_REACTIVATED', container.get(TYPES.EventHandler)],
|
||||
['EXIT_DISCOUNT_APPLY_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['EXIT_DISCOUNT_APPLIED', container.get(TYPES.EventHandler)],
|
||||
['EXIT_DISCOUNT_WITHDRAW_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
])
|
||||
|
||||
container
|
||||
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
||||
.toConstantValue(new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Logger)))
|
||||
container
|
||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
||||
.toConstantValue(
|
||||
new SQSDomainEventSubscriberFactory(
|
||||
container.get(TYPES.SQS),
|
||||
container.get(TYPES.SQS_QUEUE_URL),
|
||||
container.get(TYPES.DomainEventMessageHandler),
|
||||
),
|
||||
)
|
||||
|
||||
return container
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
import { DataSource, LoggerOptions } from 'typeorm'
|
||||
import { Event } from '../Domain/Event/Event'
|
||||
import { Env } from './Env'
|
||||
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
|
||||
const maxQueryExecutionTime = env.get('DB_MAX_QUERY_EXECUTION_TIME', true)
|
||||
? +env.get('DB_MAX_QUERY_EXECUTION_TIME', true)
|
||||
: 45_000
|
||||
|
||||
const inReplicaMode = env.get('DB_REPLICA_HOST', true) ? true : false
|
||||
|
||||
const replicationConfig = {
|
||||
master: {
|
||||
host: env.get('DB_HOST'),
|
||||
port: parseInt(env.get('DB_PORT')),
|
||||
username: env.get('DB_USERNAME'),
|
||||
password: env.get('DB_PASSWORD'),
|
||||
database: env.get('DB_DATABASE'),
|
||||
},
|
||||
slaves: [
|
||||
{
|
||||
host: env.get('DB_REPLICA_HOST', true),
|
||||
port: parseInt(env.get('DB_PORT')),
|
||||
username: env.get('DB_USERNAME'),
|
||||
password: env.get('DB_PASSWORD'),
|
||||
database: env.get('DB_DATABASE'),
|
||||
},
|
||||
],
|
||||
removeNodeErrorCount: 10,
|
||||
restoreNodeTimeout: 5,
|
||||
}
|
||||
|
||||
export const AppDataSource = new DataSource({
|
||||
type: 'mysql',
|
||||
charset: 'utf8mb4',
|
||||
supportBigNumbers: true,
|
||||
bigNumberStrings: false,
|
||||
maxQueryExecutionTime,
|
||||
replication: inReplicaMode ? replicationConfig : undefined,
|
||||
host: inReplicaMode ? undefined : env.get('DB_HOST'),
|
||||
port: inReplicaMode ? undefined : parseInt(env.get('DB_PORT')),
|
||||
username: inReplicaMode ? undefined : env.get('DB_USERNAME'),
|
||||
password: inReplicaMode ? undefined : env.get('DB_PASSWORD'),
|
||||
database: inReplicaMode ? undefined : env.get('DB_DATABASE'),
|
||||
entities: [Event],
|
||||
migrations: [env.get('DB_MIGRATIONS_PATH', true) ?? 'dist/migrations/*.js'],
|
||||
migrationsRun: true,
|
||||
logging: <LoggerOptions>env.get('DB_DEBUG_LEVEL'),
|
||||
})
|
|
@ -1,9 +0,0 @@
|
|||
import { AbstractEnv } from '@standardnotes/domain-core'
|
||||
import { config, DotenvParseOutput } from 'dotenv'
|
||||
|
||||
export class Env extends AbstractEnv {
|
||||
load(): void {
|
||||
const output = config()
|
||||
this.env = <DotenvParseOutput>output.parsed
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
const TYPES = {
|
||||
Logger: Symbol.for('Logger'),
|
||||
SQS: Symbol.for('SQS'),
|
||||
// env vars
|
||||
SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'),
|
||||
SQS_AWS_REGION: Symbol.for('SQS_AWS_REGION'),
|
||||
// Handlers
|
||||
DomainEventSubscriberFactory: Symbol.for('DomainEventSubscriberFactory'),
|
||||
DomainEventMessageHandler: Symbol.for('DomainEventMessageHandler'),
|
||||
EventHandler: Symbol.for('EventHandler'),
|
||||
// ORM
|
||||
ORMEventRepository: Symbol.for('ORMEventRepository'),
|
||||
// Services
|
||||
Timer: Symbol.for('Timer'),
|
||||
}
|
||||
|
||||
export default TYPES
|
|
@ -1,38 +0,0 @@
|
|||
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'
|
||||
|
||||
@Entity({ name: 'events' })
|
||||
export class Event {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
declare uuid: string
|
||||
|
||||
@Column({
|
||||
name: 'user_identifier',
|
||||
length: 255,
|
||||
})
|
||||
@Index('index_events_on_user_identifier')
|
||||
declare userIdentifier: string
|
||||
|
||||
@Column({
|
||||
name: 'user_identifier_type',
|
||||
length: 255,
|
||||
})
|
||||
declare userIdentifierType: string
|
||||
|
||||
@Column({
|
||||
name: 'event_type',
|
||||
length: 255,
|
||||
})
|
||||
declare eventType: string
|
||||
|
||||
@Column({
|
||||
name: 'event_payload',
|
||||
type: 'text',
|
||||
})
|
||||
declare eventPayload: string
|
||||
|
||||
@Column({
|
||||
name: 'timestamp',
|
||||
type: 'bigint',
|
||||
})
|
||||
declare timestamp: number
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
import 'reflect-metadata'
|
||||
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
import { Repository } from 'typeorm'
|
||||
import { EventHandler } from './EventHandler'
|
||||
import { Event } from '../Event/Event'
|
||||
import { Logger } from 'winston'
|
||||
import { DomainEventInterface } from '@standardnotes/domain-events'
|
||||
|
||||
describe('EventHandler', () => {
|
||||
let timer: TimerInterface
|
||||
let repository: Repository<Event>
|
||||
let logger: Logger
|
||||
|
||||
const createHandler = () => new EventHandler(timer, repository, logger)
|
||||
|
||||
beforeEach(() => {
|
||||
timer = {} as jest.Mocked<TimerInterface>
|
||||
timer.convertStringDateToMicroseconds = jest.fn().mockReturnValue(1)
|
||||
|
||||
repository = {} as jest.Mocked<Repository<Event>>
|
||||
repository.save = jest.fn()
|
||||
|
||||
logger = {} as jest.Mocked<Logger>
|
||||
logger.debug = jest.fn()
|
||||
logger.error = jest.fn()
|
||||
})
|
||||
|
||||
it('should persist as event in the store', async () => {
|
||||
const event = {
|
||||
type: 'test',
|
||||
createdAt: new Date(2),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: '1-2-3',
|
||||
userIdentifierType: 'uuid',
|
||||
},
|
||||
},
|
||||
payload: {
|
||||
foo: 'bar',
|
||||
},
|
||||
} as jest.Mocked<DomainEventInterface>
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(repository.save).toHaveBeenCalledWith({
|
||||
eventType: 'test',
|
||||
timestamp: 1,
|
||||
userIdentifier: '1-2-3',
|
||||
userIdentifierType: 'uuid',
|
||||
eventPayload: '{"foo":"bar"}',
|
||||
})
|
||||
})
|
||||
|
||||
it('should inform about failure to saven the event in the store', async () => {
|
||||
const event = {
|
||||
type: 'test',
|
||||
createdAt: new Date(2),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: '1-2-3',
|
||||
userIdentifierType: 'uuid',
|
||||
},
|
||||
},
|
||||
payload: {
|
||||
foo: 'bar',
|
||||
},
|
||||
} as jest.Mocked<DomainEventInterface>
|
||||
repository.save = jest.fn().mockImplementation(() => {
|
||||
throw new Error('Ooops')
|
||||
})
|
||||
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(logger.error).toHaveBeenCalledWith('Could not store event %O in the event store: %s', event, 'Ooops')
|
||||
})
|
||||
})
|
|
@ -1,33 +0,0 @@
|
|||
import { DomainEventHandlerInterface, DomainEventInterface } from '@standardnotes/domain-events'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Repository } from 'typeorm'
|
||||
import { Logger } from 'winston'
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { Event } from '../Event/Event'
|
||||
|
||||
@injectable()
|
||||
export class EventHandler implements DomainEventHandlerInterface {
|
||||
constructor(
|
||||
@inject(TYPES.Timer) private timer: TimerInterface,
|
||||
@inject(TYPES.ORMEventRepository) private eventRepository: Repository<Event>,
|
||||
@inject(TYPES.Logger) private logger: Logger,
|
||||
) {}
|
||||
|
||||
async handle(event: DomainEventInterface): Promise<void> {
|
||||
this.logger.debug('Handling event: %O', event)
|
||||
|
||||
try {
|
||||
const storedEvent = new Event()
|
||||
storedEvent.eventType = event.type
|
||||
storedEvent.userIdentifier = event.meta.correlation.userIdentifier
|
||||
storedEvent.userIdentifierType = event.meta.correlation.userIdentifierType
|
||||
storedEvent.eventPayload = JSON.stringify(event.payload)
|
||||
storedEvent.timestamp = this.timer.convertStringDateToMicroseconds(event.createdAt.toString())
|
||||
|
||||
await this.eventRepository.save(storedEvent)
|
||||
} catch (error) {
|
||||
this.logger.error('Could not store event %O in the event store: %s', event, (error as Error).message)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"outDir": "./dist",
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"bin/**/*",
|
||||
"migrations/**/*",
|
||||
],
|
||||
"references": []
|
||||
}
|
|
@ -44,9 +44,6 @@
|
|||
{
|
||||
"path": "./packages/domain-events-infra"
|
||||
},
|
||||
{
|
||||
"path": "./packages/event-store"
|
||||
},
|
||||
{
|
||||
"path": "./packages/files"
|
||||
},
|
||||
|
|
39
yarn.lock
39
yarn.lock
|
@ -5442,36 +5442,6 @@ __metadata:
|
|||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@standardnotes/event-store@workspace:packages/event-store":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@standardnotes/event-store@workspace:packages/event-store"
|
||||
dependencies:
|
||||
"@aws-sdk/client-sqs": "npm:^3.427.0"
|
||||
"@standardnotes/domain-core": "workspace:^"
|
||||
"@standardnotes/domain-events": "workspace:*"
|
||||
"@standardnotes/domain-events-infra": "workspace:*"
|
||||
"@standardnotes/time": "workspace:*"
|
||||
"@types/ioredis": "npm:^5.0.0"
|
||||
"@types/jest": "npm:^29.5.1"
|
||||
"@types/nodemailer": "npm:^6.4.1"
|
||||
"@typescript-eslint/eslint-plugin": "npm:^6.5.0"
|
||||
"@typescript-eslint/parser": "npm:^6.5.0"
|
||||
dotenv: "npm:^16.0.1"
|
||||
eslint: "npm:^8.39.0"
|
||||
eslint-plugin-prettier: "npm:^5.0.0"
|
||||
inversify: "npm:^6.0.1"
|
||||
ioredis: "npm:^5.2.4"
|
||||
jest: "npm:^29.5.0"
|
||||
mysql2: "npm:^3.0.1"
|
||||
prettier: "npm:^3.0.3"
|
||||
reflect-metadata: "npm:0.1.13"
|
||||
ts-jest: "npm:^29.1.0"
|
||||
typeorm: "npm:^0.3.17"
|
||||
typescript: "npm:^5.0.4"
|
||||
winston: "npm:^3.8.1"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@standardnotes/features@npm:1.59.7, @standardnotes/features@npm:^1.59.7":
|
||||
version: 1.59.7
|
||||
resolution: "@standardnotes/features@npm:1.59.7"
|
||||
|
@ -6257,15 +6227,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/nodemailer@npm:^6.4.1":
|
||||
version: 6.4.8
|
||||
resolution: "@types/nodemailer@npm:6.4.8"
|
||||
dependencies:
|
||||
"@types/node": "npm:*"
|
||||
checksum: d5afdd77ef05d207438d124fa0a221ed6c062c4df6c624d3966252ba7da3ab6dd23f1e3423818cc992dc85e129f4a36db601eac46c932b78096b112f61a03814
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/normalize-package-data@npm:^2.4.0":
|
||||
version: 2.4.1
|
||||
resolution: "@types/normalize-package-data@npm:2.4.1"
|
||||
|
|
Loading…
Reference in a new issue