chore: simplify referral codes (#28491)
This commit is contained in:
@@ -2,6 +2,7 @@ import { SECRET } from "./secret"
|
|||||||
import { domain } from "./stage"
|
import { domain } from "./stage"
|
||||||
|
|
||||||
const description = "Managed by SST (Don't edit in Honeycomb UI)"
|
const description = "Managed by SST (Don't edit in Honeycomb UI)"
|
||||||
|
const alertsDisabled = $app.stage !== "production"
|
||||||
|
|
||||||
const webhookRecipient = new honeycomb.WebhookRecipient("DiscordAlerts", {
|
const webhookRecipient = new honeycomb.WebhookRecipient("DiscordAlerts", {
|
||||||
name: $app.stage === "production" ? "Discord Alerts" : `Discord Alerts (${$app.stage})`,
|
name: $app.stage === "production" ? "Discord Alerts" : `Discord Alerts (${$app.stage})`,
|
||||||
@@ -79,7 +80,7 @@ IF(
|
|||||||
filters,
|
filters,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
formulas: [{ name: "ERROR", expression: "IF(GTE($TOTAL, 200), DIV($FAILED, $TOTAL), 0)" }],
|
formulas: [{ name: "ERROR", expression: "IF(GTE($TOTAL, 150), DIV($FAILED, $TOTAL), 0)" }],
|
||||||
timeRange: 900,
|
timeRange: 900,
|
||||||
}).json
|
}).json
|
||||||
}
|
}
|
||||||
@@ -122,7 +123,7 @@ const providerHttpErrorsQuery = () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
formulas: [
|
formulas: [
|
||||||
{ name: "ERROR", expression: "IF(GTE(SUM($SUCCESS, $FAILED), 200), DIV($FAILED, SUM($SUCCESS, $FAILED)), 0)" },
|
{ name: "ERROR", expression: "IF(GTE(SUM($SUCCESS, $FAILED), 150), DIV($FAILED, SUM($SUCCESS, $FAILED)), 0)" },
|
||||||
],
|
],
|
||||||
timeRange: 900,
|
timeRange: 900,
|
||||||
}).json
|
}).json
|
||||||
@@ -159,6 +160,7 @@ const modelLowTpsQuery = (product: "go" | "zen") => {
|
|||||||
new honeycomb.Trigger("IncreasedModelHttpErrorsGo", {
|
new honeycomb.Trigger("IncreasedModelHttpErrorsGo", {
|
||||||
name: "Increased Model HTTP Errors [Go]",
|
name: "Increased Model HTTP Errors [Go]",
|
||||||
description,
|
description,
|
||||||
|
disabled: alertsDisabled,
|
||||||
queryJson: modelHttpErrorsQuery("go"),
|
queryJson: modelHttpErrorsQuery("go"),
|
||||||
alertType: "on_change",
|
alertType: "on_change",
|
||||||
frequency: 300,
|
frequency: 300,
|
||||||
@@ -178,6 +180,7 @@ new honeycomb.Trigger("IncreasedModelHttpErrorsGo", {
|
|||||||
new honeycomb.Trigger("IncreasedModelHttpErrorsZen", {
|
new honeycomb.Trigger("IncreasedModelHttpErrorsZen", {
|
||||||
name: "Increased Model HTTP Errors [Zen]",
|
name: "Increased Model HTTP Errors [Zen]",
|
||||||
description,
|
description,
|
||||||
|
disabled: alertsDisabled,
|
||||||
queryJson: modelHttpErrorsQuery("zen"),
|
queryJson: modelHttpErrorsQuery("zen"),
|
||||||
alertType: "on_change",
|
alertType: "on_change",
|
||||||
frequency: 300,
|
frequency: 300,
|
||||||
@@ -197,6 +200,7 @@ new honeycomb.Trigger("IncreasedModelHttpErrorsZen", {
|
|||||||
new honeycomb.Trigger("LowModelTpsGo", {
|
new honeycomb.Trigger("LowModelTpsGo", {
|
||||||
name: "Low Model TPS [Go]",
|
name: "Low Model TPS [Go]",
|
||||||
description,
|
description,
|
||||||
|
disabled: alertsDisabled,
|
||||||
queryJson: modelLowTpsQuery("go"),
|
queryJson: modelLowTpsQuery("go"),
|
||||||
alertType: "on_change",
|
alertType: "on_change",
|
||||||
frequency: 600,
|
frequency: 600,
|
||||||
@@ -216,6 +220,7 @@ new honeycomb.Trigger("LowModelTpsGo", {
|
|||||||
new honeycomb.Trigger("LowModelTpsZen", {
|
new honeycomb.Trigger("LowModelTpsZen", {
|
||||||
name: "Low Model TPS [Zen]",
|
name: "Low Model TPS [Zen]",
|
||||||
description,
|
description,
|
||||||
|
disabled: alertsDisabled,
|
||||||
queryJson: modelLowTpsQuery("zen"),
|
queryJson: modelLowTpsQuery("zen"),
|
||||||
alertType: "on_change",
|
alertType: "on_change",
|
||||||
frequency: 600,
|
frequency: 600,
|
||||||
@@ -235,6 +240,7 @@ new honeycomb.Trigger("LowModelTpsZen", {
|
|||||||
new honeycomb.Trigger("IncreasedProviderHttpErrors", {
|
new honeycomb.Trigger("IncreasedProviderHttpErrors", {
|
||||||
name: "Increased Provider HTTP Errors",
|
name: "Increased Provider HTTP Errors",
|
||||||
description,
|
description,
|
||||||
|
disabled: alertsDisabled,
|
||||||
queryJson: providerHttpErrorsQuery(),
|
queryJson: providerHttpErrorsQuery(),
|
||||||
alertType: "on_change",
|
alertType: "on_change",
|
||||||
frequency: 300,
|
frequency: 300,
|
||||||
@@ -254,6 +260,7 @@ new honeycomb.Trigger("IncreasedProviderHttpErrors", {
|
|||||||
new honeycomb.Trigger("IncreasedFreeTierRequests", {
|
new honeycomb.Trigger("IncreasedFreeTierRequests", {
|
||||||
name: "Increased Free Tier Requests",
|
name: "Increased Free Tier Requests",
|
||||||
description,
|
description,
|
||||||
|
disabled: alertsDisabled,
|
||||||
queryJson: honeycomb.getQuerySpecificationOutput({
|
queryJson: honeycomb.getQuerySpecificationOutput({
|
||||||
calculations: [{ op: "COUNT" }],
|
calculations: [{ op: "COUNT" }],
|
||||||
filters: [
|
filters: [
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
CREATE TABLE `referral_code` (
|
||||||
|
`workspace_id` varchar(30) PRIMARY KEY,
|
||||||
|
`code` varchar(10) NOT NULL,
|
||||||
|
`time_created` timestamp(3) NOT NULL DEFAULT (now()),
|
||||||
|
`time_updated` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||||
|
`time_deleted` timestamp(3),
|
||||||
|
CONSTRAINT `code` UNIQUE INDEX(`code`)
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
DROP INDEX `referral_invitee_account_id` ON `referral`;--> statement-breakpoint
|
||||||
|
DROP INDEX `referral_code` ON `workspace`;--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX `invitee_account_id` ON `referral` (`invitee_account_id`);--> statement-breakpoint
|
||||||
|
ALTER TABLE `workspace` DROP COLUMN `referral_code`;
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ import { and, asc, eq, isNull, sql, Database } from "./drizzle"
|
|||||||
import { Actor } from "./actor"
|
import { Actor } from "./actor"
|
||||||
import { Identifier } from "./identifier"
|
import { Identifier } from "./identifier"
|
||||||
import { LiteTable } from "./schema/billing.sql"
|
import { LiteTable } from "./schema/billing.sql"
|
||||||
import { ReferralRewardTable, ReferralTable } from "./schema/referral.sql"
|
import { ReferralCodeTable, ReferralRewardTable, ReferralTable } from "./schema/referral.sql"
|
||||||
import { AuthTable } from "./schema/auth.sql"
|
import { AuthTable } from "./schema/auth.sql"
|
||||||
import { UserTable } from "./schema/user.sql"
|
import { UserTable } from "./schema/user.sql"
|
||||||
import { WorkspaceTable } from "./schema/workspace.sql"
|
import { WorkspaceTable } from "./schema/workspace.sql"
|
||||||
@@ -26,38 +26,29 @@ export namespace Referral {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function generateCode() {
|
function generateCode() {
|
||||||
return ulid().slice(-CODE_LENGTH)
|
return ulid().slice(-CODE_LENGTH).toUpperCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ensureCode(workspaceID = Actor.workspace()) {
|
async function ensureCode(workspaceID = Actor.workspace()) {
|
||||||
return Database.transaction(async (tx) => {
|
return Database.use(async (db) => {
|
||||||
const existing = await tx
|
const existing = await db
|
||||||
.select({ code: WorkspaceTable.referralCode })
|
.select({ code: ReferralCodeTable.code })
|
||||||
.from(WorkspaceTable)
|
.from(ReferralCodeTable)
|
||||||
.where(and(eq(WorkspaceTable.id, workspaceID), isNull(WorkspaceTable.timeDeleted)))
|
.where(eq(ReferralCodeTable.workspaceID, workspaceID))
|
||||||
.then((rows) => rows[0])
|
.then((rows) => rows[0])
|
||||||
if (!existing) throw new Error("Workspace not found")
|
if (existing) return { code: existing.code }
|
||||||
if (existing.code) return { code: existing.code }
|
|
||||||
|
|
||||||
for (const _ of Array.from({ length: 5 })) {
|
await db.insert(ReferralCodeTable).ignore().values({
|
||||||
await tx
|
workspaceID,
|
||||||
.update(WorkspaceTable)
|
code: generateCode(),
|
||||||
.set({ referralCode: generateCode() })
|
})
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(WorkspaceTable.id, workspaceID),
|
|
||||||
isNull(WorkspaceTable.referralCode),
|
|
||||||
isNull(WorkspaceTable.timeDeleted),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
const created = await tx
|
const created = await db
|
||||||
.select({ code: WorkspaceTable.referralCode })
|
.select({ code: ReferralCodeTable.code })
|
||||||
.from(WorkspaceTable)
|
.from(ReferralCodeTable)
|
||||||
.where(and(eq(WorkspaceTable.id, workspaceID), isNull(WorkspaceTable.timeDeleted)))
|
.where(eq(ReferralCodeTable.workspaceID, workspaceID))
|
||||||
.then((rows) => rows[0])
|
.then((rows) => rows[0])
|
||||||
if (created?.code) return { code: created.code }
|
if (created) return { code: created.code }
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error("Failed to generate referral code")
|
throw new Error("Failed to generate referral code")
|
||||||
})
|
})
|
||||||
@@ -300,9 +291,15 @@ export namespace Referral {
|
|||||||
|
|
||||||
return Database.transaction(async (tx) => {
|
return Database.transaction(async (tx) => {
|
||||||
const code = await tx
|
const code = await tx
|
||||||
.select({ workspaceID: WorkspaceTable.id })
|
.select({ workspaceID: ReferralCodeTable.workspaceID })
|
||||||
.from(WorkspaceTable)
|
.from(ReferralCodeTable)
|
||||||
.where(and(eq(WorkspaceTable.referralCode, referralCode), isNull(WorkspaceTable.timeDeleted)))
|
.innerJoin(WorkspaceTable, eq(WorkspaceTable.id, ReferralCodeTable.workspaceID))
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(ReferralCodeTable.code, referralCode),
|
||||||
|
isNull(WorkspaceTable.timeDeleted),
|
||||||
|
),
|
||||||
|
)
|
||||||
.then((rows) => rows[0])
|
.then((rows) => rows[0])
|
||||||
if (!code) throw new Error("Referral code invalid")
|
if (!code) throw new Error("Referral code invalid")
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,17 @@
|
|||||||
import { bigint, mysqlTable, primaryKey, uniqueIndex } from "drizzle-orm/mysql-core"
|
import { bigint, mysqlTable, primaryKey, uniqueIndex, varchar } from "drizzle-orm/mysql-core"
|
||||||
import { timestamps, ulid, utc, workspaceColumns } from "../drizzle/types"
|
import { timestamps, ulid, utc, workspaceColumns } from "../drizzle/types"
|
||||||
import { workspaceIndexes } from "./workspace.sql"
|
import { workspaceIndexes } from "./workspace.sql"
|
||||||
|
|
||||||
|
export const ReferralCodeTable = mysqlTable(
|
||||||
|
"referral_code",
|
||||||
|
{
|
||||||
|
workspaceID: ulid("workspace_id").notNull(),
|
||||||
|
code: varchar("code", { length: 10 }).notNull(),
|
||||||
|
...timestamps,
|
||||||
|
},
|
||||||
|
(table) => [primaryKey({ columns: [table.workspaceID] }), uniqueIndex("code").on(table.code)],
|
||||||
|
)
|
||||||
|
|
||||||
export const ReferralTable = mysqlTable(
|
export const ReferralTable = mysqlTable(
|
||||||
"referral",
|
"referral",
|
||||||
{
|
{
|
||||||
@@ -9,7 +19,7 @@ export const ReferralTable = mysqlTable(
|
|||||||
...timestamps,
|
...timestamps,
|
||||||
inviteeAccountID: ulid("invitee_account_id").notNull(),
|
inviteeAccountID: ulid("invitee_account_id").notNull(),
|
||||||
},
|
},
|
||||||
(table) => [...workspaceIndexes(table), uniqueIndex("referral_invitee_account_id").on(table.inviteeAccountID)],
|
(table) => [...workspaceIndexes(table), uniqueIndex("invitee_account_id").on(table.inviteeAccountID)],
|
||||||
)
|
)
|
||||||
|
|
||||||
export const ReferralRewardTable = mysqlTable(
|
export const ReferralRewardTable = mysqlTable(
|
||||||
|
|||||||
@@ -6,11 +6,10 @@ export const WorkspaceTable = mysqlTable(
|
|||||||
{
|
{
|
||||||
id: ulid("id").notNull().primaryKey(),
|
id: ulid("id").notNull().primaryKey(),
|
||||||
slug: varchar("slug", { length: 255 }),
|
slug: varchar("slug", { length: 255 }),
|
||||||
referralCode: varchar("referral_code", { length: 10 }),
|
|
||||||
name: varchar("name", { length: 255 }).notNull(),
|
name: varchar("name", { length: 255 }).notNull(),
|
||||||
...timestamps,
|
...timestamps,
|
||||||
},
|
},
|
||||||
(table) => [uniqueIndex("slug").on(table.slug), uniqueIndex("referral_code").on(table.referralCode)],
|
(table) => [uniqueIndex("slug").on(table.slug)],
|
||||||
)
|
)
|
||||||
|
|
||||||
export function workspaceIndexes(table: any) {
|
export function workspaceIndexes(table: any) {
|
||||||
|
|||||||
Reference in New Issue
Block a user