Skip to content

Commit 6258a6a

Browse files
authored
fix: Using Parse Server option extendSessionOnUse does not correctly clear memory and functions as a debounce instead of a throttle (#8683)
1 parent 3cb3c5f commit 6258a6a

File tree

2 files changed

+40
-32
lines changed

2 files changed

+40
-32
lines changed

spec/Auth.spec.js

+2
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ describe('Auth', () => {
106106
updatedAt: updatedAt.toISOString(),
107107
}
108108
);
109+
Parse.Server.cacheController.clear();
110+
await new Promise(resolve => setTimeout(resolve, 1000));
109111
await session.fetch();
110112
await new Promise(resolve => setTimeout(resolve, 1000));
111113
await session.fetch();

src/Auth.js

+38-32
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const Parse = require('parse/node');
22
import { isDeepStrictEqual } from 'util';
33
import { getRequestObject, resolveError } from './triggers';
44
import { logger } from './logger';
5+
import { LRUCache as LRU } from 'lru-cache';
56
import RestQuery from './RestQuery';
67
import RestWrite from './RestWrite';
78

@@ -67,6 +68,10 @@ function nobody(config) {
6768
return new Auth({ config, isMaster: false });
6869
}
6970

71+
const throttle = new LRU({
72+
max: 10000,
73+
ttl: 500,
74+
});
7075
/**
7176
* Checks whether session should be updated based on last update time & session length.
7277
*/
@@ -78,44 +83,45 @@ function shouldUpdateSessionExpiry(config, session) {
7883
return lastUpdated <= skipRange;
7984
}
8085

81-
const throttle = {};
8286
const renewSessionIfNeeded = async ({ config, session, sessionToken }) => {
8387
if (!config?.extendSessionOnUse) {
8488
return;
8589
}
86-
clearTimeout(throttle[sessionToken]);
87-
throttle[sessionToken] = setTimeout(async () => {
88-
try {
89-
if (!session) {
90-
const query = await RestQuery({
91-
method: RestQuery.Method.get,
92-
config,
93-
auth: master(config),
94-
runBeforeFind: false,
95-
className: '_Session',
96-
restWhere: { sessionToken },
97-
restOptions: { limit: 1 },
98-
});
99-
const { results } = await query.execute();
100-
session = results[0];
101-
}
102-
if (!shouldUpdateSessionExpiry(config, session) || !session) {
103-
return;
104-
}
105-
const expiresAt = config.generateSessionExpiresAt();
106-
await new RestWrite(
90+
if (throttle.get(sessionToken)) {
91+
return;
92+
}
93+
throttle.set(sessionToken, true);
94+
try {
95+
if (!session) {
96+
const query = await RestQuery({
97+
method: RestQuery.Method.get,
10798
config,
108-
master(config),
109-
'_Session',
110-
{ objectId: session.objectId },
111-
{ expiresAt: Parse._encode(expiresAt) }
112-
).execute();
113-
} catch (e) {
114-
if (e?.code !== Parse.Error.OBJECT_NOT_FOUND) {
115-
logger.error('Could not update session expiry: ', e);
116-
}
99+
auth: master(config),
100+
runBeforeFind: false,
101+
className: '_Session',
102+
restWhere: { sessionToken },
103+
restOptions: { limit: 1 },
104+
});
105+
const { results } = await query.execute();
106+
session = results[0];
107+
}
108+
109+
if (!shouldUpdateSessionExpiry(config, session) || !session) {
110+
return;
117111
}
118-
}, 500);
112+
const expiresAt = config.generateSessionExpiresAt();
113+
await new RestWrite(
114+
config,
115+
master(config),
116+
'_Session',
117+
{ objectId: session.objectId },
118+
{ expiresAt: Parse._encode(expiresAt) }
119+
).execute();
120+
} catch (e) {
121+
if (e?.code !== Parse.Error.OBJECT_NOT_FOUND) {
122+
logger.error('Could not update session expiry: ', e);
123+
}
124+
}
119125
};
120126

121127
// Returns a promise that resolves to an Auth object

0 commit comments

Comments
 (0)