Async AfterSave notification on completion

#1

We have afterSave hooks that run async, so the parse client gets a response before the afterSave if done running.

This creates a problem in unit tests when I want to verify a state after the afterSave has completed.

Currently, I solve for this by waiting for a couple hundred millis before testing the state. This is not optimal because it is both fragile and it slows down test runs.

My thought is to make ‘something’ an event emitter that can emit a ‘afterSave completed event’.

Clearly, I haven’t thought it through much yet.

Any reactions?

#2

Oh man! I finally got around to trying out a solution for this…and it works.

  1. I added a simple service. In this particular case, I have a a Parse Class called Plan. So here is the service:

./lib/Service/PlanHookEmitter.js

const events = require('events');

// for listening to hook events

const planHookEmitter = new events.EventEmitter();

module.exports = planHookEmitter;
  1. In my plan file, I include the service.
const planHookEmitter = require('../lib/Service/PlanHookEmitter');
...
const afterSave = function afterSave(request) {
  const promises = [];
  const p1 = doSomething();
  promises.push(p1);
   ...
  const p2 = doSomethingElse();
  promises.push(p2);

  Promise.all(promises).then(() => planHookEmitter.emit('afterSaveComplete'));
  // not returnin a promise so the client is released!
};
  1. code that needs to know when the hook is done (i’m looking at you integration tests!), can listen like so:
const planHookEmitter = require('../lib/Service/PlanHookEmitter');

const afterSavePromise = () => new Promise(resolve => planHookEmitter.once('afterSaveComplete', resolve));

describe('isActive', function () {
  beforeEach(async function () {
    require('../cloud/main');
    this.plan = await new Parse.Object('Plan')
      .save(null, { sessionToken: this.sessionToken });
    await afterSavePromise(); // BAM!
    ....

no more waiting for some random amount of time in hopes that your async thingy will finish.

If this proves to work and I figure out some pattern, then I can try to use this to replace all the pauses in the parse-server tests to speed them up. waaay up. and make them less flakey.