review fixes

This commit is contained in:
x032205
2025-10-10 14:37:52 -04:00
parent e752391dbf
commit 2f01d096c6
7 changed files with 36 additions and 22 deletions
@@ -31,6 +31,7 @@ export const gatewayV2DalFactory = (db: TDbClient) => {
if (isHeartbeatStale) { if (isHeartbeatStale) {
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000); const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000);
void query.whereNotNull(`${TableName.GatewayV2}.heartbeat`);
void query.where(`${TableName.GatewayV2}.heartbeat`, "<", oneHourAgo); void query.where(`${TableName.GatewayV2}.heartbeat`, "<", oneHourAgo);
void query.where((v) => { void query.where((v) => {
void v void v
@@ -9,6 +9,7 @@ import { PgSqlLock } from "@app/keystore/keystore";
import { crypto } from "@app/lib/crypto"; import { crypto } from "@app/lib/crypto";
import { DatabaseErrorCode } from "@app/lib/error-codes"; import { DatabaseErrorCode } from "@app/lib/error-codes";
import { BadRequestError, DatabaseError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, DatabaseError, NotFoundError } from "@app/lib/errors";
import { groupBy } from "@app/lib/fn";
import { GatewayProxyProtocol } from "@app/lib/gateway/types"; import { GatewayProxyProtocol } from "@app/lib/gateway/types";
import { withGatewayV2Proxy } from "@app/lib/gateway-v2/gateway-v2"; import { withGatewayV2Proxy } from "@app/lib/gateway-v2/gateway-v2";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
@@ -902,13 +903,7 @@ export const gatewayV2ServiceFactory = ({
"Found gateways with last heartbeat over an hour ago. Sending notifications." "Found gateways with last heartbeat over an hour ago. Sending notifications."
); );
const gatewaysByOrg = unhealthyGateways.reduce<Record<string, (typeof unhealthyGateways)[number][]>>((acc, gw) => { const gatewaysByOrg = groupBy(unhealthyGateways, (gw) => gw.orgId);
if (!acc[gw.orgId]) {
acc[gw.orgId] = [];
}
acc[gw.orgId].push(gw);
return acc;
}, {});
for await (const [orgId, gateways] of Object.entries(gatewaysByOrg)) { for await (const [orgId, gateways] of Object.entries(gatewaysByOrg)) {
try { try {
@@ -21,6 +21,7 @@ export const relayDalFactory = (db: TDbClient) => {
if (isHeartbeatStale) { if (isHeartbeatStale) {
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000); const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000);
void query.whereNotNull(`${TableName.Relay}.heartbeat`);
void query.where(`${TableName.Relay}.heartbeat`, "<", oneHourAgo); void query.where(`${TableName.Relay}.heartbeat`, "<", oneHourAgo);
void query.where((v) => { void query.where((v) => {
void v void v
@@ -8,6 +8,7 @@ import { OrgMembershipRole, TRelays } from "@app/db/schemas";
import { PgSqlLock } from "@app/keystore/keystore"; import { PgSqlLock } from "@app/keystore/keystore";
import { crypto } from "@app/lib/crypto"; import { crypto } from "@app/lib/crypto";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { groupBy } from "@app/lib/fn";
import { createRelayConnection } from "@app/lib/gateway-v2/gateway-v2"; import { createRelayConnection } from "@app/lib/gateway-v2/gateway-v2";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type"; import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
@@ -1220,14 +1221,7 @@ export const relayServiceFactory = ({
"Found relays with last heartbeat over an hour ago. Sending notifications." "Found relays with last heartbeat over an hour ago. Sending notifications."
); );
const relaysByOrg = unhealthyRelays.reduce<Record<string, TRelays[]>>((acc, r) => { const relaysByOrg = groupBy(unhealthyRelays, (r) => r.orgId ?? "instance");
const key = r.orgId ?? "instance";
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(r);
return acc;
}, {});
for await (const [orgId, relays] of Object.entries(relaysByOrg)) { for await (const [orgId, relays] of Object.entries(relaysByOrg)) {
try { try {
@@ -1244,7 +1238,7 @@ export const relayServiceFactory = ({
recipients, recipients,
subjectLine: "Relay Health Alert", subjectLine: "Relay Health Alert",
substitutions: { substitutions: {
type: "relay", type: "instance-relay",
names: relayNames names: relayNames
}, },
template: SmtpTemplates.HealthAlert template: SmtpTemplates.HealthAlert
@@ -4,7 +4,7 @@ import { BaseEmailWrapper, BaseEmailWrapperProps } from "./BaseEmailWrapper";
import { BaseLink } from "./BaseLink"; import { BaseLink } from "./BaseLink";
interface HealthAlertTemplateProps extends Omit<BaseEmailWrapperProps, "title" | "preview" | "children"> { interface HealthAlertTemplateProps extends Omit<BaseEmailWrapperProps, "title" | "preview" | "children"> {
type: "gateway" | "relay"; type: "gateway" | "relay" | "instance-relay";
names: string; names: string;
} }
@@ -24,8 +24,14 @@ export const HealthAlertTemplate = ({ siteUrl, names, type }: HealthAlertTemplat
heartbeat in over an hour: <strong>{names}</strong>. heartbeat in over an hour: <strong>{names}</strong>.
</Text> </Text>
<Text className="text-black text-[14px] leading-[24px]"> <Text className="text-black text-[14px] leading-[24px]">
If your issue persists, you can contact the Infisical team at{" "} {type === "instance-relay" && (
<BaseLink href="mailto:[email protected]">[email protected]</BaseLink>. <>
If your issue persists, you can contact the Infisical team at{" "}
<BaseLink href="mailto:[email protected]">[email protected]</BaseLink>.
</>
)}
{type === "relay" && <>Please contact your relay administrators.</>}
{type === "gateway" && <>Please contact your gateway administrators.</>}
</Text> </Text>
</Section> </Section>
</BaseEmailWrapper> </BaseEmailWrapper>
@@ -48,7 +48,7 @@ import { useDeleteGatewayV2ById } from "@app/hooks/api/gateways-v2";
import { EditGatewayDetailsModal } from "./components/EditGatewayDetailsModal"; import { EditGatewayDetailsModal } from "./components/EditGatewayDetailsModal";
export const GatewayHealthStatus = ({ heartbeat }: { heartbeat?: string }) => { const GatewayHealthStatus = ({ heartbeat }: { heartbeat?: string }) => {
const heartbeatDate = heartbeat ? new Date(heartbeat) : null; const heartbeatDate = heartbeat ? new Date(heartbeat) : null;
const now = new Date(); const now = new Date();
const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000); const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000);
@@ -42,7 +42,24 @@ import { withPermission } from "@app/hoc";
import { usePopUp } from "@app/hooks"; import { usePopUp } from "@app/hooks";
import { useDeleteRelayById, useGetRelays } from "@app/hooks/api/relays"; import { useDeleteRelayById, useGetRelays } from "@app/hooks/api/relays";
import { GatewayHealthStatus } from "../GatewayTab/GatewayTab"; const RelayHealthStatus = ({ heartbeat }: { heartbeat?: string }) => {
const heartbeatDate = heartbeat ? new Date(heartbeat) : null;
const now = new Date();
const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000);
const isHealthy = heartbeatDate && heartbeatDate >= oneHourAgo;
const tooltipContent = heartbeatDate
? `Last heartbeat: ${heartbeatDate.toLocaleString()}`
: "No heartbeat data available";
return (
<Tooltip content={tooltipContent}>
<span className={`cursor-default ${isHealthy ? "text-green-400" : "text-red-400"}`}>
{isHealthy ? "Healthy" : "Unreachable"}
</span>
</Tooltip>
);
};
export const RelayTab = withPermission( export const RelayTab = withPermission(
() => { () => {
@@ -143,7 +160,7 @@ export const RelayTab = withPermission(
<Td>{el.host}</Td> <Td>{el.host}</Td>
<Td>{formatRelative(new Date(el.createdAt), new Date())}</Td> <Td>{formatRelative(new Date(el.createdAt), new Date())}</Td>
<Td> <Td>
<GatewayHealthStatus heartbeat={el.heartbeat} /> <RelayHealthStatus heartbeat={el.heartbeat} />
</Td> </Td>
<Td className="w-5"> <Td className="w-5">
<Tooltip className="max-w-sm text-center" content="Options"> <Tooltip className="max-w-sm text-center" content="Options">