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