feat: add Idempotency to Postgres (#7750)
This commit is contained in:
@@ -6,11 +6,14 @@ const rest = require('../lib/rest');
|
||||
const auth = require('../lib/Auth');
|
||||
const uuid = require('uuid');
|
||||
|
||||
describe_only_db('mongo')('Idempotency', () => {
|
||||
describe('Idempotency', () => {
|
||||
// Parameters
|
||||
/** Enable TTL expiration simulated by removing entry instead of waiting for MongoDB TTL monitor which
|
||||
runs only every 60s, so it can take up to 119s until entry removal - ain't nobody got time for that */
|
||||
const SIMULATE_TTL = true;
|
||||
const ttl = 2;
|
||||
const maxTimeOut = 4000;
|
||||
|
||||
// Helpers
|
||||
async function deleteRequestEntry(reqId) {
|
||||
const config = Config.get(Parse.applicationId);
|
||||
@@ -38,9 +41,10 @@ describe_only_db('mongo')('Idempotency', () => {
|
||||
}
|
||||
await setup({
|
||||
paths: ['functions/.*', 'jobs/.*', 'classes/.*', 'users', 'installations'],
|
||||
ttl: 30,
|
||||
ttl: ttl,
|
||||
});
|
||||
});
|
||||
|
||||
// Tests
|
||||
it('should enforce idempotency for cloud code function', async () => {
|
||||
let counter = 0;
|
||||
@@ -56,7 +60,7 @@ describe_only_db('mongo')('Idempotency', () => {
|
||||
'X-Parse-Request-Id': 'abc-123',
|
||||
},
|
||||
};
|
||||
expect(Config.get(Parse.applicationId).idempotencyOptions.ttl).toBe(30);
|
||||
expect(Config.get(Parse.applicationId).idempotencyOptions.ttl).toBe(ttl);
|
||||
await request(params);
|
||||
await request(params).then(fail, e => {
|
||||
expect(e.status).toEqual(400);
|
||||
@@ -83,12 +87,35 @@ describe_only_db('mongo')('Idempotency', () => {
|
||||
if (SIMULATE_TTL) {
|
||||
await deleteRequestEntry('abc-123');
|
||||
} else {
|
||||
await new Promise(resolve => setTimeout(resolve, 130000));
|
||||
await new Promise(resolve => setTimeout(resolve, maxTimeOut));
|
||||
}
|
||||
await expectAsync(request(params)).toBeResolved();
|
||||
expect(counter).toBe(2);
|
||||
});
|
||||
|
||||
it_only_db('postgres')('should delete request entry when postgress ttl function is called', async () => {
|
||||
const client = Config.get(Parse.applicationId).database.adapter._client;
|
||||
let counter = 0;
|
||||
Parse.Cloud.define('myFunction', () => {
|
||||
counter++;
|
||||
});
|
||||
const params = {
|
||||
method: 'POST',
|
||||
url: 'http://localhost:8378/1/functions/myFunction',
|
||||
headers: {
|
||||
'X-Parse-Application-Id': Parse.applicationId,
|
||||
'X-Parse-Master-Key': Parse.masterKey,
|
||||
'X-Parse-Request-Id': 'abc-123',
|
||||
},
|
||||
};
|
||||
await expectAsync(request(params)).toBeResolved();
|
||||
await expectAsync(request(params)).toBeRejected();
|
||||
await new Promise(resolve => setTimeout(resolve, maxTimeOut));
|
||||
await client.one('SELECT idempotency_delete_expired_records()');
|
||||
await expectAsync(request(params)).toBeResolved();
|
||||
expect(counter).toBe(2);
|
||||
});
|
||||
|
||||
it('should enforce idempotency for cloud code jobs', async () => {
|
||||
let counter = 0;
|
||||
Parse.Cloud.job('myJob', () => {
|
||||
|
||||
@@ -558,6 +558,17 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => {
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
expect(adapter._onchange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Idempotency class should have function', async () => {
|
||||
await reconfigureServer();
|
||||
const adapter = Config.get('test').database.adapter;
|
||||
const client = adapter._client;
|
||||
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 = 'idempotency_delete_expired_records'";
|
||||
const foundFunction = await client.one(qs);
|
||||
expect(foundFunction.format).toBe("public.idempotency_delete_expired_records()");
|
||||
await adapter.deleteIdempotencyFunction();
|
||||
await client.none(qs);
|
||||
});
|
||||
});
|
||||
|
||||
describe_only_db('postgres')('PostgresStorageAdapter shutdown', () => {
|
||||
|
||||
Reference in New Issue
Block a user