Use sync access for the temp JSON file database
Replace all async reads and writes to the JSON database with the sync reads and writes to prevent a data corruption race condition where two requests are processed at the same time and write to the same file, or one reads while the other writes causing read of partially written data.
This commit is contained in:
parent
f9d188b2ba
commit
80cec71308
23 changed files with 138 additions and 138 deletions
|
@ -20,7 +20,7 @@ export async function updateScheduleInterestedCounts(users: ServerUser[]) {
|
|||
eventSlotCounts.set(id, (eventSlotCounts.get(id) ?? 0) + 1);
|
||||
}
|
||||
|
||||
const schedule = await readSchedule();
|
||||
const schedule = readSchedule();
|
||||
if (schedule.deleted) {
|
||||
throw new Error("Deleted schedule not implemented");
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ export async function updateScheduleInterestedCounts(users: ServerUser[]) {
|
|||
schedule.updatedAt = updatedFrom;
|
||||
await writeSchedule(schedule);
|
||||
await broadcastEvent({
|
||||
id: await nextEventId(),
|
||||
id: nextEventId(),
|
||||
type: "schedule-update",
|
||||
updatedFrom,
|
||||
data: update,
|
||||
|
|
|
@ -19,11 +19,11 @@ import type { ApiAuthenticationProvider, ApiSession } from "~/shared/types/api";
|
|||
import { serverUserToApiAccount } from "./user";
|
||||
|
||||
async function removeSessionSubscription(sessionId: number) {
|
||||
const subscriptions = await readSubscriptions();
|
||||
const subscriptions = readSubscriptions();
|
||||
const index = subscriptions.findIndex(subscription => subscription.sessionId === sessionId);
|
||||
if (index !== -1) {
|
||||
subscriptions.splice(index, 1);
|
||||
await writeSubscriptions(subscriptions);
|
||||
writeSubscriptions(subscriptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ async function clearServerSessionInternal(event: H3Event, sessions: ServerSessio
|
|||
if (session) {
|
||||
session.expiresAtMs = Date.now();
|
||||
broadcastEvent({
|
||||
id: await nextEventId(),
|
||||
id: nextEventId(),
|
||||
type: "session-expired",
|
||||
sessionId,
|
||||
});
|
||||
|
@ -47,9 +47,9 @@ async function clearServerSessionInternal(event: H3Event, sessions: ServerSessio
|
|||
}
|
||||
|
||||
export async function clearServerSession(event: H3Event) {
|
||||
const sessions = await readSessions();
|
||||
const sessions = readSessions();
|
||||
if (await clearServerSessionInternal(event, sessions)) {
|
||||
await writeSessions(sessions);
|
||||
writeSessions(sessions);
|
||||
}
|
||||
deleteCookie(event, "session");
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ export async function setServerSession(
|
|||
authenticationSlug?: string,
|
||||
authenticationName?: string,
|
||||
) {
|
||||
const sessions = await readSessions();
|
||||
const sessions = readSessions();
|
||||
const runtimeConfig = useRuntimeConfig(event);
|
||||
await clearServerSessionInternal(event, sessions);
|
||||
|
||||
|
@ -78,14 +78,14 @@ export async function setServerSession(
|
|||
};
|
||||
|
||||
sessions.push(newSession);
|
||||
await writeSessions(sessions);
|
||||
writeSessions(sessions);
|
||||
await setSignedCookie(event, "session", String(newSession.id), runtimeConfig.sessionDiscardTimeout)
|
||||
return newSession;
|
||||
}
|
||||
|
||||
async function rotateSession(event: H3Event, sessions: ServerSession[], session: ServerSession) {
|
||||
const runtimeConfig = useRuntimeConfig(event);
|
||||
const users = await readUsers();
|
||||
const users = readUsers();
|
||||
const account = users.find(user => !user.deleted && user.id === session.accountId);
|
||||
const now = Date.now();
|
||||
const newSession: ServerSession = {
|
||||
|
@ -94,12 +94,12 @@ async function rotateSession(event: H3Event, sessions: ServerSession[], session:
|
|||
// Authentication provider is removed to avoid possibility of an infinite delay before using it.
|
||||
rotatesAtMs: now + runtimeConfig.sessionRotatesTimeout * 1000,
|
||||
discardAtMs: now + runtimeConfig.sessionDiscardTimeout * 1000,
|
||||
id: await nextSessionId(),
|
||||
id: nextSessionId(),
|
||||
};
|
||||
session.successor = newSession.id;
|
||||
session.expiresAtMs = Date.now() + 10 * 1000;
|
||||
sessions.push(newSession);
|
||||
await writeSessions(sessions);
|
||||
writeSessions(sessions);
|
||||
await setSignedCookie(event, "session", String(newSession.id), runtimeConfig.sessionDiscardTimeout)
|
||||
return newSession;
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ export async function getServerSession(event: H3Event, ignoreTaken: boolean) {
|
|||
const sessionCookie = await getSignedCookie(event, "session");
|
||||
if (sessionCookie) {
|
||||
const sessionId = parseInt(sessionCookie, 10);
|
||||
const sessions = await readSessions();
|
||||
const sessions = readSessions();
|
||||
const session = sessions.find(session => session.id === sessionId);
|
||||
if (session) {
|
||||
const nowMs = Date.now();
|
||||
|
@ -148,7 +148,7 @@ export async function requireServerSession(event: H3Event, message: string) {
|
|||
export async function requireServerSessionWithUser(event: H3Event) {
|
||||
const message = "User session required";
|
||||
const session = await requireServerSession(event, message);
|
||||
const users = await readUsers();
|
||||
const users = readUsers();
|
||||
const account = users.find(user => user.id === session.accountId);
|
||||
if (session.accountId === undefined || !account || account.deleted)
|
||||
throw createError({
|
||||
|
@ -163,7 +163,7 @@ export async function requireServerSessionWithUser(event: H3Event) {
|
|||
export async function requireServerSessionWithAdmin(event: H3Event) {
|
||||
const message = "Admin session required";
|
||||
const session = await requireServerSession(event, message);
|
||||
const users = await readUsers();
|
||||
const users = readUsers();
|
||||
const account = users.find(user => user.id === session.accountId);
|
||||
if (session.access !== "admin" || account?.type !== "admin") {
|
||||
throw createError({
|
||||
|
@ -176,9 +176,9 @@ export async function requireServerSessionWithAdmin(event: H3Event) {
|
|||
}
|
||||
|
||||
export async function serverSessionToApi(event: H3Event, session: ServerSession): Promise<ApiSession> {
|
||||
const users = await readUsers();
|
||||
const users = readUsers();
|
||||
const account = users.find(user => !user.deleted && user.id === session.accountId);
|
||||
const subscriptions = await readSubscriptions();
|
||||
const subscriptions = readSubscriptions();
|
||||
const push = Boolean(
|
||||
subscriptions.find(sub => sub.type === "push" && sub.sessionId === session.id)
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue