Skip to content

Commit 41d3d8d

Browse files
committed
make postgres idempotency function callable
1 parent 7fb9e54 commit 41d3d8d

File tree

3 files changed

+38
-14
lines changed

3 files changed

+38
-14
lines changed

spec/Idempotency.spec.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ 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 ttl = 30;
15-
const maxTimeOut = 130000;
14+
const ttl = 2;
15+
const maxTimeOut = 4000;
1616

1717
// Helpers
1818
async function deleteRequestEntry(reqId) {
@@ -93,6 +93,29 @@ describe('Idempotency', () => {
9393
expect(counter).toBe(2);
9494
});
9595

96+
it_only_db('postgres')('should delete request entry when postgress ttl function is called', async () => {
97+
const client = Config.get(Parse.applicationId).database.adapter._client;
98+
let counter = 0;
99+
Parse.Cloud.define('myFunction', () => {
100+
counter++;
101+
});
102+
const params = {
103+
method: 'POST',
104+
url: 'http://localhost:8378/1/functions/myFunction',
105+
headers: {
106+
'X-Parse-Application-Id': Parse.applicationId,
107+
'X-Parse-Master-Key': Parse.masterKey,
108+
'X-Parse-Request-Id': 'abc-123',
109+
},
110+
};
111+
await expectAsync(request(params)).toBeResolved();
112+
await expectAsync(request(params)).toBeRejected();
113+
await new Promise(resolve => setTimeout(resolve, maxTimeOut));
114+
await client.one('SELECT idempodency_delete_old_rows()');
115+
await expectAsync(request(params)).toBeResolved();
116+
expect(counter).toBe(2);
117+
});
118+
96119
it('should enforce idempotency for cloud code jobs', async () => {
97120
let counter = 0;
98121
Parse.Cloud.job('myJob', () => {

spec/PostgresStorageAdapter.spec.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,11 +432,13 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => {
432432

433433
it('Idempotency class should have function', async () => {
434434
await reconfigureServer();
435-
const config = Config.get('test');
436-
const adapter = config.database.adapter;
435+
const adapter = Config.get('test').database.adapter;
437436
const client = adapter._client;
438-
const foundFunction = await client.one("SELECT format('%I.%I(%s)', ns.nspname, p.proname, oidvectortypes(p.proargtypes)) FROM pg_proc p INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid) WHERE p.proname = 'idempodency_delete_old_rows'");
437+
const qs = "SELECT format('%I.%I(%s)', ns.nspname, p.proname, oidvectortypes(p.proargtypes)) FROM pg_proc p INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid) WHERE p.proname = 'idempodency_delete_old_rows'";
438+
const foundFunction = await client.one(qs);
439439
expect(foundFunction.format).toBe("public.idempodency_delete_old_rows()");
440+
await adapter.deleteIdempodencyFunction();
441+
await client.none(qs);
440442
});
441443
});
442444

src/Adapters/Storage/Postgres/PostgresStorageAdapter.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
886886
}
887887

888888
async classExists(name: string) {
889-
return this._client.one(
889+
await this._client.one(
890890
'SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1)',
891891
[name],
892892
a => a.exists
@@ -964,7 +964,6 @@ export class PostgresStorageAdapter implements StorageAdapter {
964964
);
965965
});
966966
this._notifySchemaChange();
967-
return Promise.resolve();
968967
}
969968

970969
async createClass(className: string, schema: SchemaType, conn: ?any) {
@@ -1030,7 +1029,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
10301029
const qs = `CREATE TABLE IF NOT EXISTS $1:name (${patternsArray.join()})`;
10311030
const values = [className, ...valuesArray];
10321031

1033-
return conn.task('create-table', async t => {
1032+
await conn.task('create-table', async t => {
10341033
try {
10351034
await t.none(qs, values);
10361035
} catch (error) {
@@ -1953,7 +1952,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
19531952
const constraintName = `${className}_unique_${fieldNames.sort().join('_')}`;
19541953
const constraintPatterns = fieldNames.map((fieldName, index) => `$${index + 3}:name`);
19551954
const qs = `CREATE UNIQUE INDEX IF NOT EXISTS $2:name ON $1:name(${constraintPatterns.join()})`;
1956-
return this._client.none(qs, [className, constraintName, ...fieldNames]).catch(error => {
1955+
await this._client.none(qs, [className, constraintName, ...fieldNames]).catch(error => {
19571956
if (error.code === PostgresDuplicateRelationError && error.message.includes(constraintName)) {
19581957
// Index already exists. Ignore error.
19591958
} else if (
@@ -2303,7 +2302,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
23032302
.then(() => this.schemaUpgrade(schema.className, schema));
23042303
});
23052304
promises.push(this._listenToSchema());
2306-
return Promise.all(promises)
2305+
await Promise.all(promises)
23072306
.then(() => {
23082307
return this._client.tx('perform-initialization', async t => {
23092308
await t.none(sql.misc.jsonObjectSetKeys);
@@ -2421,7 +2420,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
24212420
if (setIdempodencyFunction) {
24222421
await this.ensureIdempodencyFunctionExists(options);
24232422
}
2424-
return conn.none(qs, [indexNameOptions.name, className, ...fieldNames])
2423+
await conn.none(qs, [indexNameOptions.name, className, ...fieldNames])
24252424
.catch(error => {
24262425
if (
24272426
error.code === PostgresDuplicateRelationError &&
@@ -2448,7 +2447,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
24482447
): Promise<any> {
24492448
const conn = options.conn !== undefined ? options.conn : this._client;
24502449
const qs = 'DROP FUNCTION IF EXISTS idempodency_delete_old_rows()';
2451-
return conn
2450+
await conn
24522451
.none(qs)
24532452
.catch(error => {
24542453
throw error;
@@ -2460,8 +2459,8 @@ export class PostgresStorageAdapter implements StorageAdapter {
24602459
): Promise<any> {
24612460
const conn = options.conn !== undefined ? options.conn : this._client;
24622461
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 expire < NOW() - INTERVAL $1; RETURN NEW; END; $$;';
2464-
return conn
2462+
const qs = 'CREATE OR REPLACE FUNCTION idempodency_delete_old_rows() RETURNS void LANGUAGE plpgsql AS $$ BEGIN DELETE FROM "_Idempotency" WHERE expire < NOW() - INTERVAL $1; END; $$;';
2463+
await conn
24652464
.none(qs, [ttlOptions])
24662465
.catch(error => {
24672466
if (

0 commit comments

Comments
 (0)