mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-09 13:07:02 +03:00
Add option to cycle between multiple postgres instances
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import fs from "fs";
|
||||
import { SBSConfig } from "./types/config.model";
|
||||
import packageJson from "../package.json";
|
||||
import { isBoolean, isNumber } from "lodash";
|
||||
import { isNumber } from "lodash";
|
||||
|
||||
const isTestMode = process.env.npm_lifecycle_script === packageJson.scripts.test;
|
||||
const configFile = process.env.TEST_POSTGRES ? "ci.json"
|
||||
@@ -81,6 +81,17 @@ addDefaults(config, {
|
||||
rejectUnauthorized: false
|
||||
}
|
||||
},
|
||||
postgresReadOnly: {
|
||||
enabled: false,
|
||||
weight: 1,
|
||||
user: "",
|
||||
host: "",
|
||||
password: "",
|
||||
port: 5432,
|
||||
ssl: {
|
||||
rejectUnauthorized: false
|
||||
}
|
||||
},
|
||||
dumpDatabase: {
|
||||
enabled: false,
|
||||
minTimeBetweenMs: 180000,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { IDatabase, QueryType } from "./IDatabase";
|
||||
import { Client, Pool, PoolClient, types } from "pg";
|
||||
|
||||
import fs from "fs";
|
||||
import { CustomPostgresConfig, CustomPostgresReadOnlyConfig } from "../types/config.model";
|
||||
|
||||
// return numeric (pg_type oid=1700) as float
|
||||
types.setTypeParser(1700, function(val) {
|
||||
@@ -14,16 +15,33 @@ types.setTypeParser(20, function(val) {
|
||||
return parseInt(val, 10);
|
||||
});
|
||||
|
||||
export interface DatabaseConfig {
|
||||
dbSchemaFileName: string,
|
||||
dbSchemaFolder: string,
|
||||
fileNamePrefix: string,
|
||||
readOnly: boolean,
|
||||
createDbIfNotExists: boolean,
|
||||
postgres: CustomPostgresConfig,
|
||||
postgresReadOnly: CustomPostgresReadOnlyConfig
|
||||
}
|
||||
|
||||
export class Postgres implements IDatabase {
|
||||
private pool: Pool;
|
||||
private poolRead: Pool;
|
||||
|
||||
constructor(private config: Record<string, any>) {}
|
||||
constructor(private config: DatabaseConfig) {}
|
||||
|
||||
async init(): Promise<void> {
|
||||
this.pool = new Pool(this.config.postgres);
|
||||
this.pool.on("error", (err) => {
|
||||
const errorHandler = (err: Error) => {
|
||||
Logger.error(err.stack);
|
||||
});
|
||||
};
|
||||
this.pool.on("error", errorHandler);
|
||||
|
||||
if (this.config.postgresReadOnly) {
|
||||
this.poolRead = new Pool(this.config.postgresReadOnly);
|
||||
this.poolRead.on("error", errorHandler);
|
||||
}
|
||||
|
||||
if (!this.config.readOnly) {
|
||||
if (this.config.createDbIfNotExists) {
|
||||
@@ -60,7 +78,7 @@ export class Postgres implements IDatabase {
|
||||
|
||||
let client: PoolClient;
|
||||
try {
|
||||
client = await this.pool.connect();
|
||||
client = await this.getClient(type);
|
||||
const queryResult = await client.query({ text: query, values: params });
|
||||
|
||||
switch (type) {
|
||||
@@ -85,6 +103,15 @@ export class Postgres implements IDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
private getClient(type: string): Promise<PoolClient> {
|
||||
if (this.poolRead && (type === "get" || type === "all")
|
||||
&& Math.random() > 1 / (this.config.postgresReadOnly.weight + 1)) {
|
||||
return this.poolRead.connect();
|
||||
} else {
|
||||
return this.pool.connect();
|
||||
}
|
||||
}
|
||||
|
||||
private async createDB() {
|
||||
const client = new Client({
|
||||
...this.config.postgres,
|
||||
|
||||
@@ -19,7 +19,11 @@ if (config.mysql) {
|
||||
postgres: {
|
||||
...config.postgres,
|
||||
database: "sponsorTimes",
|
||||
}
|
||||
},
|
||||
postgresReadOnly: config.postgresReadOnly ? {
|
||||
...config.postgresReadOnly,
|
||||
database: "sponsorTimes"
|
||||
} : null
|
||||
});
|
||||
|
||||
privateDB = new Postgres({
|
||||
@@ -31,7 +35,11 @@ if (config.mysql) {
|
||||
postgres: {
|
||||
...config.postgres,
|
||||
database: "privateDB"
|
||||
}
|
||||
},
|
||||
postgresReadOnly: config.postgresReadOnly ? {
|
||||
...config.postgresReadOnly,
|
||||
database: "privateDB"
|
||||
} : null
|
||||
});
|
||||
} else {
|
||||
db = new Sqlite({
|
||||
|
||||
@@ -5,10 +5,14 @@ interface RedisConfig extends redis.RedisClientOptions {
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
interface CustomPostgresConfig extends PoolConfig {
|
||||
export interface CustomPostgresConfig extends PoolConfig {
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface CustomPostgresReadOnlyConfig extends CustomPostgresConfig {
|
||||
weight: number;
|
||||
}
|
||||
|
||||
export interface SBSConfig {
|
||||
[index: string]: any
|
||||
port: number;
|
||||
@@ -51,6 +55,7 @@ export interface SBSConfig {
|
||||
redis?: RedisConfig;
|
||||
maxRewardTimePerSegmentInSeconds?: number;
|
||||
postgres?: CustomPostgresConfig;
|
||||
postgresReadOnly?: CustomPostgresReadOnlyConfig;
|
||||
dumpDatabase?: DumpDatabase;
|
||||
diskCacheURL: string;
|
||||
crons: CronJobOptions;
|
||||
|
||||
Reference in New Issue
Block a user