Skip to content

Commit ad19928

Browse files
committed
patch @sentry/remix to prevent memory leaks
1 parent e4e4b08 commit ad19928

File tree

6 files changed

+128
-51
lines changed

6 files changed

+128
-51
lines changed

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam._index/route.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ import { useProject } from "~/hooks/useProject";
7474
import { findProjectBySlug } from "~/models/project.server";
7575
import { findEnvironmentBySlug } from "~/models/runtimeEnvironment.server";
7676
import {
77+
getTaskListPresenter,
7778
type TaskActivity,
7879
type TaskListItem,
79-
taskListPresenter,
8080
} from "~/presenters/v3/TaskListPresenter.server";
8181
import {
8282
getUsefulLinksPreference,
@@ -124,6 +124,8 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
124124
}
125125

126126
try {
127+
const taskListPresenter = getTaskListPresenter();
128+
127129
const { tasks, activity, runningStats, durations } = await taskListPresenter.call({
128130
organizationId: project.organizationId,
129131
projectId: project.id,

apps/webapp/app/routes/admin.api.v1.gc.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { type DataFunctionArgs } from "@remix-run/node";
22
import { PerformanceObserver } from "node:perf_hooks";
33
import { runInNewContext } from "node:vm";
44
import v8 from "v8";
5-
import { requireUser } from "~/services/session.server";
5+
import { prisma } from "~/db.server";
6+
import { authenticateApiRequestWithPersonalAccessToken } from "~/services/personalAccessToken.server";
67

78
async function waitTillGcFinishes() {
89
let resolver: (value: PerformanceEntry) => void;
@@ -35,9 +36,19 @@ async function waitTillGcFinishes() {
3536
}
3637

3738
export async function loader({ request }: DataFunctionArgs) {
38-
const user = await requireUser(request);
39+
const authenticationResult = await authenticateApiRequestWithPersonalAccessToken(request);
3940

40-
if (!user.admin) {
41+
if (!authenticationResult) {
42+
throw new Response("You must be an admin to perform this action", { status: 403 });
43+
}
44+
45+
const user = await prisma.user.findFirst({
46+
where: {
47+
id: authenticationResult.userId,
48+
},
49+
});
50+
51+
if (!user?.admin) {
4152
throw new Response("You must be an admin to perform this action", { status: 403 });
4253
}
4354

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { ActionFunctionArgs } from "@remix-run/server-runtime";
2+
3+
export async function action({ request }: ActionFunctionArgs) {
4+
if (process.env.NODE_ENV === "production") {
5+
return new Response("Not found", { status: 404 });
6+
}
7+
8+
return new Response(
9+
JSON.stringify({
10+
data: {
11+
id: "123",
12+
type: "mock",
13+
attributes: {
14+
name: "Mock",
15+
},
16+
},
17+
}),
18+
{ status: 200 }
19+
);
20+
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@
7979
8080
8181
82-
"@kubernetes/[email protected]": "patches/@[email protected]"
82+
"@kubernetes/[email protected]": "patches/@[email protected]",
83+
"@sentry/[email protected]": "patches/@[email protected]"
8384
},
8485
"overrides": {
8586
"express@^4>body-parser": "1.20.3",

patches/@[email protected]

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
diff --git a/build/cjs/vendor/instrumentation.js b/build/cjs/vendor/instrumentation.js
2+
index 84e18d1051f57d5807e65c8b8ce858ceee7d4557..640a5253d565650338fe33e0ea52c8dffc63e4e7 100644
3+
--- a/build/cjs/vendor/instrumentation.js
4+
+++ b/build/cjs/vendor/instrumentation.js
5+
@@ -238,7 +238,7 @@ class RemixInstrumentation extends instrumentation.InstrumentationBase {
6+
return function callRouteAction(original) {
7+
return async function patchCallRouteAction( ...args) {
8+
const [params] = args;
9+
- const clonedRequest = params.request.clone();
10+
+ const clonedRequest = params.request;
11+
const span = plugin.tracer.startSpan(
12+
`ACTION ${params.routeId}`,
13+
{ attributes: { [semanticConventions.SemanticAttributes.CODE_FUNCTION]: 'action' } },
14+
@@ -257,25 +257,6 @@ class RemixInstrumentation extends instrumentation.InstrumentationBase {
15+
.then(async response => {
16+
addResponseAttributesToSpan(span, response);
17+
18+
- try {
19+
- const formData = await clonedRequest.formData();
20+
- const { actionFormDataAttributes: actionFormAttributes } = plugin.getConfig();
21+
-
22+
- formData.forEach((value, key) => {
23+
- if (
24+
- actionFormAttributes?.[key] &&
25+
- actionFormAttributes[key] !== false &&
26+
- typeof value === 'string'
27+
- ) {
28+
- const keyName = actionFormAttributes[key] === true ? key : actionFormAttributes[key];
29+
- span.setAttribute(`formData.${keyName}`, value.toString());
30+
- }
31+
- });
32+
- } catch {
33+
- // Silently continue on any error. Typically happens because the action body cannot be processed
34+
- // into FormData, in which case we should just continue.
35+
- }
36+
-
37+
return response;
38+
})
39+
.catch(async error => {

pnpm-lock.yaml

Lines changed: 50 additions & 46 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)