Skip to content

Commit f1f9bde

Browse files
committed
Merge pull request #844 from ParsePlatform/nlutsenko.hooks
Move HooksController to use MongoCollection instead of direct Mongo access.
2 parents 75ae958 + 172da3a commit f1f9bde

File tree

2 files changed

+86
-99
lines changed

2 files changed

+86
-99
lines changed

src/Adapters/Storage/Mongo/MongoCollection.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
let mongodb = require('mongodb');
32
let Collection = mongodb.Collection;
43

@@ -18,8 +17,7 @@ export default class MongoCollection {
1817
return this._rawFind(query, { skip, limit, sort })
1918
.catch(error => {
2019
// Check for "no geoindex" error
21-
if (error.code != 17007 ||
22-
!error.message.match(/unable to find index for .geoNear/)) {
20+
if (error.code != 17007 || !error.message.match(/unable to find index for .geoNear/)) {
2321
throw error;
2422
}
2523
// Figure out what key needs an index
@@ -59,6 +57,13 @@ export default class MongoCollection {
5957
})
6058
}
6159

60+
// Atomically updates data in the database for a single (first) object that matched the query
61+
// If there is nothing that matches the query - does insert
62+
// Postgres Note: `INSERT ... ON CONFLICT UPDATE` that is available since 9.5.
63+
upsertOne(query, update) {
64+
return this._mongoCollection.update(query, update, { upsert: true });
65+
}
66+
6267
// Atomically find and delete an object based on query.
6368
// The result is the promise with an object that was in the database before deleting.
6469
// Postgres Note: Translates directly to `DELETE * FROM ... RETURNING *`, which will return data after delete is done.
@@ -70,6 +75,10 @@ export default class MongoCollection {
7075
});
7176
}
7277

78+
remove(query) {
79+
return this._mongoCollection.remove(query);
80+
}
81+
7382
drop() {
7483
return this._mongoCollection.drop();
7584
}

src/Controllers/HooksController.js

Lines changed: 74 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -8,104 +8,91 @@ import * as request from "request";
88
const DefaultHooksCollectionName = "_Hooks";
99

