Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Use LRUCache for extendSessionOnUse #8683

Open
wants to merge 14 commits into
base: alpha
Choose a base branch
from
2 changes: 2 additions & 0 deletions spec/Auth.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ describe('Auth', () => {
updatedAt: updatedAt.toISOString(),
}
);
Parse.Server.cacheController.clear();
Copy link
Member

@mtrezza mtrezza Feb 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we convert this to async while already at it? Would that be a lot of work? Then we could also remove the 1s sleep below, which adds to the CI time.

await new Promise(resolve => setTimeout(resolve, 1000));
await session.fetch();
await new Promise(resolve => setTimeout(resolve, 1000));
await session.fetch();
Expand Down
60 changes: 26 additions & 34 deletions src/Auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { isDeepStrictEqual } from 'util';
import { getRequestObject, resolveError } from './triggers';
import Deprecator from './Deprecator/Deprecator';
import { logger } from './logger';
import RestQuery from './RestQuery';
import RestWrite from './RestWrite';

// An Auth object tells you who is requesting something and whether
Expand Down Expand Up @@ -73,39 +72,33 @@ const renewSessionIfNeeded = async ({ config, session, sessionToken }) => {
if (!config?.extendSessionOnUse) {
return;
}
clearTimeout(throttle[sessionToken]);
throttle[sessionToken] = setTimeout(async () => {
try {
if (!session) {
const { results } = await new RestQuery(
config,
master(config),
'_Session',
{ sessionToken },
{ limit: 1 }
).execute();
session = results[0];
}
const lastUpdated = new Date(session?.updatedAt);
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
if (lastUpdated > yesterday || !session) {
return;
}
const expiresAt = config.generateSessionExpiresAt();
await new RestWrite(
config,
master(config),
'_Session',
{ objectId: session.objectId },
{ expiresAt: Parse._encode(expiresAt) }
).execute();
} catch (e) {
if (e?.code !== Parse.Error.OBJECT_NOT_FOUND) {
logger.error('Could not update session expiry: ', e);
}
}
if (throttle[sessionToken]) {
return;
}
throttle[sessionToken] = true;
setTimeout(() => {
delete throttle[sessionToken];
dblythy marked this conversation as resolved.
Show resolved Hide resolved
}, 500);
try {
const lastUpdated = new Date(session?.updatedAt);
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
if (lastUpdated > yesterday || !session) {
return;
}
const expiresAt = config.generateSessionExpiresAt();
await new RestWrite(
config,
master(config),
'_Session',
{ objectId: session.objectId },
{ expiresAt: Parse._encode(expiresAt) }
).execute();
} catch (e) {
if (e?.code !== Parse.Error.OBJECT_NOT_FOUND) {
logger.error('Could not update session expiry: ', e);
}
}
};

// Returns a promise that resolves to an Auth object
Expand All @@ -120,7 +113,6 @@ const getAuthForSessionToken = async function ({
const userJSON = await cacheController.user.get(sessionToken);
if (userJSON) {
const cachedUser = Parse.Object.fromJSON(userJSON);
renewSessionIfNeeded({ config, sessionToken });
return Promise.resolve(
new Auth({
config,
Expand Down