9a7c08c26a
* Downgrade to remix-auth-email-link to remove yarn dependency * Turn off the pg listen service for now * Add snapshot admin route * A couple logger fixes * Add ability to disable compression * Add ability to disable SSE * Fix SSE memory leak + DB load issue
138 lines
3.7 KiB
TypeScript
138 lines
3.7 KiB
TypeScript
import { PrismaClient, prisma } from "~/db.server";
|
|
import { Project } from "~/models/project.server";
|
|
import { User } from "~/models/user.server";
|
|
import { sse } from "~/utils/sse.server";
|
|
|
|
type EnvironmentSignalsMap = {
|
|
[x: string]: {
|
|
lastUpdatedAt: number;
|
|
lastTotalEndpointUpdatedTime: number;
|
|
lastTotalIndexingUpdatedTime: number;
|
|
};
|
|
};
|
|
|
|
export class EnvironmentsStreamPresenter {
|
|
#prismaClient: PrismaClient;
|
|
|
|
constructor(prismaClient: PrismaClient = prisma) {
|
|
this.#prismaClient = prismaClient;
|
|
}
|
|
|
|
public async call({
|
|
request,
|
|
userId,
|
|
projectSlug,
|
|
}: {
|
|
request: Request;
|
|
userId: User["id"];
|
|
projectSlug: Project["slug"];
|
|
}) {
|
|
let lastEnvironmentSignals: EnvironmentSignalsMap;
|
|
|
|
return sse({
|
|
request,
|
|
run: async (send, stop) => {
|
|
const nextEnvironmentSignals = await this.#runForUpdates({
|
|
userId,
|
|
projectSlug,
|
|
});
|
|
|
|
if (!nextEnvironmentSignals) {
|
|
return stop();
|
|
}
|
|
|
|
const lastEnvironmentIds = lastEnvironmentSignals
|
|
? Object.keys(lastEnvironmentSignals)
|
|
: [];
|
|
const nextEnvironmentIds = Object.keys(nextEnvironmentSignals);
|
|
|
|
if (
|
|
//push update if the number of environments is different
|
|
nextEnvironmentIds.length !== lastEnvironmentIds.length ||
|
|
//push update if the list of ids is different
|
|
lastEnvironmentIds.some((id) => !nextEnvironmentSignals[id]) ||
|
|
nextEnvironmentIds.some((id) => !lastEnvironmentSignals[id]) ||
|
|
//push update if any signals changed
|
|
nextEnvironmentIds.some(
|
|
(id) =>
|
|
nextEnvironmentSignals[id].lastUpdatedAt !==
|
|
lastEnvironmentSignals[id].lastUpdatedAt ||
|
|
nextEnvironmentSignals[id].lastTotalEndpointUpdatedTime !==
|
|
lastEnvironmentSignals[id].lastTotalEndpointUpdatedTime ||
|
|
nextEnvironmentSignals[id].lastTotalIndexingUpdatedTime !==
|
|
lastEnvironmentSignals[id].lastTotalIndexingUpdatedTime
|
|
)
|
|
) {
|
|
send({ data: new Date().toISOString() });
|
|
}
|
|
|
|
lastEnvironmentSignals = nextEnvironmentSignals;
|
|
},
|
|
});
|
|
}
|
|
|
|
async #runForUpdates({
|
|
userId,
|
|
projectSlug,
|
|
}: {
|
|
userId: User["id"];
|
|
projectSlug: Project["slug"];
|
|
}) {
|
|
const environments = await this.#prismaClient.runtimeEnvironment.findMany({
|
|
select: {
|
|
id: true,
|
|
updatedAt: true,
|
|
endpoints: {
|
|
select: {
|
|
updatedAt: true,
|
|
indexings: {
|
|
select: {
|
|
updatedAt: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
where: {
|
|
project: {
|
|
slug: projectSlug,
|
|
},
|
|
organization: {
|
|
members: {
|
|
some: {
|
|
userId,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!environments) return null;
|
|
|
|
const environmentSignalsMap = environments.reduce<EnvironmentSignalsMap>((acc, environment) => {
|
|
const lastUpdatedAt = environment.updatedAt.getTime();
|
|
const lastTotalEndpointUpdatedTime = environment.endpoints.reduce(
|
|
(prev, endpoint) => prev + endpoint.updatedAt.getTime(),
|
|
0
|
|
);
|
|
const lastTotalIndexingUpdatedTime = environment.endpoints.reduce(
|
|
(prev, endpoint) =>
|
|
prev +
|
|
endpoint.indexings.reduce((prev, indexing) => prev + indexing.updatedAt.getTime(), 0),
|
|
0
|
|
);
|
|
|
|
return {
|
|
...acc,
|
|
[environment.id]: {
|
|
lastUpdatedAt,
|
|
lastTotalEndpointUpdatedTime,
|
|
lastTotalIndexingUpdatedTime,
|
|
},
|
|
};
|
|
}, {});
|
|
|
|
return environmentSignalsMap;
|
|
}
|
|
}
|