add new service + fix docs links

This commit is contained in:
Emily
2024-06-09 19:00:44 +02:00
parent 2720222048
commit 127be91506
25 changed files with 2241 additions and 160 deletions

3
producer/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
node_modules
start_dev.js
dist

View File

@@ -0,0 +1,17 @@
module.exports = {
apps: [
{
name: 'Producer',
port: '3000',
exec_mode: 'fork',
script: './dist/producer/src/index.js',
env: {
PORT: "8088",
REDIS_URL: "redis://litlyx.com",
REDIS_USERNAME: "default",
REDIS_PASSWORD: "cameriera",
STREAM_NAME: "lib-events"
}
}
]
}

View File

@@ -0,0 +1,23 @@
module.exports = {
apps: [
{
name: 'QueueBroker',
port: '3000',
exec_mode: 'cluster',
instances: '2',
script: './dist/broker/src/index.js',
env: {
EMAIL_SERVICE: "",
EMAIL_HOST: "",
EMAIL_USER: "",
EMAIL_PASS: "",
PORT: "",
MONGO_CONNECTION_STRING: "",
REDIS_URL: "",
REDIS_USERNAME: "",
REDIS_PASSWORD: "",
STREAM_NAME: ""
}
}
]
}

29
producer/package.json Normal file
View File

@@ -0,0 +1,29 @@
{
"dependencies": {
"cors": "^2.8.5",
"express": "^4.19.2",
"ioredis": "^5.4.1",
"redis": "^4.6.14",
"remove": "^0.1.5"
},
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/node": "^20.14.2",
"glob": "^10.4.1",
"typescript": "^5.4.5"
},
"name": "litlyx-producer",
"version": "1.0.0",
"main": "dist/index.js",
"scripts": {
"dev": "node scripts/start_dev.js",
"compile": "tsc",
"build": "ts-node scripts/build.ts",
"build_all": "scripts/build_all.bat"
},
"keywords": [],
"author": "Emily",
"license": "MIT",
"description": "Producer for Litlyx - Saves events to redis stream."
}

1666
producer/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

17
producer/scripts/build.ts Normal file
View File

@@ -0,0 +1,17 @@
import fs from 'fs';
import { globSync } from 'glob';
const tsconfigContent = fs.readFileSync('tsconfig.json', 'utf8');
const tsconfigObject = JSON.parse(tsconfigContent);
const paths = tsconfigObject.compilerOptions.paths;
const filesList = globSync('dist/**/*.js');
filesList.forEach(file => {
let raw = fs.readFileSync(file, 'utf8');
for (const path in paths) {
const deep = (file.match(/\\|\//g) || []).length;
const pathText = path.replace('*', '');
const toReplaceText = new RegExp(`"${pathText}(.*?)"`, 'g');
raw = raw.replace(toReplaceText, `"${new Array(deep - 2).fill('../').join('')}${paths[path][0].replace('*', '')}${'$1'}"`);
}
fs.writeFileSync(file, raw);
});

69
producer/src/index.ts Normal file
View File

@@ -0,0 +1,69 @@
import { requireEnv } from "../../shared/utilts/requireEnv";
import { RedisStreamService } from "@services/RedisStreamService";
import crypto from 'crypto';
import express from 'express';
import cors from 'cors';
const app = express();
app.use(cors());
const allowAnyType = () => true;
const jsonOptions = { limit: '5mb', type: allowAnyType }
const streamName = requireEnv('STREAM_NAME');
function getIPFromRequest(req: express.Request) {
const ip = req.header('X-Real-IP') || req.header('X-Forwarded-For') || '0.0.0.0';
return ip;
}
export function createSessionHash(website: string, ip: string, userAgent: string) {
const dailySalt = new Date().toLocaleDateString('it-IT');
const sessionClean = dailySalt + website + ip + userAgent;
const sessionHash = crypto.createHash('md5').update(sessionClean).digest("hex");
return sessionHash;
}
app.post('/event', express.json(jsonOptions), async (req, res) => {
try {
const ip = getIPFromRequest(req);
const sessionHash = createSessionHash(req.body.website, ip, req.body.userAgent);
await RedisStreamService.addToStream(streamName, { ...req.body, _type: 'event', sessionHash, ip });
return res.sendStatus(200);
} catch (ex: any) {
return res.status(500).json({ error: ex.message });
}
});
app.post('/visit', express.json(jsonOptions), async (req, res) => {
try {
const ip = getIPFromRequest(req);
const sessionHash = createSessionHash(req.body.website, ip, req.body.userAgent);
await RedisStreamService.addToStream(streamName, { ...req.body, _type: 'visit', sessionHash, ip });
return res.sendStatus(200);
} catch (ex: any) {
return res.status(500).json({ error: ex.message });
}
});
app.post('/keep_alive', express.json(jsonOptions), async (req, res) => {
try {
const ip = getIPFromRequest(req);
const sessionHash = createSessionHash(req.body.website, ip, req.body.userAgent);
await RedisStreamService.addToStream(streamName, { ...req.body, _type: 'keep_alive', sessionHash, ip });
return res.sendStatus(200);
} catch (ex: any) {
return res.status(500).json({ error: ex.message });
}
});
async function main() {
await RedisStreamService.connect();
app.listen(requireEnv("PORT"), () => console.log(`Listening on port ${requireEnv("PORT")}`));
}
main();

28
producer/tsconfig.json Normal file
View File

@@ -0,0 +1,28 @@
{
"compilerOptions": {
"module": "NodeNext",
"target": "ESNext",
"esModuleInterop": true,
"outDir": "dist",
"paths": {
"@schema/*": [
"../shared/schema/*"
],
"@services/*": [
"../shared/services/*"
],
"@data/*": [
"../shared/data/*"
],
"@functions/*": [
"../shared/functions/*"
]
}
},
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules"
]
}