Openstatus www.openstatus.dev

๐Ÿš€ trigger checker after creation (#1317)

* ๐Ÿš€ trigger checker after creation

* ci: apply automated fixes

* ๐Ÿ”ฅ

* ci: apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

authored by

Thibault Le Ouay
autofix-ci[bot]
and committed by
GitHub
10a37024 0ade17c2

+133 -1
+6
apps/dashboard/src/app/(dashboard)/monitors/create/page.tsx
··· 20 20 const trpc = useTRPC(); 21 21 const queryClient = useQueryClient(); 22 22 const router = useRouter(); 23 + 24 + const triggerCheckMutation = useMutation( 25 + trpc.checker.triggerChecker.mutationOptions({}), 26 + ); 27 + 23 28 const createMonitorMutation = useMutation( 24 29 trpc.monitor.new.mutationOptions({ 25 30 onSuccess: (data) => { 26 31 queryClient.invalidateQueries({ 27 32 queryKey: trpc.monitor.list.queryKey(), 28 33 }); 34 + triggerCheckMutation.mutate({ id: data.id }); 29 35 router.push(`/monitors/${data.id}/edit`); 30 36 }, 31 37 }),
+5 -1
apps/dashboard/src/app/(dashboard)/onboarding/client.tsx
··· 91 91 const { data: workspace, refetch } = useQuery( 92 92 trpc.workspace.get.queryOptions(), 93 93 ); 94 + const triggerCheckMutation = useMutation( 95 + trpc.checker.triggerChecker.mutationOptions({}), 96 + ); 94 97 const createMonitorMutation = useMutation( 95 98 trpc.monitor.new.mutationOptions({ 96 - onSuccess: () => { 99 + onSuccess: (data) => { 97 100 setSearchParams({ step: "2" }); 101 + triggerCheckMutation.mutate({ id: data.id }); 98 102 refetch(); 99 103 queryClient.invalidateQueries({ 100 104 queryKey: trpc.monitor.list.queryKey(),
+1
packages/api/package.json
··· 12 12 "@openstatus/db": "workspace:*", 13 13 "@openstatus/emails": "workspace:*", 14 14 "@openstatus/error": "workspace:*", 15 + "@openstatus/utils": "workspace:*", 15 16 "@openstatus/tinybird": "workspace:*", 16 17 "@t3-oss/env-core": "0.7.1", 17 18 "@trpc/client": "11.4.3",
+118
packages/api/src/router/checker.ts
··· 8 8 statusAssertion, 9 9 textBodyAssertion, 10 10 } from "@openstatus/assertions"; 11 + import { and, db, eq } from "@openstatus/db"; 12 + import { monitor, selectMonitorSchema } from "@openstatus/db/src/schema"; 11 13 import { monitorFlyRegionSchema } from "@openstatus/db/src/schema/constants"; 14 + import { 15 + type httpPayloadSchema, 16 + type tpcPayloadSchema, 17 + transformHeaders, 18 + } from "@openstatus/utils"; 12 19 import { z } from "zod"; 13 20 import { env } from "../env"; 14 21 import { createTRPCRouter, protectedProcedure } from "../trpc"; ··· 247 254 } 248 255 } 249 256 257 + export async function triggerChecker( 258 + input: z.infer<typeof selectMonitorSchema>, 259 + ) { 260 + let payload: 261 + | z.infer<typeof httpPayloadSchema> 262 + | z.infer<typeof tpcPayloadSchema> 263 + | null = null; 264 + 265 + if (process.env.NODE_ENV !== "production") { 266 + return; 267 + } 268 + 269 + const timestamp = Date.now(); 270 + 271 + if (input.jobType === "http") { 272 + payload = { 273 + workspaceId: String(input.workspaceId), 274 + monitorId: String(input.id), 275 + url: input.url, 276 + method: input.method || "GET", 277 + cronTimestamp: timestamp, 278 + body: input.body, 279 + headers: input.headers, 280 + status: "active", 281 + assertions: input.assertions ? JSON.parse(input.assertions) : null, 282 + degradedAfter: input.degradedAfter, 283 + timeout: input.timeout, 284 + trigger: "cron", 285 + otelConfig: input.otelEndpoint 286 + ? { 287 + endpoint: input.otelEndpoint, 288 + headers: transformHeaders(input.otelHeaders), 289 + } 290 + : undefined, 291 + retry: input.retry || 3, 292 + }; 293 + } 294 + if (input.jobType === "tcp") { 295 + payload = { 296 + workspaceId: String(input.workspaceId), 297 + monitorId: String(input.id), 298 + uri: input.url, 299 + status: "active", 300 + assertions: input.assertions ? JSON.parse(input.assertions) : null, 301 + cronTimestamp: timestamp, 302 + degradedAfter: input.degradedAfter, 303 + timeout: input.timeout, 304 + trigger: "cron", 305 + retry: input.retry || 3, 306 + otelConfig: input.otelEndpoint 307 + ? { 308 + endpoint: input.otelEndpoint, 309 + headers: transformHeaders(input.otelHeaders), 310 + } 311 + : undefined, 312 + }; 313 + } 314 + const allResult = []; 315 + 316 + for (const region of input.regions) { 317 + const res = fetch(generateUrl({ row: input }), { 318 + method: "POST", 319 + headers: { 320 + Authorization: `Basic ${env.CRON_SECRET}`, 321 + "Content-Type": "application/json", 322 + "fly-prefer-region": region, 323 + }, 324 + body: JSON.stringify(payload), 325 + signal: AbortSignal.timeout(ABORT_TIMEOUT), 326 + }); 327 + allResult.push(res); 328 + } 329 + 330 + await Promise.allSettled(allResult); 331 + } 332 + 333 + function generateUrl({ row }: { row: z.infer<typeof selectMonitorSchema> }) { 334 + switch (row.jobType) { 335 + case "http": 336 + return `https://openstatus-checker.fly.dev/checker/http?monitor_id=${row.id}`; 337 + case "tcp": 338 + return `https://openstatus-checker.fly.dev/checker/tcp?monitor_id=${row.id}`; 339 + default: 340 + throw new Error("Invalid jobType"); 341 + } 342 + } 343 + 250 344 export const checkerRouter = createTRPCRouter({ 251 345 testHttp: protectedProcedure 252 346 .meta({ track: Events.TestMonitor }) ··· 260 354 .input(tcpTestInput) 261 355 .mutation(async ({ input }) => { 262 356 return testTcp(input); 357 + }), 358 + 359 + triggerChecker: protectedProcedure 360 + .input(z.object({ id: z.number() })) 361 + .mutation(async (opts) => { 362 + const m = await db 363 + .select() 364 + .from(monitor) 365 + .where( 366 + and( 367 + eq(monitor.id, opts.input.id), 368 + eq(monitor.workspaceId, opts.ctx.workspace.id), 369 + ), 370 + ) 371 + .get(); 372 + if (!m) { 373 + throw new TRPCError({ 374 + code: "NOT_FOUND", 375 + message: "Monitor not found", 376 + }); 377 + } 378 + const input = selectMonitorSchema.parse(m); 379 + 380 + return await triggerChecker(input); 263 381 }), 264 382 });
+3
pnpm-lock.yaml
··· 879 879 '@openstatus/tinybird': 880 880 specifier: workspace:* 881 881 version: link:../tinybird 882 + '@openstatus/utils': 883 + specifier: workspace:* 884 + version: link:../utils 882 885 '@t3-oss/env-core': 883 886 specifier: 0.7.1 884 887 version: 0.7.1(typescript@5.7.2)(zod@3.24.1)