Openstatus www.openstatus.dev
at 4c0f4c00a38753a5d0dfd7e7b7b7706dec6f1503 119 lines 3.5 kB view raw
1import { db, eq } from "@openstatus/db"; 2import { type WorkspacePlan, workspace } from "@openstatus/db/src/schema"; 3import { env } from "../env"; 4 5import readline from "node:readline"; 6 7// Function to prompt user for confirmation 8const askConfirmation = async (question: string): Promise<boolean> => { 9 const rl = readline.createInterface({ 10 input: process.stdin, 11 output: process.stdout, 12 }); 13 14 return new Promise((resolve) => { 15 rl.question(`${question} (y/n): `, (answer) => { 16 rl.close(); 17 resolve(answer.trim().toLowerCase() === "y"); 18 }); 19 }); 20}; 21 22/** 23 * Calculates the unix timestamp in milliseconds for a given number of days in the past. 24 * @param days The number of days to subtract from the current date. 25 * @returns The calculated unix timestamp in milliseconds. 26 */ 27function calculatePastTimestamp(days: number) { 28 const date = new Date(); 29 date.setDate(date.getDate() - days); 30 const timestamp = date.getTime(); 31 console.log(`${days}d back: ${timestamp}`); 32 return timestamp; 33} 34 35/** 36 * Get the array of workspace IDs for a given plan. 37 * @param plan The plan to filter by. 38 * @returns The array of workspace IDs. 39 */ 40async function getWorkspaceIdsByPlan(plan: WorkspacePlan) { 41 const workspaces = await db 42 .select() 43 .from(workspace) 44 .where(eq(workspace.plan, plan)) 45 .all(); 46 const workspaceIds = workspaces.map((w) => w.id); 47 console.log(`${plan}: ${workspaceIds}`); 48 return workspaceIds; 49} 50 51/** 52 * 53 * @param timestamp timestamp to delete logs before (in milliseconds) 54 * @param workspaceIds array of workspace IDs to delete logs for 55 * @param reverse allows to NOT delete the logs for the given workspace IDs 56 * @returns 57 */ 58async function deleteLogs( 59 timestamp: number, 60 workspaceIds: number[], 61 reverse = false, 62) { 63 const response = await fetch( 64 "https://api.tinybird.co/v0/datasources/ping_response__v8/delete", 65 { 66 method: "POST", 67 headers: { 68 "Content-Type": "application/x-www-form-urlencoded", 69 Authorization: `Bearer ${env().TINY_BIRD_API_KEY}`, 70 }, 71 body: new URLSearchParams({ 72 delete_condition: `timestamp <= ${timestamp} AND ${reverse ? "NOT" : ""} arrayExists(x -> x IN (${workspaceIds.join(", ")}), [workspaceId])`, 73 }), 74 }, 75 ); 76 const json = await response.json(); 77 console.log(json); 78 79 return json; 80} 81 82async function main() { 83 // check if the script is running in production 84 console.log(`DATABASE_URL: ${env().DATABASE_URL}`); 85 86 const isConfirmed = await askConfirmation( 87 "Are you sure you want to run this script?", 88 ); 89 90 if (!isConfirmed) { 91 console.log("Script execution cancelled."); 92 return; 93 } 94 95 const lastTwoWeeks = calculatePastTimestamp(14); 96 const lastThreeMonths = calculatePastTimestamp(90); 97 const lastYear = calculatePastTimestamp(365); 98 // const _lastTwoYears = calculatePastTimestamp(730); 99 100 const starters = await getWorkspaceIdsByPlan("starter"); 101 const teams = await getWorkspaceIdsByPlan("team"); 102 // const pros = await getWorkspaceIdsByPlan("pro"); 103 104 // all other workspaces, we need to 'reverse' the deletion here to NOT include those workspaces 105 const rest = [...starters, ...teams]; 106 107 deleteLogs(lastTwoWeeks, rest, true); 108 deleteLogs(lastThreeMonths, starters); 109 deleteLogs(lastYear, teams); 110 // deleteLogs(lastYear, pros); 111} 112 113/** 114 * REMINDER: do it manually (to avoid accidental deletion on dev mode) 115 * Within the app/workflows folder, run the following command: 116 * $ bun src/scripts/tinybird.ts 117 */ 118 119// main().catch(console.error);