mirror of
https://codeberg.org/yeentown/barkey.git
synced 2025-04-28 09:36:56 +00:00
merge: Add separate redis for rate limit (!908)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/908 Approved-by: dakkar <dakkar@thenautilus.net> Approved-by: Marie <github@yuugi.dev>
This commit is contained in:
commit
d67eefaaf5
10 changed files with 60 additions and 4 deletions
|
@ -103,6 +103,16 @@ redis:
|
|||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForRateLimit:
|
||||
# host: localhost
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
# # You can specify more ioredis options...
|
||||
# #username: example-username
|
||||
|
||||
# ┌───────────────────────────────┐
|
||||
#───┘ Fulltext search configuration └─────────────────────────────
|
||||
|
||||
|
|
|
@ -124,6 +124,16 @@ redis:
|
|||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForRateLimit:
|
||||
# host: localhost
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
# # You can specify more ioredis options...
|
||||
# #username: example-username
|
||||
|
||||
# ┌───────────────────────────────┐
|
||||
#───┘ Fulltext search configuration └─────────────────────────────
|
||||
|
||||
|
|
|
@ -171,6 +171,16 @@ redis:
|
|||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForRateLimit:
|
||||
# host: localhost
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
# # You can specify more ioredis options...
|
||||
# #username: example-username
|
||||
|
||||
# ┌───────────────────────────────┐
|
||||
#───┘ Fulltext search configuration └─────────────────────────────
|
||||
|
||||
|
|
|
@ -198,6 +198,16 @@ redis:
|
|||
# # You can specify more ioredis options...
|
||||
# #username: example-username
|
||||
|
||||
#redisForRateLimit:
|
||||
# host: localhost
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
# # You can specify more ioredis options...
|
||||
# #username: example-username
|
||||
|
||||
# ┌───────────────────────────────┐
|
||||
#───┘ Fulltext search configuration └─────────────────────────────
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ const promises = Array
|
|||
config.redisForJobQueue,
|
||||
config.redisForTimelines,
|
||||
config.redisForReactions,
|
||||
config.redisForRateLimit,
|
||||
]))
|
||||
.map(connectToRedis)
|
||||
.concat([
|
||||
|
|
|
@ -92,6 +92,14 @@ const $redisForReactions: Provider = {
|
|||
inject: [DI.config],
|
||||
};
|
||||
|
||||
const $redisForRateLimit: Provider = {
|
||||
provide: DI.redisForRateLimit,
|
||||
useFactory: (config: Config) => {
|
||||
return new Redis.Redis(config.redisForRateLimit);
|
||||
},
|
||||
inject: [DI.config],
|
||||
};
|
||||
|
||||
const $meta: Provider = {
|
||||
provide: DI.meta,
|
||||
useFactory: async (db: DataSource, redisForSub: Redis.Redis) => {
|
||||
|
@ -152,8 +160,8 @@ const $meta: Provider = {
|
|||
@Global()
|
||||
@Module({
|
||||
imports: [RepositoryModule],
|
||||
providers: [$config, $db, $meta, $meilisearch, $redis, $redisForPub, $redisForSub, $redisForTimelines, $redisForReactions],
|
||||
exports: [$config, $db, $meta, $meilisearch, $redis, $redisForPub, $redisForSub, $redisForTimelines, $redisForReactions, RepositoryModule],
|
||||
providers: [$config, $db, $meta, $meilisearch, $redis, $redisForPub, $redisForSub, $redisForTimelines, $redisForReactions, $redisForRateLimit],
|
||||
exports: [$config, $db, $meta, $meilisearch, $redis, $redisForPub, $redisForSub, $redisForTimelines, $redisForReactions, $redisForRateLimit, RepositoryModule],
|
||||
})
|
||||
export class GlobalModule implements OnApplicationShutdown {
|
||||
constructor(
|
||||
|
@ -163,6 +171,7 @@ export class GlobalModule implements OnApplicationShutdown {
|
|||
@Inject(DI.redisForSub) private redisForSub: Redis.Redis,
|
||||
@Inject(DI.redisForTimelines) private redisForTimelines: Redis.Redis,
|
||||
@Inject(DI.redisForReactions) private redisForReactions: Redis.Redis,
|
||||
@Inject(DI.redisForRateLimit) private redisForRateLimit: Redis.Redis,
|
||||
) { }
|
||||
|
||||
public async dispose(): Promise<void> {
|
||||
|
@ -176,6 +185,7 @@ export class GlobalModule implements OnApplicationShutdown {
|
|||
this.redisForSub.disconnect(),
|
||||
this.redisForTimelines.disconnect(),
|
||||
this.redisForReactions.disconnect(),
|
||||
this.redisForRateLimit.disconnect(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ type Source = {
|
|||
redisForJobQueue?: RedisOptionsSource;
|
||||
redisForTimelines?: RedisOptionsSource;
|
||||
redisForReactions?: RedisOptionsSource;
|
||||
redisForRateLimit?: RedisOptionsSource;
|
||||
fulltextSearch?: {
|
||||
provider?: FulltextSearchProvider;
|
||||
};
|
||||
|
@ -231,6 +232,7 @@ export type Config = {
|
|||
redisForJobQueue: RedisOptions & RedisOptionsSource;
|
||||
redisForTimelines: RedisOptions & RedisOptionsSource;
|
||||
redisForReactions: RedisOptions & RedisOptionsSource;
|
||||
redisForRateLimit: RedisOptions & RedisOptionsSource;
|
||||
sentryForBackend: { options: Partial<Sentry.NodeOptions>; enableNodeProfiling: boolean; } | undefined;
|
||||
sentryForFrontend: { options: Partial<Sentry.NodeOptions> } | undefined;
|
||||
perChannelMaxNoteCacheCount: number;
|
||||
|
@ -345,6 +347,7 @@ export function loadConfig(): Config {
|
|||
redisForJobQueue: config.redisForJobQueue ? convertRedisOptions(config.redisForJobQueue, host) : redis,
|
||||
redisForTimelines: config.redisForTimelines ? convertRedisOptions(config.redisForTimelines, host) : redis,
|
||||
redisForReactions: config.redisForReactions ? convertRedisOptions(config.redisForReactions, host) : redis,
|
||||
redisForRateLimit: config.redisForRateLimit ? convertRedisOptions(config.redisForRateLimit, host) : redis,
|
||||
sentryForBackend: config.sentryForBackend,
|
||||
sentryForFrontend: config.sentryForFrontend,
|
||||
id: config.id,
|
||||
|
@ -535,7 +538,7 @@ function applyEnvOverrides(config: Source) {
|
|||
_apply_top(['db', ['host', 'port', 'db', 'user', 'pass', 'disableCache']]);
|
||||
_apply_top(['dbSlaves', Array.from((config.dbSlaves ?? []).keys()), ['host', 'port', 'db', 'user', 'pass']]);
|
||||
_apply_top([
|
||||
['redis', 'redisForPubsub', 'redisForJobQueue', 'redisForTimelines', 'redisForReactions'],
|
||||
['redis', 'redisForPubsub', 'redisForJobQueue', 'redisForTimelines', 'redisForReactions', 'redisForRateLimit'],
|
||||
['host', 'port', 'username', 'pass', 'db', 'prefix'],
|
||||
]);
|
||||
_apply_top(['fulltextSearch', 'provider']);
|
||||
|
|
|
@ -13,6 +13,7 @@ export const DI = {
|
|||
redisForSub: Symbol('redisForSub'),
|
||||
redisForTimelines: Symbol('redisForTimelines'),
|
||||
redisForReactions: Symbol('redisForReactions'),
|
||||
redisForRateLimit: Symbol('redisForRateLimit'),
|
||||
|
||||
//#region Repositories
|
||||
usersRepository: Symbol('usersRepository'),
|
||||
|
|
|
@ -39,6 +39,7 @@ The first call is read-only, while the others perform at least one write operati
|
|||
Two integer keys are stored per client/subject, and both expire together after the maximum duration of the limit.
|
||||
While performance has not been formally tested, it's expected that SkRateLimiterService has an impact roughly on par with the legacy RateLimiterService.
|
||||
Redis memory usage should be notably lower due to the reduced number of keys and avoidance of set / array constructions.
|
||||
If redis load does become a concern, then a dedicated node can be assigned via the `redisForRateLimit` config setting.
|
||||
|
||||
## Concurrency and Multi-Node Correctness
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ export class SkRateLimiterService {
|
|||
@Inject('TimeService')
|
||||
private readonly timeService: TimeService,
|
||||
|
||||
@Inject(DI.redis)
|
||||
@Inject(DI.redisForRateLimit)
|
||||
private readonly redisClient: Redis.Redis,
|
||||
|
||||
@Inject('RoleService')
|
||||
|
|
Loading…
Add table
Reference in a new issue