From a17b52b2c56b456b2f3161530aa143d8f9312ff7 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Fri, 1 Dec 2023 13:00:00 -1000 Subject: [PATCH] feat: Add new Redis caching to queries --- README.md | 25 +++++++++++++++- bun.lockb | Bin 343464 -> 345808 bytes config/config.example.toml | 11 +++++-- index.ts | 7 +++++ package.json | 3 ++ utils/config.ts | 16 +++++++++- utils/redis.ts | 60 +++++++++++++++++++++++++++++++++++++ 7 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 utils/redis.ts diff --git a/README.md b/README.md index 6d3a627a..b23635cf 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,14 @@ This is a project to create a federated social network based on the [Lysand](https://lysand.org) protocol. It is currently in alpha phase, with basic federation and API support. -This project aims to be a fully featured social network, with a focus on privacy and security. It will implement the Mastodon API for support with clients that already support Mastodon or Pleroma. +This project aims to be a fully featured social network, with a focus on privacy, security, and performance. It will implement the Mastodon API for support with clients that already support Mastodon or Pleroma. > **Note:** This project is not affiliated with Mastodon or Pleroma, and is not a fork of either project. It is a new project built from the ground up. ## Features - [x] Inbound federation +- [x] Hyper fast (thousands of HTTP requests per second) - [x] S3 or local media storage - [x] Deduplication of uploaded files - [x] Federation limits @@ -42,6 +43,28 @@ TOKEN=token_here bun benchmark:timeline The `request_count` variable is optional and defaults to 100. `TOKEN` is your personal user token, used to login to the API. +On a quad-core laptop: + +``` +$ bun run benchmarks/timelines.ts 100 +✓ All requests succeeded +✓ 100 requests fulfilled in 0.12611s +``` + +``` +$ bun run benchmarks/timelines.ts 1000 +✓ All requests succeeded +✓ 1000 requests fulfilled in 0.90925s +``` + +``` +$ bun run benchmarks/timelines.ts 10000 +✓ All requests succeeded +✓ 10000 requests fulfilled in 12.44852s +``` + +Lysand is extremely fast and can handle tens of thousands of HTTP requests per second on a good server. + ## How do I run it? ### Requirements diff --git a/bun.lockb b/bun.lockb index 0f28a8644432d21b8507a8007bfbb11d73de62e7..2cfe188606c5449d2ac4dc6e86915b3146d539f4 100755 GIT binary patch delta 68274 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%0DLnxLdjnSW1ROB? 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 elaK$bo0p diff --git a/config/config.example.toml b/config/config.example.toml index 8c8e92bd..603eb05a 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -7,9 +7,16 @@ database = "lysand" [redis.queue] host = "localhost" -post = 6379 +port = 6379 password = "" -# database = 0 +database = 0 + +[redis.cache] +host = "localhost" +port = 6379 +password = "" +database = 1 +enabled = false [http] base_url = "https://lysand.social" diff --git a/index.ts b/index.ts index ce7ababe..38a9de04 100644 --- a/index.ts +++ b/index.ts @@ -11,6 +11,7 @@ import { mkdir } from "fs/promises"; import { client } from "~database/datasource"; import type { PrismaClientInitializationError } from "@prisma/client/runtime/library"; import { HookTypes, Server } from "~plugins/types"; +import { initializeRedisCache } from "@redis"; const timeAtStart = performance.now(); const server = new Server(); @@ -33,6 +34,12 @@ if (!(await requests_log.exists())) { await Bun.write(process.cwd() + "/logs/requests.log", ""); } +const redisCache = await initializeRedisCache(); + +if (redisCache) { + client.$use(redisCache); +} + // Check if database is reachable let postCount = 0; try { diff --git a/package.json b/package.json index 90da5362..224545b0 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "@microsoft/eslint-formatter-sarif": "^3.0.0", "@types/cli-table": "^0.3.4", "@types/html-to-text": "^9.0.4", + "@types/ioredis": "^5.0.0", "@types/jsonld": "^1.5.13", "@typescript-eslint/eslint-plugin": "^6.13.1", "@typescript-eslint/parser": "^6.13.1", @@ -78,12 +79,14 @@ "cli-table": "^0.3.11", "eventemitter3": "^5.0.1", "html-to-text": "^9.0.5", + "ioredis": "^5.3.2", "ip-matching": "^2.1.2", "iso-639-1": "^3.1.0", "isomorphic-dompurify": "^1.10.0", "jsonld": "^8.3.1", "marked": "^9.1.2", "prisma": "^5.6.0", + "prisma-redis-middleware": "^4.8.0", "semver": "^7.5.4", "sharp": "^0.33.0-rc.2" } diff --git a/utils/config.ts b/utils/config.ts index eddec0b6..92553c16 100644 --- a/utils/config.ts +++ b/utils/config.ts @@ -16,6 +16,13 @@ export interface ConfigType { password: string; database: number | null; }; + cache: { + host: string; + port: number; + password: string; + database: number | null; + enabled: boolean; + }; }; http: { @@ -159,7 +166,14 @@ export const configDefaults: ConfigType = { host: "localhost", port: 6379, password: "", - database: null, + database: 0, + }, + cache: { + host: "localhost", + port: 6379, + password: "", + database: 1, + enabled: false, }, }, instance: { diff --git a/utils/redis.ts b/utils/redis.ts new file mode 100644 index 00000000..a5715bc1 --- /dev/null +++ b/utils/redis.ts @@ -0,0 +1,60 @@ +import { getConfig } from "@config"; +import type { Prisma } from "@prisma/client"; +import chalk from "chalk"; +import Redis from "ioredis"; +import { createPrismaRedisCache } from "prisma-redis-middleware"; + +const config = getConfig(); + +const cacheRedis = config.redis.cache.enabled + ? new Redis({ + host: config.redis.cache.host, + port: Number(config.redis.cache.port), + password: config.redis.cache.password, + db: Number(config.redis.cache.database ?? 0), + }) + : null; + +cacheRedis?.on("error", e => { + console.log(e); +}); + +export { cacheRedis }; + +export const initializeRedisCache = async () => { + if (cacheRedis) { + // Test connection + try { + await cacheRedis.ping(); + } catch (e) { + console.error( + `${chalk.red(`✗`)} ${chalk.bold( + `Error while connecting to Redis` + )}` + ); + throw e; + } + + console.log(`${chalk.green(`✓`)} ${chalk.bold(`Connected to Redis`)}`); + + const cacheMiddleware: Prisma.Middleware = createPrismaRedisCache({ + storage: { + type: "redis", + options: { + client: cacheRedis, + invalidation: { + referencesTTL: 300, + }, + }, + }, + cacheTime: 300, + onError: e => { + console.error(e); + }, + }); + + return cacheMiddleware; + } + + return null; +};