Adds logging when we encounter a webhook trigger error

PHOTO EMBED

Thu Jul 20 2023 12:29:32 GMT+0000 (Coordinated Universal Time)

Saved by @ibz

import {
  BlockActionEvent,
  Consumer,
  FormSubmission,
  Page,
  Project,
  RestHookSubscriptionType,
} from "@prisma/client";
import logger from "server/observability/logger";
import { prisma } from "server/data/prisma";
import { addTracingHeaders, fetchTraced } from "server/observability/tracing";
import { formSubmissionSchema } from "server/schemas/form-submissions";
import { blockActionEventSchema } from "server/schemas/blockActions";
import { mapBlock } from "../blocks";
import { BlockWithExtras } from "blocks/v2/__shared__/types";
import { consumerSchema } from "server/schemas/consumers";
import { PageWithoutContentSchema } from "server/schemas/pages";
import { ProjectSchema } from "server/schemas/projects";

export async function sendProjectCreatedWebhooks(project: Project) {
  const subscriptions = await prisma.restHookSubscription.findMany({
    where: {
      accountId: project.accountId,
      type: RestHookSubscriptionType.ProjectCreated,
    },
  });

  return await Promise.all(
    subscriptions.map(async (s) => {
      logger().info({ subscription: s }, "sending webhook");
      const response = await fetchTraced(s.url, {
        method: "post",
        headers: await addTracingHeaders({
          "Content-Type": "application/json",
        }),
        body: JSON.stringify(ProjectSchema.parse(project)),
      });
      if (response.status >= 500 || response.status >= 400) {
        logger().error(
          {
            response_text: response.statusText,
            response_status: response.status,
            subscriptions: s,
            userId: s.accountId,
            triggerEvent: s.type,
          },
          `Webhook Trigger Error -- TriggerType:${s.type}, UserId:${s.accountId}, ResponseStatus:${response.status},  ResponseStatusText:${response.statusText}`
        );
      }
      return response;
    })
  );
}

export async function sendPageCreatedWebhooks(page: Page) {
  const subscriptions = await prisma.restHookSubscription.findMany({
    where: {
      projectId: page.projectId,
      type: RestHookSubscriptionType.PageCreated,
    },
  });

  return await Promise.all(
    subscriptions.map(async (s) => {
      logger().info({ subscription: s }, "sending webhook");
      const response = await fetchTraced(s.url, {
        method: "post",
        headers: await addTracingHeaders({
          "Content-Type": "application/json",
        }),
        body: JSON.stringify(PageWithoutContentSchema.parse(page)),
      });
      if (response.status >= 500 || response.status >= 400) {
        logger().error(
          {
            response_text: response.statusText,
            response_status: response.status,
            subscriptions: s,
            userId: s.accountId,
            triggerEvent: s.type,
          },
          `Webhook Trigger Error -- TriggerType:${s.type}, UserId:${s.accountId}, ResponseStatus:${response.status},  ResponseStatusText:${response.statusText}`
        );
      }
      return response;
    })
  );
}

export async function sendBlockCreatedWebhooks(block: BlockWithExtras) {
  const subscriptions = await prisma.restHookSubscription.findMany({
    where: {
      pageId: block.pageId,
      type: RestHookSubscriptionType.BlockCreated,
    },
  } as any);

  const filteredSubscriptions = subscriptions.filter(
    (s) => s.blockType === block.type || s.blockType === null
  );

  return await Promise.all(
    filteredSubscriptions.map(async (s) => {
      logger().info({ subscription: s }, "sending webhook");
      const response = await fetchTraced(s.url, {
        method: "post",
        headers: await addTracingHeaders({
          "Content-Type": "application/json",
        }),
        body: JSON.stringify({ id: block.id, ...mapBlock(block) }),
      });
      if (response.status >= 500 || response.status >= 400) {
        logger().error(
          {
            response_text: response.statusText,
            response_status: response.status,
            subscriptions: s,
            userId: s.accountId,
            triggerEvent: s.type,
          },
          `Webhook Trigger Error -- TriggerType:${s.type}, UserId:${s.accountId}, ResponseStatus:${response.status},  ResponseStatusText:${response.statusText}`
        );
      }
      return response;
    })
  );
}

export async function sendFormSubmissionCreatedWebhooks(
  formSubmission: FormSubmission,
  tableId?: string,
  recordId?: string
) {
  const subscriptions = await prisma.restHookSubscription.findMany({
    where: {
      blockId: formSubmission.blockId,
      type: RestHookSubscriptionType.FormSubmissionCreated,
    },
  });

  return await Promise.all(
    subscriptions.map(async (s) => {
      logger().info({ subscription: s }, "sending webhook");
      const response = await fetchTraced(s.url, {
        method: "post",
        headers: await addTracingHeaders({
          "Content-Type": "application/json",
        }),
        body: JSON.stringify(
          formSubmissionSchema.parse({ ...formSubmission, tableId, recordId })
        ),
      });
      if (response.status >= 500 || response.status >= 400) {
        logger().error(
          {
            response_text: response.statusText,
            response_status: response.status,
            subscriptions: s,
            userId: s.accountId,
            triggerEvent: s.type,
          },
          `Webhook Trigger Error -- TriggerType:${s.type}, UserId:${s.accountId}, ResponseStatus:${response.status},  ResponseStatusText:${response.statusText}`
        );
      }
      return response;
    })
  );
}

export async function sendBlockActionEventWebhooks(
  blockActionEvent: BlockActionEvent
) {
  const subscriptions = await prisma.restHookSubscription.findMany({
    where: {
      blockActionId: blockActionEvent.blockActionId,
      blockId: blockActionEvent.blockId,
      type: RestHookSubscriptionType.BlockActionEvent,
    },
  });

  return await Promise.all(
    subscriptions.map(async (s) => {
      logger().info({ subscription: s }, "sending webhook");
      const response = await fetchTraced(s.url, {
        method: "post",
        headers: await addTracingHeaders({
          "Content-Type": "application/json",
        }),
        body: JSON.stringify(blockActionEventSchema.parse(blockActionEvent)),
      });
      if (response.status >= 500 || response.status >= 400) {
        logger().error(
          {
            response_text: response.statusText,
            response_status: response.status,
            subscriptions: s,
            userId: s.accountId,
            triggerEvent: s.type,
          },
          `Webhook Trigger Error -- TriggerType:${s.type}, UserId:${s.accountId}, ResponseStatus:${response.status},  ResponseStatusText:${response.statusText}`
        );
      }
      return response;
    })
  );
}

export async function sendConsumerCreatedWebhooks(consumer: Consumer) {
  const subscriptions = await prisma.restHookSubscription.findMany({
    where: {
      projectId: consumer.projectId,
      type: RestHookSubscriptionType.ConsumerCreated,
    },
  });

  return await Promise.all(
    subscriptions.map(async (s) => {
      logger().info({ subscription: s }, "sending webhook");
      const response = await fetchTraced(s.url, {
        method: "post",
        headers: await addTracingHeaders({
          "Content-Type": "application/json",
        }),
        body: JSON.stringify(consumerSchema.parse(consumer)),
      });
      if (response.status >= 500 || response.status >= 400) {
        logger().error(
          {
            response_text: response.statusText,
            response_status: response.status,
            subscriptions: s,
            userId: s.accountId,
            triggerEvent: s.type,
          },
          `Webhook Trigger Error -- TriggerType:${s.type}, UserId:${s.accountId}, ResponseStatus:${response.status},  ResponseStatusText:${response.statusText}`
        );
      }
      return response;
    })
  );
}
content_copyCOPY