mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-23 13:26:41 +00:00
Merge branch 'main' into dev
This commit is contained in:
@@ -46,8 +46,6 @@ export class UsageService {
|
||||
return null;
|
||||
}
|
||||
|
||||
let orgIdToUse = await this.getBillingOrg(orgId, transaction);
|
||||
|
||||
// Truncate value to 11 decimal places
|
||||
value = this.truncateValue(value);
|
||||
|
||||
@@ -59,6 +57,7 @@ export class UsageService {
|
||||
try {
|
||||
let usage;
|
||||
if (transaction) {
|
||||
const orgIdToUse = await this.getBillingOrg(orgId, transaction);
|
||||
usage = await this.internalAddUsage(
|
||||
orgIdToUse,
|
||||
featureId,
|
||||
@@ -67,6 +66,7 @@ export class UsageService {
|
||||
);
|
||||
} else {
|
||||
await db.transaction(async (trx) => {
|
||||
const orgIdToUse = await this.getBillingOrg(orgId, trx);
|
||||
usage = await this.internalAddUsage(
|
||||
orgIdToUse,
|
||||
featureId,
|
||||
@@ -92,7 +92,7 @@ export class UsageService {
|
||||
const delay = baseDelay + jitter;
|
||||
|
||||
logger.warn(
|
||||
`Deadlock detected for ${orgIdToUse}/${featureId}, retrying attempt ${attempt}/${maxRetries} after ${delay.toFixed(0)}ms`
|
||||
`Deadlock detected for ${orgId}/${featureId}, retrying attempt ${attempt}/${maxRetries} after ${delay.toFixed(0)}ms`
|
||||
);
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
@@ -100,7 +100,7 @@ export class UsageService {
|
||||
}
|
||||
|
||||
logger.error(
|
||||
`Failed to add usage for ${orgIdToUse}/${featureId} after ${attempt} attempts:`,
|
||||
`Failed to add usage for ${orgId}/${featureId} after ${attempt} attempts:`,
|
||||
error
|
||||
);
|
||||
break;
|
||||
@@ -169,7 +169,7 @@ export class UsageService {
|
||||
return;
|
||||
}
|
||||
|
||||
let orgIdToUse = await this.getBillingOrg(orgId);
|
||||
const orgIdToUse = await this.getBillingOrg(orgId);
|
||||
|
||||
try {
|
||||
// Truncate value to 11 decimal places if provided
|
||||
@@ -227,7 +227,7 @@ export class UsageService {
|
||||
orgId: string,
|
||||
featureId: FeatureId
|
||||
): Promise<string | null> {
|
||||
let orgIdToUse = await this.getBillingOrg(orgId);
|
||||
const orgIdToUse = await this.getBillingOrg(orgId);
|
||||
|
||||
const cacheKey = `customer_${orgIdToUse}_${featureId}`;
|
||||
const cached = cache.get<string>(cacheKey);
|
||||
@@ -274,7 +274,7 @@ export class UsageService {
|
||||
return null;
|
||||
}
|
||||
|
||||
let orgIdToUse = await this.getBillingOrg(orgId, trx);
|
||||
const orgIdToUse = await this.getBillingOrg(orgId, trx);
|
||||
|
||||
const usageId = `${orgIdToUse}-${featureId}`;
|
||||
|
||||
@@ -382,7 +382,7 @@ export class UsageService {
|
||||
return false;
|
||||
}
|
||||
|
||||
let orgIdToUse = await this.getBillingOrg(orgId, trx);
|
||||
const orgIdToUse = await this.getBillingOrg(orgId, trx);
|
||||
|
||||
// This method should check the current usage against the limits set for the organization
|
||||
// and kick out all of the sites on the org
|
||||
|
||||
@@ -78,7 +78,8 @@ export async function getOrgTierData(
|
||||
if (
|
||||
subscription.type === "tier1" ||
|
||||
subscription.type === "tier2" ||
|
||||
subscription.type === "tier3"
|
||||
subscription.type === "tier3" ||
|
||||
subscription.type === "enterprise"
|
||||
) {
|
||||
tier = subscription.type;
|
||||
active = true;
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
import { config } from "@server/lib/config";
|
||||
import logger from "@server/logger";
|
||||
import { redis } from "#private/lib/redis";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
const instanceId = uuidv4();
|
||||
|
||||
export class LockManager {
|
||||
/**
|
||||
@@ -33,7 +36,7 @@ export class LockManager {
|
||||
}
|
||||
|
||||
const lockValue = `${
|
||||
config.getRawConfig().gerbil.exit_node_name
|
||||
instanceId
|
||||
}:${Date.now()}`;
|
||||
const redisKey = `lock:${lockKey}`;
|
||||
|
||||
@@ -52,7 +55,7 @@ export class LockManager {
|
||||
if (result === "OK") {
|
||||
logger.debug(
|
||||
`Lock acquired: ${lockKey} by ${
|
||||
config.getRawConfig().gerbil.exit_node_name
|
||||
instanceId
|
||||
}`
|
||||
);
|
||||
return true;
|
||||
@@ -63,14 +66,14 @@ export class LockManager {
|
||||
if (
|
||||
existingValue &&
|
||||
existingValue.startsWith(
|
||||
`${config.getRawConfig().gerbil.exit_node_name}:`
|
||||
`${instanceId}:`
|
||||
)
|
||||
) {
|
||||
// Extend the lock TTL since it's the same worker
|
||||
await redis.pexpire(redisKey, ttlMs);
|
||||
logger.debug(
|
||||
`Lock extended: ${lockKey} by ${
|
||||
config.getRawConfig().gerbil.exit_node_name
|
||||
instanceId
|
||||
}`
|
||||
);
|
||||
return true;
|
||||
@@ -116,7 +119,7 @@ export class LockManager {
|
||||
local key = KEYS[1]
|
||||
local worker_prefix = ARGV[1]
|
||||
local current_value = redis.call('GET', key)
|
||||
|
||||
|
||||
if current_value and string.find(current_value, worker_prefix, 1, true) == 1 then
|
||||
return redis.call('DEL', key)
|
||||
else
|
||||
@@ -129,19 +132,19 @@ export class LockManager {
|
||||
luaScript,
|
||||
1,
|
||||
redisKey,
|
||||
`${config.getRawConfig().gerbil.exit_node_name}:`
|
||||
`${instanceId}:`
|
||||
)) as number;
|
||||
|
||||
if (result === 1) {
|
||||
logger.debug(
|
||||
`Lock released: ${lockKey} by ${
|
||||
config.getRawConfig().gerbil.exit_node_name
|
||||
instanceId
|
||||
}`
|
||||
);
|
||||
} else {
|
||||
logger.warn(
|
||||
`Lock not released - not owned by worker: ${lockKey} by ${
|
||||
config.getRawConfig().gerbil.exit_node_name
|
||||
instanceId
|
||||
}`
|
||||
);
|
||||
}
|
||||
@@ -198,7 +201,7 @@ export class LockManager {
|
||||
const ownedByMe =
|
||||
exists &&
|
||||
value!.startsWith(
|
||||
`${config.getRawConfig().gerbil.exit_node_name}:`
|
||||
`${instanceId}:`
|
||||
);
|
||||
const owner = exists ? value!.split(":")[0] : undefined;
|
||||
|
||||
@@ -233,7 +236,7 @@ export class LockManager {
|
||||
local worker_prefix = ARGV[1]
|
||||
local ttl = tonumber(ARGV[2])
|
||||
local current_value = redis.call('GET', key)
|
||||
|
||||
|
||||
if current_value and string.find(current_value, worker_prefix, 1, true) == 1 then
|
||||
return redis.call('PEXPIRE', key, ttl)
|
||||
else
|
||||
@@ -246,14 +249,14 @@ export class LockManager {
|
||||
luaScript,
|
||||
1,
|
||||
redisKey,
|
||||
`${config.getRawConfig().gerbil.exit_node_name}:`,
|
||||
`${instanceId}:`,
|
||||
ttlMs.toString()
|
||||
)) as number;
|
||||
|
||||
if (result === 1) {
|
||||
logger.debug(
|
||||
`Lock extended: ${lockKey} by ${
|
||||
config.getRawConfig().gerbil.exit_node_name
|
||||
instanceId
|
||||
} for ${ttlMs}ms`
|
||||
);
|
||||
return true;
|
||||
@@ -356,7 +359,7 @@ export class LockManager {
|
||||
(value) =>
|
||||
value &&
|
||||
value.startsWith(
|
||||
`${config.getRawConfig().gerbil.exit_node_name}:`
|
||||
`${instanceId}:`
|
||||
)
|
||||
).length;
|
||||
}
|
||||
|
||||
@@ -72,15 +72,15 @@ export const privateConfigSchema = z.object({
|
||||
db: z.int().nonnegative().optional().default(0)
|
||||
})
|
||||
)
|
||||
.optional(),
|
||||
tls: z
|
||||
.object({
|
||||
rejectUnauthorized: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.default(true)
|
||||
})
|
||||
.optional()
|
||||
// tls: z
|
||||
// .object({
|
||||
// reject_unauthorized: z
|
||||
// .boolean()
|
||||
// .optional()
|
||||
// .default(true)
|
||||
// })
|
||||
// .optional()
|
||||
})
|
||||
.optional(),
|
||||
gerbil: z
|
||||
|
||||
@@ -108,11 +108,15 @@ class RedisManager {
|
||||
port: redisConfig.port!,
|
||||
password: redisConfig.password,
|
||||
db: redisConfig.db
|
||||
// tls: {
|
||||
// rejectUnauthorized:
|
||||
// redisConfig.tls?.reject_unauthorized || false
|
||||
// }
|
||||
};
|
||||
|
||||
// Enable TLS if configured (required for AWS ElastiCache in-transit encryption)
|
||||
if (redisConfig.tls) {
|
||||
opts.tls = {
|
||||
rejectUnauthorized: redisConfig.tls.rejectUnauthorized ?? true
|
||||
};
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
@@ -130,11 +134,15 @@ class RedisManager {
|
||||
port: replica.port!,
|
||||
password: replica.password,
|
||||
db: replica.db || redisConfig.db
|
||||
// tls: {
|
||||
// rejectUnauthorized:
|
||||
// replica.tls?.reject_unauthorized || false
|
||||
// }
|
||||
};
|
||||
|
||||
// Enable TLS if configured (required for AWS ElastiCache in-transit encryption)
|
||||
if (redisConfig.tls) {
|
||||
opts.tls = {
|
||||
rejectUnauthorized: redisConfig.tls.rejectUnauthorized ?? true
|
||||
};
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,6 @@ export async function updateSiteBandwidth(
|
||||
usageService
|
||||
.checkLimitSet(
|
||||
orgId,
|
||||
|
||||
FeatureId.EGRESS_DATA_MB,
|
||||
bandwidthUsage
|
||||
)
|
||||
|
||||
@@ -2,9 +2,13 @@ import { db, dnsRecords } from "@server/db";
|
||||
import { domains, exitNodes, orgDomains, orgs, resources } from "@server/db";
|
||||
import config from "@server/lib/config";
|
||||
import { eq, ne } from "drizzle-orm";
|
||||
import logger from "@server/logger";
|
||||
import { build } from "@server/build";
|
||||
|
||||
export async function copyInConfig() {
|
||||
if (build == "saas") {
|
||||
return;
|
||||
}
|
||||
|
||||
const endpoint = config.getRawConfig().gerbil.base_endpoint;
|
||||
const listenPort = config.getRawConfig().gerbil.start_port;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import m11 from "./scriptsPg/1.14.0";
|
||||
import m12 from "./scriptsPg/1.15.0";
|
||||
import m13 from "./scriptsPg/1.15.3";
|
||||
import m14 from "./scriptsPg/1.15.4";
|
||||
import { build } from "@server/build";
|
||||
|
||||
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
|
||||
// EXCEPT FOR THE DATABASE AND THE SCHEMA
|
||||
@@ -53,6 +54,10 @@ async function run() {
|
||||
}
|
||||
|
||||
export async function runMigrations() {
|
||||
if (build == "saas") {
|
||||
console.log("Running in SaaS mode, skipping migrations...");
|
||||
return;
|
||||
}
|
||||
if (process.env.DISABLE_MIGRATIONS) {
|
||||
console.log("Migrations are disabled. Skipping...");
|
||||
return;
|
||||
|
||||
@@ -37,6 +37,7 @@ import m32 from "./scriptsSqlite/1.14.0";
|
||||
import m33 from "./scriptsSqlite/1.15.0";
|
||||
import m34 from "./scriptsSqlite/1.15.3";
|
||||
import m35 from "./scriptsSqlite/1.15.4";
|
||||
import { build } from "@server/build";
|
||||
|
||||
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
|
||||
// EXCEPT FOR THE DATABASE AND THE SCHEMA
|
||||
@@ -105,6 +106,10 @@ function backupDb() {
|
||||
}
|
||||
|
||||
export async function runMigrations() {
|
||||
if (build == "saas") {
|
||||
console.log("Running in SaaS mode, skipping migrations...");
|
||||
return;
|
||||
}
|
||||
if (process.env.DISABLE_MIGRATIONS) {
|
||||
console.log("Migrations are disabled. Skipping...");
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user