1010
export class HooksController {
11-
_applicationId: string;
12-
_collectionPrefix: string;
11+
_applicationId:string;
12+
_collectionPrefix:string;
1313
_collection;
1414

15-
constructor(applicationId: string, collectionPrefix: string = '') {
15+
constructor(applicationId:string, collectionPrefix:string = '') {
1616
this._applicationId = applicationId;
1717
this._collectionPrefix = collectionPrefix;
1818
}
19-
20-
database() {
21-
return DatabaseAdapter.getDatabaseConnection(this._applicationId, this._collectionPrefix);
19+
20+
load() {
21+
return this._getHooks().then(hooks => {
22+
hooks = hooks || [];
23+
hooks.forEach((hook) => {
24+
this.addHookToTriggers(hook);
25+
});
26+
});
2227
}
23-
24-
collection() {
28+
29+
getCollection() {
2530
if (this._collection) {
2631
return Promise.resolve(this._collection)
2732
}
28-
return this.database().rawCollection(DefaultHooksCollectionName).then((collection) => {
33+
34+
let database = DatabaseAdapter.getDatabaseConnection(this._applicationId, this._collectionPrefix);
35+
return database.adaptiveCollection(DefaultHooksCollectionName).then(collection => {
2936
this._collection = collection;
3037
return collection;
3138
});
3239
}
33-
40+
3441
getFunction(functionName) {
35-
return this.getOne({functionName: functionName})
42+
return this._getHooks({ functionName: functionName }, 1).then(results => results[0]);
3643
}
37-
44+
3845
getFunctions() {
39-
return this.get({functionName: { $exists: true }})
46+
return this._getHooks({ functionName: { $exists: true } });
4047
}
41-
48+
4249
getTrigger(className, triggerName) {
43-
return this.getOne({className: className, triggerName: triggerName })
50+
return this._getHooks({ className: className, triggerName: triggerName }, 1).then(results => results[0]);
4451
}
45-
52+
4653
getTriggers() {
47-
return this.get({className: { $exists: true }, triggerName: { $exists: true }})
54+
return this._getHooks({ className: { $exists: true }, triggerName: { $exists: true } });
4855
}
49-
56+
5057
deleteFunction(functionName) {
5158
triggers.removeFunction(functionName, this._applicationId);
52-
return this.delete({functionName: functionName});
59+
return this._removeHooks({ functionName: functionName });
5360
}
54-
61+
5562
deleteTrigger(className, triggerName) {
5663
triggers.removeTrigger(triggerName, className, this._applicationId);
57-
return this.delete({className: className, triggerName: triggerName});
58-
}
59-
60-
delete(query) {
61-
return this.collection().then((collection) => {
62-
return collection.remove(query)
63-
}).then( (res) => {
64-
return {};
65-
}, 1);
64+
return this._removeHooks({ className: className, triggerName: triggerName });
6665
}
67-
68-
getOne(query) {
69-
return this.collection()
70-
.then(coll => coll.findOne(query, {_id: 0}))
71-
.then(hook => {
72-
return hook;
73-
});
66+
67+
_getHooks(query, limit) {
68+
let options = limit ? { limit: limit } : undefined;
69+
return this.getCollection().then(collection => collection.find(query, options));
7470
}
75-
76-
get(query) {
77-
return this.collection()
78-
.then(coll => coll.find(query, {_id: 0}).toArray())
79-
.then(hooks => {
80-
return hooks;
71+
72+
_removeHooks(query) {
73+
return this.getCollection().then(collection => {
74+
return collection.remove(query);
75+
}).then(() => {
76+
return {};
8177
});
8278
}
83-
84-
getHooks() {
85-
return this.collection()
86-
.then(coll => coll.find({}, {_id: 0}).toArray())
87-
.then(hooks => {
88-
return hooks;
89-
}, () => ([]))
90-
}
91-
79+
9280
saveHook(hook) {
93-
9481
var query;
9582
if (hook.functionName && hook.url) {
96-
query = {functionName: hook.functionName }
83+
query = { functionName: hook.functionName }
9784
} else if (hook.triggerName && hook.className && hook.url) {
9885
query = { className: hook.className, triggerName: hook.triggerName }
9986
} else {
10087
throw new Parse.Error(143, "invalid hook declaration");
10188
}
102-
return this.collection().then((collection) => {
103-
return collection.update(query, hook, {upsert: true})
104-
}).then(function(res){
105-
return hook;
106-
})
89+
return this.getCollection()
90+
.then(collection => collection.upsertOne(query, hook))
91+
.then(() => {
92+
return hook;
93+
});
10794
}
108-
95+
10996
addHookToTriggers(hook) {
11097
var wrappedFunction = wrapToHTTPRequest(hook);
11198
wrappedFunction.url = hook.url;
@@ -114,13 +101,13 @@ export class HooksController {
114101
} else {
115102
triggers.addFunction(hook.functionName, wrappedFunction, null, this._applicationId);
116103
}
117-
}
118-
104+
}
105+
119106
addHook(hook) {
120107
this.addHookToTriggers(hook);
121108
return this.saveHook(hook);
122109
}
123-
110+
124111
createOrUpdateHook(aHook) {
125112
var hook;
126113
if (aHook && aHook.functionName && aHook.url) {
@@ -132,69 +119,59 @@ export class HooksController {
132119
hook.className = aHook.className;
133120
hook.url = aHook.url;
134121
hook.triggerName = aHook.triggerName;
135-
122+
136123
} else {
137124
throw new Parse.Error(143, "invalid hook declaration");
138-
}
139-
125+
}
126+
140127
return this.addHook(hook);
141128
};
142-
129+
143130
createHook(aHook) {
144131
if (aHook.functionName) {
145132
return this.getFunction(aHook.functionName).then((result) => {
146133
if (result) {
147-
throw new Parse.Error(143,`function name: ${aHook.functionName} already exits`);
134+
throw new Parse.Error(143, `function name: ${aHook.functionName} already exits`);
148135
} else {
149136
return this.createOrUpdateHook(aHook);
150137
}
151138
});
152139
} else if (aHook.className && aHook.triggerName) {
153140
return this.getTrigger(aHook.className, aHook.triggerName).then((result) => {
154141
if (result) {
155-
throw new Parse.Error(143,`class ${aHook.className} already has trigger ${aHook.triggerName}`);
142+
throw new Parse.Error(143, `class ${aHook.className} already has trigger ${aHook.triggerName}`);
156143
}
157144
return this.createOrUpdateHook(aHook);
158145
});
159146
}
160-
147+
161148
throw new Parse.Error(143, "invalid hook declaration");
162149
};
163-
150+
164151
updateHook(aHook) {
165152
if (aHook.functionName) {
166153
return this.getFunction(aHook.functionName).then((result) => {
167154
if (result) {
168155
return this.createOrUpdateHook(aHook);
169156
}
170-
throw new Parse.Error(143,`no function named: ${aHook.functionName} is defined`);
157+
throw new Parse.Error(143, `no function named: ${aHook.functionName} is defined`);
171158
});
172159
} else if (aHook.className && aHook.triggerName) {
173160
return this.getTrigger(aHook.className, aHook.triggerName).then((result) => {
174161
if (result) {
175162
return this.createOrUpdateHook(aHook);
176163
}
177-
throw new Parse.Error(143,`class ${aHook.className} does not exist`);
164+
throw new Parse.Error(143, `class ${aHook.className} does not exist`);
178165
});
179166
}
180167
throw new Parse.Error(143, "invalid hook declaration");
181168
};
182-
183-
load() {
184-
return this.getHooks().then((hooks) => {
185-
hooks = hooks || [];
186-
hooks.forEach((hook) => {
187-
this.addHookToTriggers(hook);
188-
});
189-
});
190-
}
191-
192169
}
193170

194171
function wrapToHTTPRequest(hook) {
195-
return function(req, res) {
196-
var jsonBody = {};
197-
for(var i in req) {
172+
return (req, res) => {
173+
let jsonBody = {};
174+
for (var i in req) {
198175
jsonBody[i] = req[i];
199176
}
200177
if (req.object) {
@@ -205,30 +182,31 @@ function wrapToHTTPRequest(hook) {
205182
jsonBody.original = req.original.toJSON();
206183
jsonBody.original.className = req.original.className;
207184
}
208-
var jsonRequest = {};
209-
jsonRequest.headers = {
210-
'Content-Type': 'application/json'
211-
}
212-
jsonRequest.body = JSON.stringify(jsonBody);
213-
214-
request.post(hook.url, jsonRequest, function(err, httpResponse, body){
185+
let jsonRequest = {
186+
headers: {
187+
'Content-Type': 'application/json'
188+
},
189+
body: JSON.stringify(jsonBody)
190+
};
191+
192+
request.post(hook.url, jsonRequest, function (err, httpResponse, body) {
215193
var result;
216194
if (body) {
217195
if (typeof body == "string") {
218196
try {
219197
body = JSON.parse(body);
220-
} catch(e) {
221-
err = {error: "Malformed response", code: -1};
198+
} catch (e) {
199+
err = { error: "Malformed response", code: -1 };
222200
}
223201
}
224202
if (!err) {
225203
result = body.success;
226-
err = body.error;
204+
err = body.error;
227205
}
228206
}
229207
if (err) {
230208
return res.error(err);
231-
} else {
209+
} else {
232210
return res.success(result);
233211
}
234212
});

0 commit comments

Comments
 (0)