Skip to content

Commit 3d7d269

Browse files
authored
Add EventuallyQueue API (#1291)
* Add EventuallyQueue API * Add saveEventually and destroyEventually * Documentation * Add in memory cache, prevent raise conditions * oops
1 parent c8270a7 commit 3d7d269

File tree

10 files changed

+1208
-3
lines changed

10 files changed

+1208
-3
lines changed
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
'use strict';
2+
3+
const assert = require('assert');
4+
const Parse = require('../../node');
5+
const sleep = require('./sleep');
6+
7+
describe('Parse EventuallyQueue', () => {
8+
beforeEach(async () => {
9+
await Parse.EventuallyQueue.clear();
10+
});
11+
12+
it('can queue save object', async () => {
13+
const object = new TestObject({ test: 'test' });
14+
await object.save();
15+
object.set('foo', 'bar');
16+
await Parse.EventuallyQueue.save(object);
17+
await Parse.EventuallyQueue.sendQueue();
18+
19+
const query = new Parse.Query(TestObject);
20+
const result = await query.get(object.id);
21+
assert.strictEqual(result.get('foo'), 'bar');
22+
23+
const length = await Parse.EventuallyQueue.length();
24+
assert.strictEqual(length, 0);
25+
});
26+
27+
it('can queue destroy object', async () => {
28+
const object = new TestObject({ test: 'test' });
29+
await object.save();
30+
await Parse.EventuallyQueue.destroy(object);
31+
await Parse.EventuallyQueue.sendQueue();
32+
33+
const query = new Parse.Query(TestObject);
34+
query.equalTo('objectId', object.id);
35+
const results = await query.find();
36+
assert.strictEqual(results.length, 0);
37+
38+
const length = await Parse.EventuallyQueue.length();
39+
assert.strictEqual(length, 0);
40+
});
41+
42+
it('can queue multiple object', async () => {
43+
const obj1 = new TestObject({ foo: 'bar' });
44+
const obj2 = new TestObject({ foo: 'baz' });
45+
const obj3 = new TestObject({ foo: 'bag' });
46+
await Parse.EventuallyQueue.save(obj1);
47+
await Parse.EventuallyQueue.save(obj2);
48+
await Parse.EventuallyQueue.save(obj3);
49+
50+
let length = await Parse.EventuallyQueue.length();
51+
assert.strictEqual(length, 3);
52+
53+
await Parse.EventuallyQueue.sendQueue();
54+
55+
const query = new Parse.Query(TestObject);
56+
query.ascending('createdAt');
57+
const results = await query.find();
58+
assert.strictEqual(results.length, 3);
59+
assert.strictEqual(results[0].get('foo'), 'bar');
60+
assert.strictEqual(results[1].get('foo'), 'baz');
61+
assert.strictEqual(results[2].get('foo'), 'bag');
62+
63+
length = await Parse.EventuallyQueue.length();
64+
assert.strictEqual(length, 0);
65+
66+
// TODO: Properly handle SingleInstance
67+
await Parse.EventuallyQueue.destroy(results[0]);
68+
await Parse.EventuallyQueue.destroy(results[1]);
69+
await Parse.EventuallyQueue.destroy(results[2]);
70+
71+
length = await Parse.EventuallyQueue.length();
72+
assert.strictEqual(length, 3);
73+
74+
await Parse.EventuallyQueue.sendQueue();
75+
const objects = await query.find();
76+
assert.strictEqual(objects.length, 0);
77+
});
78+
79+
it('can queue destroy for object that does not exist', async () => {
80+
const object = new TestObject({ test: 'test' });
81+
await object.save();
82+
await object.destroy();
83+
await Parse.EventuallyQueue.destroy(object);
84+
await Parse.EventuallyQueue.sendQueue();
85+
86+
const length = await Parse.EventuallyQueue.length();
87+
assert.strictEqual(length, 0);
88+
});
89+
90+
it('can queue destroy then save', async () => {
91+
const object = new TestObject({ hash: 'test' });
92+
await Parse.EventuallyQueue.destroy(object);
93+
await Parse.EventuallyQueue.save(object);
94+
await Parse.EventuallyQueue.sendQueue();
95+
96+
const query = new Parse.Query(TestObject);
97+
query.equalTo('hash', 'test');
98+
const results = await query.find();
99+
assert.strictEqual(results.length, 1);
100+
101+
const length = await Parse.EventuallyQueue.length();
102+
assert.strictEqual(length, 0);
103+
});
104+
105+
it('can queue unsaved object with hash', async () => {
106+
const hash = 'secret';
107+
const object = new TestObject({ test: 'test' });
108+
object.set('hash', hash);
109+
await Parse.EventuallyQueue.save(object);
110+
await Parse.EventuallyQueue.sendQueue();
111+
112+
const query = new Parse.Query(TestObject);
113+
query.equalTo('hash', hash);
114+
const results = await query.find();
115+
assert.strictEqual(results.length, 1);
116+
});
117+
118+
it('can queue saved object and unsaved with hash', async () => {
119+
const hash = 'ransom+salt';
120+
const object = new TestObject({ test: 'test' });
121+
object.set('hash', hash);
122+
await Parse.EventuallyQueue.save(object);
123+
await Parse.EventuallyQueue.sendQueue();
124+
125+
let query = new Parse.Query(TestObject);
126+
query.equalTo('hash', hash);
127+
const results = await query.find();
128+
assert.strictEqual(results.length, 1);
129+
130+
const unsaved = new TestObject({ hash, foo: 'bar' });
131+
await Parse.EventuallyQueue.save(unsaved);
132+
await Parse.EventuallyQueue.sendQueue();
133+
134+
query = new Parse.Query(TestObject);
135+
query.equalTo('hash', hash);
136+
const hashes = await query.find();
137+
assert.strictEqual(hashes.length, 1);
138+
assert.strictEqual(hashes[0].get('foo'), 'bar');
139+
});
140+
141+
it('can queue same object but override undefined fields', async () => {
142+
const object = new Parse.Object('TestObject');
143+
object.set('foo', 'bar');
144+
object.set('test', '1234');
145+
await Parse.EventuallyQueue.save(object);
146+
147+
object.set('foo', undefined);
148+
await Parse.EventuallyQueue.save(object);
149+
150+
const length = await Parse.EventuallyQueue.length();
151+
assert.strictEqual(length, 1);
152+
153+
const queue = await Parse.EventuallyQueue.getQueue();
154+
assert.strictEqual(queue[0].object.foo, 'bar');
155+
assert.strictEqual(queue[0].object.test, '1234');
156+
});
157+
158+
it('can poll server', async () => {
159+
const object = new TestObject({ test: 'test' });
160+
await object.save();
161+
object.set('foo', 'bar');
162+
await Parse.EventuallyQueue.save(object);
163+
Parse.EventuallyQueue.poll();
164+
assert.ok(Parse.EventuallyQueue.isPolling());
165+
166+
await sleep(4000);
167+
const query = new Parse.Query(TestObject);
168+
const result = await query.get(object.id);
169+
assert.strictEqual(result.get('foo'), 'bar');
170+
171+
const length = await Parse.EventuallyQueue.length();
172+
assert.strictEqual(length, 0);
173+
assert.strictEqual(Parse.EventuallyQueue.isPolling(), false);
174+
});
175+
176+
it('can clear queue', async () => {
177+
const object = new TestObject({ test: 'test' });
178+
await object.save();
179+
await Parse.EventuallyQueue.save(object);
180+
const q = await Parse.EventuallyQueue.getQueue();
181+
assert.strictEqual(q.length, 1);
182+
183+
await Parse.EventuallyQueue.clear();
184+
const length = await Parse.EventuallyQueue.length();
185+
assert.strictEqual(length, 0);
186+
});
187+
188+
it('can saveEventually', async done => {
189+
const parseServer = await reconfigureServer();
190+
const object = new TestObject({ hash: 'saveSecret' });
191+
await parseServer.handleShutdown();
192+
parseServer.server.close(async () => {
193+
await object.saveEventually();
194+
let length = await Parse.EventuallyQueue.length();
195+
assert(Parse.EventuallyQueue.isPolling());
196+
assert.strictEqual(length, 1);
197+
198+
await reconfigureServer({});
199+
await sleep(3000); // Wait for polling
200+
201+
assert.strictEqual(Parse.EventuallyQueue.isPolling(), false);
202+
length = await Parse.EventuallyQueue.length();
203+
assert.strictEqual(length, 0);
204+
205+
const query = new Parse.Query(TestObject);
206+
query.equalTo('hash', 'saveSecret');
207+
const results = await query.find();
208+
assert.strictEqual(results.length, 1);
209+
done();
210+
});
211+
});
212+
213+
it('can destroyEventually', async done => {
214+
const parseServer = await reconfigureServer();
215+
const object = new TestObject({ hash: 'deleteSecret' });
216+
await object.save();
217+
await parseServer.handleShutdown();
218+
parseServer.server.close(async () => {
219+
await object.destroyEventually();
220+
let length = await Parse.EventuallyQueue.length();
221+
assert(Parse.EventuallyQueue.isPolling());
222+
assert.strictEqual(length, 1);
223+
224+
await reconfigureServer({});
225+
await sleep(3000); // Wait for polling
226+
227+
assert.strictEqual(Parse.EventuallyQueue.isPolling(), false);
228+
length = await Parse.EventuallyQueue.length();
229+
assert.strictEqual(length, 0);
230+
231+
const query = new Parse.Query(TestObject);
232+
query.equalTo('hash', 'deleteSecret');
233+
const results = await query.find();
234+
assert.strictEqual(results.length, 0);
235+
done();
236+
});
237+
});
238+
});

integration/test/helper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
1+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
22

33
const ParseServer = require('parse-server').default;
44
const CustomAuth = require('./CustomAuth');

jasmine.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
"*Test.js"
88
],
99
"random": false,
10-
"timeout": 5000
10+
"timeout": 10000
1111
}

0 commit comments

Comments
 (0)