Skip to content

Commit

Permalink
add instrumentation file (#1056)
Browse files Browse the repository at this point in the history
* add instrumentation file

* singleton

* fix tests

---------

Co-authored-by: Andy Wang <[email protected]>
  • Loading branch information
igorosip0v and andy-t-wang authored Nov 27, 2024
1 parent 4371dd0 commit 5ba5a9e
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 72 deletions.
7 changes: 7 additions & 0 deletions web/@types/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Redis, Cluster as RedisCluster } from "ioredis";

type Messages = typeof en;

declare global {
var RedisClient: Redis | RedisCluster | undefined;
}
11 changes: 5 additions & 6 deletions web/api/helpers/app-rating/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"use server";
import { createRedisClient } from "@/lib/redis";
import { getAPIServiceGraphqlClient } from "../graphql";
import { getSdk as getAppRatingSdk } from "./graphql/get-app-rating.generated";

Expand All @@ -8,11 +7,11 @@ export async function getAppRating(appId: string): Promise<number> {
const redisKey = `app:${appId}:rating`;
const lockKey = `lock:${appId}:rating`;

const redis = createRedisClient({
url: process.env.REDIS_URL!,
password: process.env.REDIS_PASSWORD!,
username: process.env.REDIS_USERNAME!,
});
const redis = global.RedisClient;

if (!redis) {
throw new Error("Redis client not found");
}

try {
// Try to get from cache first
Expand Down
34 changes: 34 additions & 0 deletions web/instrumentation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export async function register() {
console.log("🛠️ Starting Instrumentation registration...");

try {
if (
typeof window === "undefined" &&
process.env.NEXT_RUNTIME === "nodejs"
) {
const { createRedisClient } = await import("./lib/redis");

if (
!process.env.REDIS_URL ||
!process.env.REDIS_USERNAME ||
!process.env.REDIS_PASSWORD
) {
return console.error(
"🔴 Missing Redis configuration in instrumentation.ts",
);
}

const redis = createRedisClient({
url: process.env.REDIS_URL,
password: process.env.REDIS_PASSWORD,
username: process.env.REDIS_USERNAME,
});

global.RedisClient = redis;
}
} catch (error) {
return console.error("🔴 Instrumentation registration error: ", error);
}

console.log("✅ Instrumentation registration complete.");
}
7 changes: 7 additions & 0 deletions web/jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import IORedis from "ioredis-mock";
import { setConfig } from "next/config";
import "whatwg-fetch";

Expand All @@ -9,6 +10,12 @@ setConfig({
),
});

// Create the mock Redis client
const redisMock = new IORedis();

// Set the global mock
global.RedisClient = redisMock;

export const MOCKED_GENERAL_SECRET_KEY =
"0xsuperSecretKey99994ab56046d4d97695b9999999";

Expand Down
5 changes: 5 additions & 0 deletions web/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ const publicAppURL =
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: false,

experimental: {
instrumentationHook: true,
},

output: "standalone",
images: {
remotePatterns: [
Expand Down
43 changes: 12 additions & 31 deletions web/pages/api/v1/oidc/authorize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { validateRequestSchema } from "@/legacy/backend/utils";
import { verifyProof } from "@/legacy/backend/verify";
import { logger } from "@/legacy/lib/logger";
import { OIDCFlowType, OIDCResponseType } from "@/legacy/lib/types";
import { createRedisClient } from "@/lib/redis";
import { captureEvent } from "@/services/posthogClient";
import { gql } from "@apollo/client";
import { VerificationLevel } from "@worldcoin/idkit-core";
Expand Down Expand Up @@ -98,32 +97,20 @@ export default async function handleOIDCAuthorize(
return errorNotAllowed(req.method, res, req);
}

let redis;
const redis = global.RedisClient;

try {
// Initial validations...
if (!process.env.REDIS_URL || !process.env.REDIS_USERNAME) {
return errorResponse(
res,
500,
"missing_redis_config",
"Missing ENV variables.",
"INVALID_CONFIG",
req,
);
}

if (process.env.NODE_ENV !== "development" && !process.env.REDIS_USERNAME) {
return errorResponse(
res,
500,
"missing_redis_config",
"Missing ENV variables.",
"INVALID_CONFIG",
req,
);
}
if (!redis) {
return errorResponse(
res,
500,
"internal_server_error",
"Redis client not found",
"server",
req,
);
}

try {
const { isValid, parsedParams, handleError } = await validateRequestSchema({
schema,
value: req.body,
Expand Down Expand Up @@ -225,12 +212,6 @@ export default async function handleOIDCAuthorize(
);
}

redis = createRedisClient({
url: process.env.REDIS_URL,
password: process.env.REDIS_PASSWORD,
username: process.env.REDIS_USERNAME,
});

// Anchor: Check the proof hasn't been replayed
const hashedProof = createHash("sha256").update(proof).digest("hex");
const proofKey = `oidc:proof:${hashedProof}`;
Expand Down
20 changes: 2 additions & 18 deletions web/tests/api/oidc/authorize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
insertAuthCodeQuery,
} from "@/legacy/backend/oidc";
import { OIDCResponseType } from "@/legacy/lib/types";
import { createRedisClient } from "@/lib/redis";
import handleOIDCAuthorize from "@/pages/api/v1/oidc/authorize";
import { createPublicKey } from "crypto";
import dayjs from "dayjs";
Expand All @@ -26,15 +25,6 @@ jest.mock("legacy/backend/jwks", () =>
require("tests/api/__mocks__/jwks.mock.ts"),
);

jest.mock("ioredis", () => {
const ioredisMock = jest.requireActual("ioredis-mock");
return {
__esModule: true,
Redis: ioredisMock,
Cluster: ioredisMock.Cluster,
};
});

const fetchAppQueryResponse = () => ({
data: {
app: [
Expand Down Expand Up @@ -74,6 +64,8 @@ jest.mock(
);

beforeEach(async () => {
await global.RedisClient?.flushall();

when(requestReturnFn)
.calledWith(
expect.objectContaining({
Expand Down Expand Up @@ -108,14 +100,6 @@ beforeEach(async () => {
.mockImplementation((args) => ({
data: { insert_auth_code_one: { auth_code: args.variables.auth_code } },
}));

const redis = createRedisClient({
url: process.env.REDIS_URL!,
password: process.env.REDIS_PASSWORD,
username: process.env.REDIS_USERNAME!,
});

await redis.flushall();
});

beforeAll(() => {
Expand Down
18 changes: 1 addition & 17 deletions web/tests/integration/oidc/authorize.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { OIDCErrorCodes } from "@/legacy/backend/oidc";
import { createRedisClient } from "@/lib/redis";
import handleOIDCAuthorize from "@/pages/api/v1/oidc/authorize";
import { createHash } from "crypto";
import fetchMock from "jest-fetch-mock";
Expand All @@ -10,24 +9,9 @@ import { validSemaphoreProofMock } from "tests/api/__mocks__/sequencer.mock";
import { integrationDBClean, integrationDBExecuteQuery } from "../setup";
import { testGetDefaultApp } from "../test-utils";

jest.mock("ioredis", () => {
const ioredisMock = jest.requireActual("ioredis-mock");
return {
__esModule: true,
Redis: ioredisMock,
Cluster: ioredisMock.Cluster,
};
});

beforeEach(async () => {
await integrationDBClean();
const redis = createRedisClient({
url: process.env.REDIS_URL!,
password: process.env.REDIS_PASSWORD,
username: process.env.REDIS_USERNAME!,
});

await redis.flushall();
await global.RedisClient?.flushall();
});

beforeAll(() => {
Expand Down

0 comments on commit 5ba5a9e

Please sign in to comment.