Skip to content

Commit 479e82c

Browse files
committed
working idempotency on postgres
1 parent 12ae0bf commit 479e82c

File tree

3 files changed

+32
-21
lines changed

3 files changed

+32
-21
lines changed

spec/Idempotency.spec.js

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ describe('Idempotency', () => {
1111
/** Enable TTL expiration simulated by removing entry instead of waiting for MongoDB TTL monitor which
1212
runs only every 60s, so it can take up to 119s until entry removal - ain't nobody got time for that */
1313
const SIMULATE_TTL = true;
14-
const applicationId = "testIdempotency";
14+
const ttl = 2;
1515

1616
// Helpers
1717
async function deleteRequestEntry(reqId) {
18-
const config = Config.get(applicationId);
18+
const config = Config.get(Parse.applicationId);
1919
const res = await rest.find(
2020
config,
2121
auth.master(config),
@@ -27,7 +27,7 @@ describe('Idempotency', () => {
2727
}
2828
async function setup(options) {
2929
await reconfigureServer({
30-
appId: applicationId,
30+
appId: Parse.applicationId,
3131
masterKey: Parse.masterKey,
3232
serverURL: Parse.serverURL,
3333
idempotencyOptions: options,
@@ -40,9 +40,10 @@ describe('Idempotency', () => {
4040
}
4141
await setup({
4242
paths: ['functions/.*', 'jobs/.*', 'classes/.*', 'users', 'installations'],
43-
ttl: 30,
43+
ttl: ttl,
4444
});
4545
});
46+
4647
// Tests
4748
it('should enforce idempotency for cloud code function', async () => {
4849
let counter = 0;
@@ -58,7 +59,7 @@ describe('Idempotency', () => {
5859
'X-Parse-Request-Id': 'abc-123',
5960
},
6061
};
61-
expect(Config.get(applicationId).idempotencyOptions.ttl).toBe(30);
62+
expect(Config.get(Parse.applicationId).idempotencyOptions.ttl).toBe(ttl);
6263
await request(params);
6364
await request(params).then(fail, e => {
6465
expect(e.status).toEqual(400);
@@ -76,7 +77,7 @@ describe('Idempotency', () => {
7677
method: 'POST',
7778
url: 'http://localhost:8378/1/functions/myFunction',
7879
headers: {
79-
'X-Parse-Application-Id': applicationId,
80+
'X-Parse-Application-Id': Parse.applicationId,
8081
'X-Parse-Master-Key': Parse.masterKey,
8182
'X-Parse-Request-Id': 'abc-123',
8283
},
@@ -85,7 +86,7 @@ describe('Idempotency', () => {
8586
if (SIMULATE_TTL) {
8687
await deleteRequestEntry('abc-123');
8788
} else {
88-
await new Promise(resolve => setTimeout(resolve, 130000));
89+
await new Promise(resolve => setTimeout(resolve, 10));
8990
}
9091
await expectAsync(request(params)).toBeResolved();
9192
expect(counter).toBe(2);
@@ -100,7 +101,7 @@ describe('Idempotency', () => {
100101
method: 'POST',
101102
url: 'http://localhost:8378/1/jobs/myJob',
102103
headers: {
103-
'X-Parse-Application-Id': applicationId,
104+
'X-Parse-Application-Id': Parse.applicationId,
104105
'X-Parse-Master-Key': Parse.masterKey,
105106
'X-Parse-Request-Id': 'abc-123',
106107
},
@@ -122,7 +123,7 @@ describe('Idempotency', () => {
122123
method: 'POST',
123124
url: 'http://localhost:8378/1/classes/MyClass',
124125
headers: {
125-
'X-Parse-Application-Id': applicationId,
126+
'X-Parse-Application-Id': Parse.applicationId,
126127
'X-Parse-Master-Key': Parse.masterKey,
127128
'X-Parse-Request-Id': 'abc-123',
128129
},
@@ -148,7 +149,7 @@ describe('Idempotency', () => {
148149
password: 'pass',
149150
},
150151
headers: {
151-
'X-Parse-Application-Id': applicationId,
152+
'X-Parse-Application-Id': Parse.applicationId,
152153
'X-Parse-Master-Key': Parse.masterKey,
153154
'X-Parse-Request-Id': 'abc-123',
154155
},
@@ -174,7 +175,7 @@ describe('Idempotency', () => {
174175
deviceType: 'ios',
175176
},
176177
headers: {
177-
'X-Parse-Application-Id': applicationId,
178+
'X-Parse-Application-Id': Parse.applicationId,
178179
'X-Parse-Master-Key': Parse.masterKey,
179180
'X-Parse-Request-Id': 'abc-123',
180181
},
@@ -197,7 +198,7 @@ describe('Idempotency', () => {
197198
method: 'POST',
198199
url: 'http://localhost:8378/1/classes/MyClass',
199200
headers: {
200-
'X-Parse-Application-Id': applicationId,
201+
'X-Parse-Application-Id': Parse.applicationId,
201202
'X-Parse-Master-Key': Parse.masterKey,
202203
'X-Parse-Request-Id': uuid.v4(),
203204
},
@@ -215,7 +216,7 @@ describe('Idempotency', () => {
215216
method: 'POST',
216217
url: 'http://localhost:8378/1/functions/myFunction',
217218
headers: {
218-
'X-Parse-Application-Id': applicationId,
219+
'X-Parse-Application-Id': Parse.applicationId,
219220
'X-Parse-Master-Key': Parse.masterKey,
220221
'X-Parse-Request-Id': 'abc-123',
221222
},
@@ -228,10 +229,10 @@ describe('Idempotency', () => {
228229

229230
it('should use default configuration when none is set', async () => {
230231
await setup({});
231-
expect(Config.get(applicationId).idempotencyOptions.ttl).toBe(
232+
expect(Config.get(Parse.applicationId).idempotencyOptions.ttl).toBe(
232233
Definitions.IdempotencyOptions.ttl.default
233234
);
234-
expect(Config.get(applicationId).idempotencyOptions.paths).toBe(
235+
expect(Config.get(Parse.applicationId).idempotencyOptions.paths).toBe(
235236
Definitions.IdempotencyOptions.paths.default
236237
);
237238
});

spec/PostgresStorageAdapter.spec.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,18 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => {
429429
await new Promise(resolve => setTimeout(resolve, 500));
430430
expect(adapter._onchange).toHaveBeenCalled();
431431
});
432+
433+
it('Idempotency class should have trigger', async () => {
434+
await reconfigureServer();
435+
const config = Config.get('test');
436+
const adapter = config.database.adapter;
437+
const client = adapter._client;
438+
const triggers = await client.one("SELECT event_object_table, trigger_name, event_manipulation, action_statement FROM information_schema.triggers WHERE event_object_table = '_Idempotency' ORDER BY event_object_table,event_manipulation");
439+
expect(triggers.event_object_table).toBe("_Idempotency");
440+
expect(triggers.trigger_name).toBe("idempodency_delete_old_rows_trigger");
441+
expect(triggers.event_manipulation).toBe("INSERT");
442+
expect(triggers.action_statement).toBe("EXECUTE FUNCTION idempodency_delete_old_rows()");
443+
});
432444
});
433445

434446
describe_only_db('postgres')('PostgresStorageAdapter shutdown', () => {

src/Adapters/Storage/Postgres/PostgresStorageAdapter.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2460,12 +2460,12 @@ export class PostgresStorageAdapter implements StorageAdapter {
24602460
): Promise<any> {
24612461
const conn = options.conn !== undefined ? options.conn : this._client;
24622462
const ttlOptions = options.ttl !== undefined ? `${options.ttl} seconds` : '60 seconds';
2463-
const qs = 'CREATE OR REPLACE FUNCTION idempodency_delete_old_rows() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN DELETE FROM "_Idempotency" WHERE timestamp < NOW() - INTERVAL $1::text; RETURN NEW; END; $$;';
2463+
const qs = 'CREATE OR REPLACE FUNCTION idempodency_delete_old_rows() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN DELETE FROM "_Idempotency" WHERE expire < NOW() - INTERVAL $1; RETURN NEW; END; $$;';
24642464
await this.deleteIdempodencyTrigger(options = { conn: conn })
24652465
.catch(error => {
24662466
throw error;
24672467
})
2468-
return conn
2468+
await conn
24692469
.none(qs, [ttlOptions])
24702470
.catch(error => {
24712471
if (
@@ -2478,7 +2478,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
24782478
throw error;
24792479
}
24802480
});
2481-
/*const qs2 = 'CREATE TRIGGER idempodency_delete_old_rows_trigger AFTER INSERT ON "_Idempotency" FOR EACH ROW EXECUTE PROCEDURE idempodency_delete_old_rows()';
2481+
const qs2 = 'CREATE TRIGGER idempodency_delete_old_rows_trigger AFTER INSERT ON "_Idempotency" FOR EACH ROW EXECUTE PROCEDURE idempodency_delete_old_rows()';
24822482
return conn
24832483
.none(qs2)
24842484
.catch(error => {
@@ -2487,13 +2487,11 @@ export class PostgresStorageAdapter implements StorageAdapter {
24872487
error.code === PostgresUniqueIndexViolationError ||
24882488
error.code === PostgresDuplicateObjectError
24892489
) {
2490-
console.log("3333");
24912490
// Function already exists, must have been created by a different request. Ignore error.
24922491
} else {
2493-
console.log("4444");
24942492
throw error;
24952493
}
2496-
});*/
2494+
});
24972495
}
24982496
}
24992497

0 commit comments

Comments
 (0)