mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 16:38:19 +01:00
feat: Add new Redis caching to queries
This commit is contained in:
parent
df5e8f744b
commit
a17b52b2c5
25
README.md
25
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 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.
|
> **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
|
## Features
|
||||||
|
|
||||||
- [x] Inbound federation
|
- [x] Inbound federation
|
||||||
|
- [x] Hyper fast (thousands of HTTP requests per second)
|
||||||
- [x] S3 or local media storage
|
- [x] S3 or local media storage
|
||||||
- [x] Deduplication of uploaded files
|
- [x] Deduplication of uploaded files
|
||||||
- [x] Federation limits
|
- [x] Federation limits
|
||||||
|
|
@ -42,6 +43,28 @@ TOKEN=token_here bun benchmark:timeline <request_count>
|
||||||
|
|
||||||
The `request_count` variable is optional and defaults to 100. `TOKEN` is your personal user token, used to login to the API.
|
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?
|
## How do I run it?
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,16 @@ database = "lysand"
|
||||||
|
|
||||||
[redis.queue]
|
[redis.queue]
|
||||||
host = "localhost"
|
host = "localhost"
|
||||||
post = 6379
|
port = 6379
|
||||||
password = ""
|
password = ""
|
||||||
# database = 0
|
database = 0
|
||||||
|
|
||||||
|
[redis.cache]
|
||||||
|
host = "localhost"
|
||||||
|
port = 6379
|
||||||
|
password = ""
|
||||||
|
database = 1
|
||||||
|
enabled = false
|
||||||
|
|
||||||
[http]
|
[http]
|
||||||
base_url = "https://lysand.social"
|
base_url = "https://lysand.social"
|
||||||
|
|
|
||||||
7
index.ts
7
index.ts
|
|
@ -11,6 +11,7 @@ import { mkdir } from "fs/promises";
|
||||||
import { client } from "~database/datasource";
|
import { client } from "~database/datasource";
|
||||||
import type { PrismaClientInitializationError } from "@prisma/client/runtime/library";
|
import type { PrismaClientInitializationError } from "@prisma/client/runtime/library";
|
||||||
import { HookTypes, Server } from "~plugins/types";
|
import { HookTypes, Server } from "~plugins/types";
|
||||||
|
import { initializeRedisCache } from "@redis";
|
||||||
|
|
||||||
const timeAtStart = performance.now();
|
const timeAtStart = performance.now();
|
||||||
const server = new Server();
|
const server = new Server();
|
||||||
|
|
@ -33,6 +34,12 @@ if (!(await requests_log.exists())) {
|
||||||
await Bun.write(process.cwd() + "/logs/requests.log", "");
|
await Bun.write(process.cwd() + "/logs/requests.log", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const redisCache = await initializeRedisCache();
|
||||||
|
|
||||||
|
if (redisCache) {
|
||||||
|
client.$use(redisCache);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if database is reachable
|
// Check if database is reachable
|
||||||
let postCount = 0;
|
let postCount = 0;
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
"@microsoft/eslint-formatter-sarif": "^3.0.0",
|
"@microsoft/eslint-formatter-sarif": "^3.0.0",
|
||||||
"@types/cli-table": "^0.3.4",
|
"@types/cli-table": "^0.3.4",
|
||||||
"@types/html-to-text": "^9.0.4",
|
"@types/html-to-text": "^9.0.4",
|
||||||
|
"@types/ioredis": "^5.0.0",
|
||||||
"@types/jsonld": "^1.5.13",
|
"@types/jsonld": "^1.5.13",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.13.1",
|
"@typescript-eslint/eslint-plugin": "^6.13.1",
|
||||||
"@typescript-eslint/parser": "^6.13.1",
|
"@typescript-eslint/parser": "^6.13.1",
|
||||||
|
|
@ -78,12 +79,14 @@
|
||||||
"cli-table": "^0.3.11",
|
"cli-table": "^0.3.11",
|
||||||
"eventemitter3": "^5.0.1",
|
"eventemitter3": "^5.0.1",
|
||||||
"html-to-text": "^9.0.5",
|
"html-to-text": "^9.0.5",
|
||||||
|
"ioredis": "^5.3.2",
|
||||||
"ip-matching": "^2.1.2",
|
"ip-matching": "^2.1.2",
|
||||||
"iso-639-1": "^3.1.0",
|
"iso-639-1": "^3.1.0",
|
||||||
"isomorphic-dompurify": "^1.10.0",
|
"isomorphic-dompurify": "^1.10.0",
|
||||||
"jsonld": "^8.3.1",
|
"jsonld": "^8.3.1",
|
||||||
"marked": "^9.1.2",
|
"marked": "^9.1.2",
|
||||||
"prisma": "^5.6.0",
|
"prisma": "^5.6.0",
|
||||||
|
"prisma-redis-middleware": "^4.8.0",
|
||||||
"semver": "^7.5.4",
|
"semver": "^7.5.4",
|
||||||
"sharp": "^0.33.0-rc.2"
|
"sharp": "^0.33.0-rc.2"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,13 @@ export interface ConfigType {
|
||||||
password: string;
|
password: string;
|
||||||
database: number | null;
|
database: number | null;
|
||||||
};
|
};
|
||||||
|
cache: {
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
password: string;
|
||||||
|
database: number | null;
|
||||||
|
enabled: boolean;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
http: {
|
http: {
|
||||||
|
|
@ -159,7 +166,14 @@ export const configDefaults: ConfigType = {
|
||||||
host: "localhost",
|
host: "localhost",
|
||||||
port: 6379,
|
port: 6379,
|
||||||
password: "",
|
password: "",
|
||||||
database: null,
|
database: 0,
|
||||||
|
},
|
||||||
|
cache: {
|
||||||
|
host: "localhost",
|
||||||
|
port: 6379,
|
||||||
|
password: "",
|
||||||
|
database: 1,
|
||||||
|
enabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
instance: {
|
instance: {
|
||||||
|
|
|
||||||
60
utils/redis.ts
Normal file
60
utils/redis.ts
Normal file
|
|
@ -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;
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue