fix: sync call gets called by other functions (#823)

* fix: sync call gets called by other functions

* fix: sync call gets called by other functions

* remove unused imports

* remove unused import

* fix userId update
This commit is contained in:
Matti Nannt
2023-09-17 00:31:38 +09:00
committed by GitHub
parent d8b14f5f35
commit f313275a14
4 changed files with 108 additions and 193 deletions

View File

@@ -1,10 +1,10 @@
import { getUpdatedState } from "@/app/api/v1/js/sync/lib/sync";
import { responses } from "@/lib/api/response";
import { transformErrorToDetails } from "@/lib/api/validator";
import { prisma } from "@formbricks/database";
import { WEBAPP_URL } from "@formbricks/lib/constants";
import { createAttributeClass, getAttributeClassByNameCached } from "@formbricks/lib/services/attributeClass";
import { getPersonCached } from "@formbricks/lib/services/person";
import { TJsState, ZJsPeopleAttributeInput } from "@formbricks/types/v1/js";
import { ZJsPeopleAttributeInput } from "@formbricks/types/v1/js";
import { revalidateTag } from "next/cache";
import { NextResponse } from "next/server";
@@ -76,21 +76,7 @@ export async function POST(req: Request, { params }): Promise<NextResponse> {
// revalidate person
revalidateTag(personId);
const syncRes = await fetch(`${WEBAPP_URL}/api/v1/js/sync`, {
method: "POST",
body: JSON.stringify({
environmentId,
personId,
sessionId,
}),
});
if (!syncRes.ok) {
throw new Error("Unable to get latest state from sync");
}
const syncJson = await syncRes.json();
const state: TJsState = syncJson.data;
const state = await getUpdatedState(environmentId, personId, sessionId);
return responses.successResponse({ ...state }, true);
} catch (error) {

View File

@@ -1,9 +1,9 @@
import { getUpdatedState } from "@/app/api/v1/js/sync/lib/sync";
import { responses } from "@/lib/api/response";
import { transformErrorToDetails } from "@/lib/api/validator";
import { prisma } from "@formbricks/database";
import { WEBAPP_URL } from "@formbricks/lib/constants";
import { deletePerson, selectPerson, transformPrismaPerson } from "@formbricks/lib/services/person";
import { TJsState, ZJsPeopleUserIdInput } from "@formbricks/types/v1/js";
import { ZJsPeopleUserIdInput } from "@formbricks/types/v1/js";
import { revalidateTag } from "next/cache";
import { NextResponse } from "next/server";
@@ -97,21 +97,7 @@ export async function POST(req: Request, { params }): Promise<NextResponse> {
revalidateTag(person.id);
}
const syncRes = await fetch(`${WEBAPP_URL}/api/v1/js/sync`, {
method: "POST",
body: JSON.stringify({
environmentId,
personId,
sessionId,
}),
});
if (!syncRes.ok) {
throw new Error("Unable to get latest state from sync");
}
const syncJson = await syncRes.json();
const state: TJsState = syncJson.data;
const state = await getUpdatedState(environmentId, person.id, sessionId);
return responses.successResponse({ ...state }, true);
} catch (error) {

View File

@@ -0,0 +1,99 @@
import { getSurveysCached } from "@/app/api/v1/js/surveys";
import { getActionClassesCached } from "@formbricks/lib/services/actionClass";
import { getEnvironmentCached } from "@formbricks/lib/services/environment";
import { createPerson, getPersonCached } from "@formbricks/lib/services/person";
import { getProductByEnvironmentIdCached } from "@formbricks/lib/services/product";
import { createSession, extendSession, getSessionCached } from "@formbricks/lib/services/session";
import { captureTelemetry } from "@formbricks/lib/telemetry";
import { TEnvironment } from "@formbricks/types/v1/environment";
import { TJsState } from "@formbricks/types/v1/js";
import { TPerson } from "@formbricks/types/v1/people";
import { TSession } from "@formbricks/types/v1/sessions";
const captureNewSessionTelemetry = async (jsVersion?: string): Promise<void> => {
await captureTelemetry("session created", { jsVersion: jsVersion ?? "unknown" });
};
export const getUpdatedState = async (
environmentId: string,
personId?: string,
sessionId?: string,
jsVersion?: string
): Promise<TJsState> => {
let environment: TEnvironment | null;
let person: TPerson;
let session: TSession | null;
// check if environment exists
environment = await getEnvironmentCached(environmentId);
if (!environment) {
throw new Error("Environment does not exist");
}
if (!personId) {
// create a new person
person = await createPerson(environmentId);
// create a new session
session = await createSession(person.id);
} else {
// check if person exists
const existingPerson = await getPersonCached(personId);
if (!existingPerson) {
// create a new person
person = await createPerson(environmentId);
} else {
person = existingPerson;
}
}
if (!sessionId) {
// create a new session
session = await createSession(person.id);
} else {
// check validity of person & session
session = await getSessionCached(sessionId);
if (!session) {
// create a new session
session = await createSession(person.id);
captureNewSessionTelemetry(jsVersion);
} else {
// check if session is expired
if (session.expiresAt < new Date()) {
// create a new session
session = await createSession(person.id);
captureNewSessionTelemetry(jsVersion);
} else {
// extend session (if about to expire)
const isSessionAboutToExpire =
new Date(session.expiresAt).getTime() - new Date().getTime() < 1000 * 60 * 10;
if (isSessionAboutToExpire) {
session = await extendSession(sessionId);
}
}
}
}
// we now have a valid person & session
// get/create rest of the state
const [surveys, noCodeActionClasses, product] = await Promise.all([
getSurveysCached(environmentId, person),
getActionClassesCached(environmentId),
getProductByEnvironmentIdCached(environmentId),
]);
if (!product) {
throw new Error("Product not found");
}
// return state
const state: TJsState = {
person: person!,
session,
surveys,
noCodeActionClasses: noCodeActionClasses.filter((actionClass) => actionClass.type === "noCode"),
product,
};
return state;
};

View File

@@ -1,21 +1,9 @@
import { getSurveysCached } from "@/app/api/v1/js/surveys";
import { getUpdatedState } from "@/app/api/v1/js/sync/lib/sync";
import { responses } from "@/lib/api/response";
import { transformErrorToDetails } from "@/lib/api/validator";
import { getActionClassesCached } from "@formbricks/lib/services/actionClass";
import { getEnvironmentCached } from "@formbricks/lib/services/environment";
import { createPerson, getPersonCached } from "@formbricks/lib/services/person";
import { getProductByEnvironmentIdCached } from "@formbricks/lib/services/product";
import { createSession, extendSession, getSessionCached } from "@formbricks/lib/services/session";
import { captureTelemetry } from "@formbricks/lib/telemetry";
import { TJsState, ZJsSyncInput } from "@formbricks/types/v1/js";
import { TPerson } from "@formbricks/types/v1/people";
import { TSession } from "@formbricks/types/v1/sessions";
import { ZJsSyncInput } from "@formbricks/types/v1/js";
import { NextResponse } from "next/server";
const captureNewSessionTelemetry = async (jsVersion?: string): Promise<void> => {
await captureTelemetry("session created", { jsVersion: jsVersion ?? "unknown" });
};
export async function OPTIONS(): Promise<NextResponse> {
return responses.successResponse({}, true);
}
@@ -37,152 +25,8 @@ export async function POST(req: Request): Promise<NextResponse> {
const { environmentId, personId, sessionId } = inputValidation.data;
// check if environment exists
const environment = await getEnvironmentCached(environmentId);
const state = await getUpdatedState(environmentId, personId, sessionId, inputValidation.data.jsVersion);
if (!environment) {
return responses.badRequestResponse(
"Environment does not exist",
{ environmentId: "Environment with this ID does not exist" },
true
);
}
if (!personId) {
// create a new person
const person = await createPerson(environmentId);
// create a new session
const session = await createSession(person.id);
// get/create rest of the state
const [surveys, noCodeActionClasses, product] = await Promise.all([
getSurveysCached(environmentId, person),
getActionClassesCached(environmentId),
getProductByEnvironmentIdCached(environmentId),
]);
captureNewSessionTelemetry(inputValidation.data.jsVersion);
if (!product) {
return responses.notFoundResponse("ProductByEnvironmentId", environmentId, true);
}
// return state
const state: TJsState = {
person,
session,
surveys,
noCodeActionClasses: noCodeActionClasses.filter((actionClass) => actionClass.type === "noCode"),
product,
};
return responses.successResponse({ ...state }, true);
}
if (!sessionId) {
let person: TPerson | null;
// check if person exists
person = await getPersonCached(personId);
if (!person) {
// create a new person
person = await createPerson(environmentId);
}
// create a new session
const session = await createSession(person.id);
const [surveys, noCodeActionClasses, product] = await Promise.all([
getSurveysCached(environmentId, person),
getActionClassesCached(environmentId),
getProductByEnvironmentIdCached(environmentId),
]);
if (!product) {
return responses.notFoundResponse("ProductByEnvironmentId", environmentId, true);
}
captureNewSessionTelemetry(inputValidation.data.jsVersion);
// return state
const state: TJsState = {
person,
session,
surveys,
noCodeActionClasses: noCodeActionClasses.filter((actionClass) => actionClass.type === "noCode"),
product,
};
return responses.successResponse({ ...state }, true);
}
// person & session exists
// check if session exists
let person: TPerson | null;
let session: TSession | null;
session = await getSessionCached(sessionId);
if (!session) {
// check if person exits
person = await getPersonCached(personId);
if (!person) {
// create a new person
person = await createPerson(environmentId);
}
// create a new session
session = await createSession(person.id);
captureNewSessionTelemetry(inputValidation.data.jsVersion);
} else {
// session exists
// check if person exists (should always exist, but just in case)
person = await getPersonCached(personId);
if (!person) {
// create a new person & session
person = await createPerson(environmentId);
session = await createSession(person.id);
} else {
// check if session is expired
if (session.expiresAt < new Date()) {
// create a new session
session = await createSession(person.id);
captureNewSessionTelemetry(inputValidation.data.jsVersion);
} else {
// extend session
const isSessionAboutToExpire =
new Date(session.expiresAt).getTime() - new Date().getTime() < 1000 * 60 * 10;
if (isSessionAboutToExpire) {
session = await extendSession(sessionId);
}
}
}
}
// get/create rest of the state
const [surveys, noCodeActionClasses, product] = await Promise.all([
getSurveysCached(environmentId, person),
getActionClassesCached(environmentId),
getProductByEnvironmentIdCached(environmentId),
]);
if (!product) {
return responses.notFoundResponse("ProductByEnvironmentId", environmentId, true);
}
// return state
const state: TJsState = {
person,
session,
surveys,
noCodeActionClasses: noCodeActionClasses.filter((actionClass) => actionClass.type === "noCode"),
product,
};
return responses.successResponse({ ...state }, true);
} catch (error) {
console.error(error);