Merge pull request #694 from ParsePlatform/nlutsenko.cache

Unify and cleanup cache.js.
This commit is contained in:
Nikita Lutsenko
2016-02-29 12:49:04 -08:00
11 changed files with 56 additions and 78 deletions

View File

@@ -52,13 +52,13 @@ delete defaultConfiguration.cloud;
// Allows testing specific configurations of Parse Server // Allows testing specific configurations of Parse Server
var setServerConfiguration = configuration => { var setServerConfiguration = configuration => {
api = new ParseServer(configuration);
app = express();
app.use('/1', api);
cache.clearCache();
server.close(); server.close();
cache.clearCache();
app = express();
api = new ParseServer(configuration);
app.use('/1', api);
server = app.listen(port); server = app.listen(port);
} };
var restoreServerConfiguration = () => setServerConfiguration(defaultConfiguration); var restoreServerConfiguration = () => setServerConfiguration(defaultConfiguration);

View File

@@ -43,7 +43,7 @@ function nobody(config) {
// Returns a promise that resolves to an Auth object // Returns a promise that resolves to an Auth object
var getAuthForSessionToken = function(config, sessionToken) { var getAuthForSessionToken = function(config, sessionToken) {
var cachedUser = cache.getUser(sessionToken); var cachedUser = cache.users.get(sessionToken);
if (cachedUser) { if (cachedUser) {
return Promise.resolve(new Auth(config, false, cachedUser)); return Promise.resolve(new Auth(config, false, cachedUser));
} }
@@ -65,8 +65,8 @@ var getAuthForSessionToken = function(config, sessionToken) {
delete obj.password; delete obj.password;
obj['className'] = '_User'; obj['className'] = '_User';
obj['sessionToken'] = sessionToken; obj['sessionToken'] = sessionToken;
var userObject = Parse.Object.fromJSON(obj); let userObject = Parse.Object.fromJSON(obj);
cache.setUser(sessionToken, userObject); cache.users.set(sessionToken, userObject);
return new Auth(config, false, userObject); return new Auth(config, false, userObject);
}); });
}; };

View File

