Add locks to allocations

This commit is contained in:
Owen
2026-05-06 15:58:51 -07:00
parent 65ee9b9544
commit b046ab7513

View File

@@ -6,6 +6,7 @@ import z from "zod";
import logger from "@server/logger"; import logger from "@server/logger";
import semver from "semver"; import semver from "semver";
import { getValidCertificatesForDomains } from "#dynamic/lib/certificates"; import { getValidCertificatesForDomains } from "#dynamic/lib/certificates";
import { lockManager } from "#dynamic/lib/lock";
interface IPRange { interface IPRange {
start: bigint; start: bigint;
@@ -327,6 +328,9 @@ export async function getNextAvailableClientSubnet(
orgId: string, orgId: string,
transaction: Transaction | typeof db = db transaction: Transaction | typeof db = db
): Promise<string> { ): Promise<string> {
return await lockManager.withLock(
`client-subnet-allocation:${orgId}`,
async () => {
const [org] = await transaction const [org] = await transaction
.select() .select()
.from(orgs) .from(orgs)
@@ -337,7 +341,9 @@ export async function getNextAvailableClientSubnet(
} }
if (!org.subnet) { if (!org.subnet) {
throw new Error(`Organization with ID ${orgId} has no subnet defined`); throw new Error(
`Organization with ID ${orgId} has no subnet defined`
);
} }
const existingAddressesSites = await transaction const existingAddressesSites = await transaction
@@ -352,7 +358,9 @@ export async function getNextAvailableClientSubnet(
address: clients.subnet address: clients.subnet
}) })
.from(clients) .from(clients)
.where(and(isNotNull(clients.subnet), eq(clients.orgId, orgId))); .where(
and(isNotNull(clients.subnet), eq(clients.orgId, orgId))
);
const addresses = [ const addresses = [
...existingAddressesSites.map( ...existingAddressesSites.map(
@@ -369,20 +377,30 @@ export async function getNextAvailableClientSubnet(
} }
return subnet; return subnet;
}
);
} }
export async function getNextAvailableAliasAddress( export async function getNextAvailableAliasAddress(
orgId: string, orgId: string,
trx: Transaction | typeof db = db trx: Transaction | typeof db = db
): Promise<string> { ): Promise<string> {
const [org] = await trx.select().from(orgs).where(eq(orgs.orgId, orgId)); return await lockManager.withLock(
`alias-address-allocation:${orgId}`,
async () => {
const [org] = await trx
.select()
.from(orgs)
.where(eq(orgs.orgId, orgId));
if (!org) { if (!org) {
throw new Error(`Organization with ID ${orgId} not found`); throw new Error(`Organization with ID ${orgId} not found`);
} }
if (!org.subnet) { if (!org.subnet) {
throw new Error(`Organization with ID ${orgId} has no subnet defined`); throw new Error(
`Organization with ID ${orgId} has no subnet defined`
);
} }
if (!org.utilitySubnet) { if (!org.utilitySubnet) {
@@ -411,7 +429,11 @@ export async function getNextAvailableAliasAddress(
`${org.utilitySubnet.split("/")[0]}/29` `${org.utilitySubnet.split("/")[0]}/29`
].filter((address) => address !== null) as string[]; ].filter((address) => address !== null) as string[];
let subnet = findNextAvailableCidr(addresses, 32, org.utilitySubnet); let subnet = findNextAvailableCidr(
addresses,
32,
org.utilitySubnet
);
if (!subnet) { if (!subnet) {
throw new Error("No available subnets remaining in space"); throw new Error("No available subnets remaining in space");
} }
@@ -420,9 +442,12 @@ export async function getNextAvailableAliasAddress(
subnet = subnet.split("/")[0]; subnet = subnet.split("/")[0];
return subnet; return subnet;
}
);
} }
export async function getNextAvailableOrgSubnet(): Promise<string> { export async function getNextAvailableOrgSubnet(): Promise<string> {
return await lockManager.withLock("org-subnet-allocation", async () => {
const existingAddresses = await db const existingAddresses = await db
.select({ .select({
subnet: orgs.subnet subnet: orgs.subnet
@@ -442,6 +467,7 @@ export async function getNextAvailableOrgSubnet(): Promise<string> {
} }
return subnet; return subnet;
});
} }
export function generateRemoteSubnets( export function generateRemoteSubnets(