fix: timescaleDB migration fixes and changes
This commit is contained in:
1 parent
ae85af26bf
commit
987ed64256
8 files changed
+30
-13
No files matched your search
@@ -73,7 +73,7 @@ export interface Monitor {
|
||||
gameId?: string;
|
||||
grpcServiceName?: string;
|
||||
group: string | null;
|
||||
customUserAgent?: string;
|
||||
customUserAgent?: string | null;
|
||||
geoCheckEnabled?: boolean;
|
||||
geoCheckLocations?: GeoContinent[];
|
||||
geoCheckInterval?: number;
|
||||
|
||||
@@ -45,6 +45,8 @@ const httpSchema = baseSchema.extend({
|
||||
/^[\t\x20-\x7E\x80-\xFF]*$/,
|
||||
"Only printable characters, spaces, and tabs are allowed (RFC 7230 §3.2.6)"
|
||||
)
|
||||
.transform((val) => (val.trim() === "" ? null : val.trim()))
|
||||
.nullable()
|
||||
.optional(),
|
||||
});
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import { createStatusPages, dropStatusPages } from "./0018_create_status_pages.j
|
||||
import { createAppSettings, dropAppSettings } from "./0019_create_app_settings.js";
|
||||
import { createContinuousAggregates, dropContinuousAggregates } from "./0020_create_continuous_aggregates.js";
|
||||
import { createRetentionCompression, dropRetentionCompression } from "./0021_create_retention_compression.js";
|
||||
import { addUserAgentFields, dropUserAgentFields } from "./0022_add_user_agent_fields.js";
|
||||
|
||||
const SERVICE_NAME = "TimescaleDB Migrations";
|
||||
|
||||
@@ -52,6 +53,7 @@ const migrations: MigrationEntry[] = [
|
||||
{ name: "0019_create_app_settings", up: createAppSettings, down: dropAppSettings },
|
||||
{ name: "0020_create_continuous_aggregates", up: createContinuousAggregates, down: dropContinuousAggregates },
|
||||
{ name: "0021_create_retention_compression", up: createRetentionCompression, down: dropRetentionCompression },
|
||||
{ name: "0022_add_user_agent_fields", up: addUserAgentFields, down: dropUserAgentFields },
|
||||
];
|
||||
|
||||
const ensureMigrationsTable = async (pool: Pool) => {
|
||||
|
||||
@@ -37,6 +37,7 @@ interface MonitorRow {
|
||||
game_id: string | null;
|
||||
grpc_service_name: string | null;
|
||||
monitor_group: string | null;
|
||||
custom_user_agent: string | null;
|
||||
geo_check_enabled: boolean;
|
||||
geo_check_locations: GeoContinent[] | null;
|
||||
geo_check_interval_ms: number;
|
||||
@@ -49,7 +50,7 @@ const MONITOR_COLUMNS = `id, user_id, team_id, name, description, type, status,
|
||||
interval_ms, is_active, status_window, status_window_size, status_window_threshold, uptime_percentage,
|
||||
cpu_alert_threshold, cpu_alert_counter, memory_alert_threshold, memory_alert_counter,
|
||||
disk_alert_threshold, disk_alert_counter, temp_alert_threshold, temp_alert_counter, selected_disks,
|
||||
game_id, grpc_service_name, monitor_group, geo_check_enabled, geo_check_locations, geo_check_interval_ms,
|
||||
game_id, grpc_service_name, monitor_group, custom_user_agent, geo_check_enabled, geo_check_locations, geo_check_interval_ms,
|
||||
created_at, updated_at`;
|
||||
|
||||
export class TimescaleMonitorsRepository implements IMonitorsRepository {
|
||||
@@ -62,8 +63,8 @@ export class TimescaleMonitorsRepository implements IMonitorsRepository {
|
||||
interval_ms, is_active, status_window, status_window_size, status_window_threshold,
|
||||
cpu_alert_threshold, cpu_alert_counter, memory_alert_threshold, memory_alert_counter,
|
||||
disk_alert_threshold, disk_alert_counter, temp_alert_threshold, temp_alert_counter, selected_disks,
|
||||
game_id, grpc_service_name, monitor_group, geo_check_enabled, geo_check_locations, geo_check_interval_ms)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34)
|
||||
game_id, grpc_service_name, monitor_group, custom_user_agent, geo_check_enabled, geo_check_locations, geo_check_interval_ms)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35)
|
||||
RETURNING ${MONITOR_COLUMNS}`,
|
||||
[
|
||||
userId,
|
||||
@@ -97,6 +98,7 @@ export class TimescaleMonitorsRepository implements IMonitorsRepository {
|
||||
monitor.gameId ?? null,
|
||||
monitor.grpcServiceName ?? null,
|
||||
monitor.group ?? null,
|
||||
monitor.customUserAgent ?? null,
|
||||
monitor.geoCheckEnabled ?? false,
|
||||
monitor.geoCheckLocations ?? [],
|
||||
monitor.geoCheckInterval ?? 300000,
|
||||
@@ -595,6 +597,7 @@ export class TimescaleMonitorsRepository implements IMonitorsRepository {
|
||||
["gameId", "game_id"],
|
||||
["grpcServiceName", "grpc_service_name"],
|
||||
["group", "monitor_group"],
|
||||
["customUserAgent", "custom_user_agent"],
|
||||
["geoCheckEnabled", "geo_check_enabled"],
|
||||
["geoCheckLocations", "geo_check_locations"],
|
||||
["geoCheckInterval", "geo_check_interval_ms"],
|
||||
@@ -1034,6 +1037,7 @@ export class TimescaleMonitorsRepository implements IMonitorsRepository {
|
||||
gameId: row.game_id ?? undefined,
|
||||
grpcServiceName: row.grpc_service_name ?? undefined,
|
||||
group: row.monitor_group,
|
||||
customUserAgent: row.custom_user_agent ?? undefined,
|
||||
geoCheckEnabled: row.geo_check_enabled,
|
||||
geoCheckLocations: row.geo_check_locations ?? [],
|
||||
geoCheckInterval: row.geo_check_interval_ms,
|
||||
|
||||
@@ -21,6 +21,7 @@ interface SettingsRow {
|
||||
system_email_require_tls: boolean | null;
|
||||
system_email_reject_unauthorized: boolean | null;
|
||||
show_url: boolean | null;
|
||||
default_user_agent: string | null;
|
||||
version: string | null;
|
||||
threshold_cpu_usage: number | null;
|
||||
threshold_memory_usage: number | null;
|
||||
@@ -34,7 +35,7 @@ const COLUMNS = `id, check_ttl, language, jwt_secret, pagespeed_api_key,
|
||||
system_email_host, system_email_port, system_email_address, system_email_password, system_email_user,
|
||||
system_email_connection_host, system_email_tls_servername, system_email_secure, system_email_pool,
|
||||
system_email_ignore_tls, system_email_require_tls, system_email_reject_unauthorized,
|
||||
show_url, version, threshold_cpu_usage, threshold_memory_usage, threshold_disk_usage, threshold_temperature,
|
||||
show_url, default_user_agent, version, threshold_cpu_usage, threshold_memory_usage, threshold_disk_usage, threshold_temperature,
|
||||
created_at, updated_at`;
|
||||
|
||||
export class TimescaleSettingsRepository implements ISettingsRepository {
|
||||
@@ -46,8 +47,8 @@ export class TimescaleSettingsRepository implements ISettingsRepository {
|
||||
system_email_host, system_email_port, system_email_address, system_email_password, system_email_user,
|
||||
system_email_connection_host, system_email_tls_servername, system_email_secure, system_email_pool,
|
||||
system_email_ignore_tls, system_email_require_tls, system_email_reject_unauthorized,
|
||||
show_url, version, threshold_cpu_usage, threshold_memory_usage, threshold_disk_usage, threshold_temperature)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22)
|
||||
show_url, default_user_agent, version, threshold_cpu_usage, threshold_memory_usage, threshold_disk_usage, threshold_temperature)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23)
|
||||
RETURNING ${COLUMNS}`,
|
||||
[
|
||||
settings.checkTTL ?? 30,
|
||||
@@ -67,6 +68,7 @@ export class TimescaleSettingsRepository implements ISettingsRepository {
|
||||
settings.systemEmailRequireTLS ?? false,
|
||||
settings.systemEmailRejectUnauthorized ?? true,
|
||||
settings.showURL ?? false,
|
||||
settings.defaultUserAgent ?? null,
|
||||
settings.version ?? 1,
|
||||
settings.globalThresholds?.cpu ?? null,
|
||||
settings.globalThresholds?.memory ?? null,
|
||||
@@ -113,6 +115,7 @@ export class TimescaleSettingsRepository implements ISettingsRepository {
|
||||
["systemEmailRequireTLS", "system_email_require_tls"],
|
||||
["systemEmailRejectUnauthorized", "system_email_reject_unauthorized"],
|
||||
["showURL", "show_url"],
|
||||
["defaultUserAgent", "default_user_agent"],
|
||||
["version", "version"],
|
||||
];
|
||||
|
||||
@@ -197,6 +200,7 @@ export class TimescaleSettingsRepository implements ISettingsRepository {
|
||||
systemEmailRequireTLS: row.system_email_require_tls ?? false,
|
||||
systemEmailRejectUnauthorized: row.system_email_reject_unauthorized ?? true,
|
||||
showURL: row.show_url ?? false,
|
||||
defaultUserAgent: row.default_user_agent ?? undefined,
|
||||
singleton: true,
|
||||
version: Number(row.version ?? 1),
|
||||
globalThresholds:
|
||||
|
||||
@@ -82,8 +82,13 @@ export class SettingsService implements ISettingsService {
|
||||
};
|
||||
|
||||
updateDbSettings = async (newSettings: SettingsUpdate) => {
|
||||
this.cachedDefaultUserAgent = newSettings.defaultUserAgent ?? null;
|
||||
return await this.getRepository().update(newSettings);
|
||||
const updated = await this.getRepository().update(newSettings);
|
||||
// Only refresh the cache if defaultUserAgent was actually part of the update payload.
|
||||
// `?? null` would clobber the cache on partial updates that don't include this field.
|
||||
if ("defaultUserAgent" in newSettings) {
|
||||
this.cachedDefaultUserAgent = newSettings.defaultUserAgent ?? null;
|
||||
}
|
||||
return updated;
|
||||
};
|
||||
|
||||
getDBSettings = async () => {
|
||||
|
||||
@@ -50,7 +50,7 @@ export interface Monitor {
|
||||
gameId?: string;
|
||||
grpcServiceName?: string;
|
||||
group: string | null;
|
||||
customUserAgent?: string;
|
||||
customUserAgent?: string | null;
|
||||
geoCheckEnabled?: boolean;
|
||||
geoCheckLocations?: GeoContinent[];
|
||||
geoCheckInterval?: number;
|
||||
|
||||
@@ -75,7 +75,7 @@ export const createMonitorBodyValidation = z.object({
|
||||
grpcServiceName: z.union([z.string(), z.literal("")]).default(""),
|
||||
selectedDisks: z.array(z.string()).optional(),
|
||||
group: z.union([z.string().max(50).trim(), z.null(), z.literal("")]).optional(),
|
||||
customUserAgent: httpHeaderValueSchema.optional(),
|
||||
customUserAgent: httpHeaderValueSchema.nullable().optional(),
|
||||
geoCheckEnabled: z.boolean().optional(),
|
||||
geoCheckLocations: z.array(z.enum(GeoContinents)).optional(),
|
||||
geoCheckInterval: z.number().min(300000).optional(),
|
||||
@@ -105,7 +105,7 @@ export const editMonitorBodyValidation = z.object({
|
||||
grpcServiceName: z.union([z.string(), z.literal("")]).optional(),
|
||||
selectedDisks: z.array(z.string()).optional(),
|
||||
group: z.union([z.string().max(50).trim(), z.null(), z.literal("")]).optional(),
|
||||
customUserAgent: httpHeaderValueSchema.optional(),
|
||||
customUserAgent: httpHeaderValueSchema.nullable().optional(),
|
||||
geoCheckEnabled: z.boolean().optional(),
|
||||
geoCheckLocations: z.array(z.enum(GeoContinents)).optional(),
|
||||
geoCheckInterval: z.number().min(300000).optional(),
|
||||
@@ -159,7 +159,7 @@ const importedMonitorSchema = z.object({
|
||||
gameId: z.union([z.string(), z.literal("")]).optional(),
|
||||
grpcServiceName: z.union([z.string(), z.literal("")]).default(""),
|
||||
group: z.union([z.string().max(50).trim(), z.null()]).default(null),
|
||||
customUserAgent: httpHeaderValueSchema.optional(),
|
||||
customUserAgent: httpHeaderValueSchema.nullable().optional(),
|
||||
geoCheckEnabled: z.boolean().default(false),
|
||||
geoCheckLocations: z.array(z.enum(GeoContinents)).default([]),
|
||||
geoCheckInterval: z.number().min(300000).default(300000),
|
||||
|
||||
Reference in new issue
Block a user