@@ -7,15 +7,12 @@ import cache from './cache';
export class Config { export class Config {
constructor(applicationId: string, mount: string) { constructor(applicationId: string, mount: string) {
let DatabaseAdapter = require('./DatabaseAdapter'); let DatabaseAdapter = require('./DatabaseAdapter');
let cacheInfo = cache.apps.get(applicationId);
let cacheInfo = cache.apps[applicationId]; if (!cacheInfo) {
this.valid = !!cacheInfo;
if (!this.valid) {
return; return;
} }
this.applicationId = applicationId; this.applicationId = applicationId;
this.collectionPrefix = cacheInfo.collectionPrefix || '';
this.masterKey = cacheInfo.masterKey; this.masterKey = cacheInfo.masterKey;
this.clientKey = cacheInfo.clientKey; this.clientKey = cacheInfo.clientKey;
this.javascriptKey = cacheInfo.javascriptKey; this.javascriptKey = cacheInfo.javascriptKey;
@@ -25,7 +22,7 @@ export class Config {
this.facebookAppIds = cacheInfo.facebookAppIds; this.facebookAppIds = cacheInfo.facebookAppIds;
this.enableAnonymousUsers = cacheInfo.enableAnonymousUsers; this.enableAnonymousUsers = cacheInfo.enableAnonymousUsers;
this.allowClientClassCreation = cacheInfo.allowClientClassCreation; this.allowClientClassCreation = cacheInfo.allowClientClassCreation;
this.database = DatabaseAdapter.getDatabaseConnection(applicationId, this.collectionPrefix); this.database = DatabaseAdapter.getDatabaseConnection(applicationId, cacheInfo.collectionPrefix);
this.hooksController = cacheInfo.hooksController; this.hooksController = cacheInfo.hooksController;
this.filesController = cacheInfo.filesController; this.filesController = cacheInfo.filesController;
this.pushController = cacheInfo.pushController; this.pushController = cacheInfo.pushController;

View File

@@ -75,7 +75,7 @@ export class UsersRouter extends ClassesRouter {
} }
let user; let user;
return req.database.find('_User', { username: req.body.username }) return req.config.database.find('_User', { username: req.body.username })
.then((results) => { .then((results) => {
if (!results.length) { if (!results.length) {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.');

View File

@@ -1,45 +1,35 @@
export var apps = {}; /** @flow weak */
export var stats = {};
export var isLoaded = false;
export var users = {};
export function getApp(app, callback) { export function CacheStore<KeyType, ValueType>() {
if (apps[app]) return callback(true, apps[app]); let dataStore: {[id:KeyType]:ValueType} = {};
return callback(false); return {
get: (key: KeyType): ValueType => {
return dataStore[key];
},
set(key: KeyType, value: ValueType): void {
dataStore[key] = value;
},
remove(key: KeyType): void {
delete dataStore[key];
},
clear(): void {
dataStore = {};
}
};
} }
export function updateStat(key, value) { const apps = CacheStore();
stats[key] = value; const users = CacheStore();
}
export function getUser(sessionToken) {
if (users[sessionToken]) return users[sessionToken];
return undefined;
}
export function setUser(sessionToken, userObject) {
users[sessionToken] = userObject;
}
export function clearUser(sessionToken) {
delete users[sessionToken];
}
//So far used only in tests //So far used only in tests
export function clearCache() { export function clearCache(): void {
apps = {}; apps.clear();
stats = {}; users.clear();
users = {};
} }
export default { export default {
apps, apps,
stats, users,
isLoaded,
getApp,
updateStat,
clearUser,
getUser,
setUser,
clearCache, clearCache,
CacheStore
}; };

View File

@@ -126,7 +126,7 @@ function ParseServer({
const loggerController = new LoggerController(loggerControllerAdapter); const loggerController = new LoggerController(loggerControllerAdapter);
const hooksController = new HooksController(appId, collectionPrefix); const hooksController = new HooksController(appId, collectionPrefix);
cache.apps[appId] = { cache.apps.set(appId, {
masterKey: masterKey, masterKey: masterKey,
collectionPrefix: collectionPrefix, collectionPrefix: collectionPrefix,
clientKey: clientKey, clientKey: clientKey,
@@ -142,11 +142,11 @@ function ParseServer({
enableAnonymousUsers: enableAnonymousUsers, enableAnonymousUsers: enableAnonymousUsers,
allowClientClassCreation: allowClientClassCreation, allowClientClassCreation: allowClientClassCreation,
oauth: oauth oauth: oauth
}; });
// To maintain compatibility. TODO: Remove in v2.1 // To maintain compatibility. TODO: Remove in v2.1
if (process.env.FACEBOOK_APP_ID) { if (process.env.FACEBOOK_APP_ID) {
cache.apps[appId]['facebookAppIds'].push(process.env.FACEBOOK_APP_ID); cache.apps.get(appId)['facebookAppIds'].push(process.env.FACEBOOK_APP_ID);
} }
// This app serves the Parse API directly. // This app serves the Parse API directly.
@@ -220,13 +220,6 @@ function addParseCloud() {
global.Parse = Parse; global.Parse = Parse;
} }
function getClassName(parseClass) {
if (parseClass && parseClass.className) {
return parseClass.className;
}
return parseClass;
}
module.exports = { module.exports = {
ParseServer: ParseServer, ParseServer: ParseServer,
S3Adapter: S3Adapter S3Adapter: S3Adapter

View File

@@ -35,7 +35,7 @@ function handleParseHeaders(req, res, next) {
var fileViaJSON = false; var fileViaJSON = false;
if (!info.appId || !cache.apps[info.appId]) { if (!info.appId || !cache.apps.get(info.appId)) {
// See if we can find the app id on the body. // See if we can find the app id on the body.
if (req.body instanceof Buffer) { if (req.body instanceof Buffer) {
// The only chance to find the app id is if this is a file // The only chance to find the app id is if this is a file
@@ -44,12 +44,10 @@ function handleParseHeaders(req, res, next) {
fileViaJSON = true; fileViaJSON = true;
} }
if (req.body && req.body._ApplicationId if (req.body &&
&& cache.apps[req.body._ApplicationId] req.body._ApplicationId &&
&& ( cache.apps.get(req.body._ApplicationId) &&
!info.masterKey (!info.masterKey || cache.apps.get(req.body._ApplicationId).masterKey === info.masterKey)
||
cache.apps[req.body._ApplicationId]['masterKey'] === info.masterKey)
) { ) {
info.appId = req.body._ApplicationId; info.appId = req.body._ApplicationId;
info.javascriptKey = req.body._JavaScriptKey || ''; info.javascriptKey = req.body._JavaScriptKey || '';
@@ -84,9 +82,8 @@ function handleParseHeaders(req, res, next) {
req.body = new Buffer(base64, 'base64'); req.body = new Buffer(base64, 'base64');
} }
info.app = cache.apps[info.appId]; info.app = cache.apps.get(info.appId);
req.config = new Config(info.appId, mount); req.config = new Config(info.appId, mount);
req.database = req.config.database;
req.info = info; req.info = info;
var isMaster = (info.masterKey === req.config.masterKey); var isMaster = (info.masterKey === req.config.masterKey);

View File

@@ -1,2 +1,2 @@
/* @flow */ /** @flow */
export default (errorMessage: string) => {throw errorMessage} export default (errorMessage: string): any => { throw errorMessage }

View File

@@ -46,7 +46,7 @@ function del(config, auth, className, objectId) {
.then((response) => { .then((response) => {
if (response && response.results && response.results.length) { if (response && response.results && response.results.length) {
response.results[0].className = className; response.results[0].className = className;
cache.clearUser(response.results[0].sessionToken); cache.users.remove(response.results[0].sessionToken);
inflatedObject = Parse.Object.fromJSON(response.results[0]); inflatedObject = Parse.Object.fromJSON(response.results[0]);
return triggers.maybeRunTrigger(triggers.Types.beforeDelete, auth, inflatedObject, null, config.applicationId); return triggers.maybeRunTrigger(triggers.Types.beforeDelete, auth, inflatedObject, null, config.applicationId);
} }

View File

@@ -10,10 +10,11 @@ var router = express.Router();
// creates a unique app in the cache, with a collection prefix // creates a unique app in the cache, with a collection prefix
function createApp(req, res) { function createApp(req, res) {
var appId = cryptoUtils.randomHexString(32); var appId = cryptoUtils.randomHexString(32);
cache.apps[appId] = { // TODO: (nlutsenko) This doesn't work and should die, since there are no controllers on this configuration.
cache.apps.set(appId, {
'collectionPrefix': appId + '_', 'collectionPrefix': appId + '_',
'masterKey': 'master' 'masterKey': 'master'
}; });
var keys = { var keys = {
'application_id': appId, 'application_id': appId,
'client_key': 'unused', 'client_key': 'unused',
@@ -31,7 +32,7 @@ function clearApp(req, res) {
if (!req.auth.isMaster) { if (!req.auth.isMaster) {
return res.status(401).send({"error": "unauthorized"}); return res.status(401).send({"error": "unauthorized"});
} }
req.database.deleteEverything().then(() => { return req.config.database.deleteEverything().then(() => {
res.status(200).send({}); res.status(200).send({});
}); });
} }
@@ -41,8 +42,8 @@ function dropApp(req, res) {
if (!req.auth.isMaster) { if (!req.auth.isMaster) {
return res.status(401).send({"error": "unauthorized"}); return res.status(401).send({"error": "unauthorized"});
} }
req.database.deleteEverything().then(() => { return req.config.database.deleteEverything().then(() => {
delete cache.apps[req.config.applicationId]; cache.apps.remove(req.config.applicationId);
res.status(200).send({}); res.status(200).send({});
}); });
} }

View File

@@ -157,8 +157,8 @@ export function maybeRunTrigger(triggerType, auth, parseObject, originalParseObj
var response = getResponseObject(request, resolve, reject); var response = getResponseObject(request, resolve, reject);
// Force the current Parse app before the trigger // Force the current Parse app before the trigger
Parse.applicationId = applicationId; Parse.applicationId = applicationId;
Parse.javascriptKey = cache.apps[applicationId].javascriptKey || ''; Parse.javascriptKey = cache.apps.get(applicationId).javascriptKey || '';
Parse.masterKey = cache.apps[applicationId].masterKey; Parse.masterKey = cache.apps.get(applicationId).masterKey;
trigger(request, response); trigger(request, response);
}); });
}; };