Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrating with newer test waiters system #340

Closed
ef4 opened this issue Jun 14, 2021 · 5 comments
Closed

Integrating with newer test waiters system #340

ef4 opened this issue Jun 14, 2021 · 5 comments

Comments

@ef4
Copy link
Contributor

ef4 commented Jun 14, 2021

I would like to register a source with ember's test waiter system so that this source is included in the default Ember settled state. This seems to work:

import SourceClass from '@orbit/jsonapi';
import { registerWaiter } from '@ember/test';

let currentSource;
registerWaiter(function () {
  return (
    currentSource.requestQueue.empty &&
    !currentSource.requestQueue.processing &&
    currentSource.syncQueue.empty &&
    !currentSource.syncQueue.processing
  );
});

export default {
  create(injections = {}) {
    return (currentSource = new SourceClass(injections));
  },
};

However, current versions of the ember eslint plugin will complain about this use of registerWaiter and push you toward the newer @ember/test-waiters system. That API no longer supports polling like this, and instead wants to wrap each asynchronous operation.

Since I would guess most sources don't want to build this in by default, would it be appropriate to emit events from the sources that one could observe in order to notice each time a task is enqueue or resolved? Is there an existing hook?

I'm aware of waitForSource, but that serves a different purpose than what I'm trying to do here. Especially for people porting from ember-data, it's very helpful to make a remote source always block settled.

@dgeb
Copy link
Member

dgeb commented Jun 15, 2021

@ef4 Each of these queues is an Orbit TaskQueue. When the queues are empty they emit a complete event, which you can listen for:

currentSource.requestQueue.on('complete', () => { 
  // optionally return a promise here if you want to delay future actions of the queue until the promise resolves or errors
});

Remember to cleanup with off.

@ef4
Copy link
Contributor Author

ef4 commented Jun 15, 2021

Thanks. Is there a corresponding event for going from empty to active?

@dgeb
Copy link
Member

dgeb commented Jun 15, 2021

beforeTask is emitted before each task in the queue is processed. I think this is most like an "active" indicator.

Another event to be aware of is change which is emitted whenever the contents of the queue change, but this may happen when the queue is complete or processing has paused and its contents are changed.

@ef4
Copy link
Contributor Author

ef4 commented Jun 15, 2021

Thanks, that set me on the right track. I ended up going with beforeTask for start and task or fail for end. Here is a utility that may help others (and could potentially go into ember-orbit):

import { buildWaiter } from '@ember/test-waiters';

export function buildOrbitWaiter(label) {
  let waiter = buildWaiter(label);

  const taskTokens = new WeakMap();

  function taskStarted(task) {
    let token = waiter.beginAsync();
    taskTokens.set(task, token);
  }
  function taskEnded(task) {
    let token = taskTokens.get(task);
    if (token) {
      waiter.endAsync(token);
    }
  }

  function waitForSource(source) {
    source.requestQueue.on('beforeTask', taskStarted);
    source.requestQueue.on('task', taskEnded);
    source.requestQueue.on('fail', taskEnded);
    source.syncQueue.on('beforeTask', taskStarted);
    source.syncQueue.on('task', taskEnded);
    source.syncQueue.on('fail', taskEnded);
    return source;
  }

  return { waitForSource };
}

You use it like:

import JSONAPISource from '@orbit/jsonapi';
import { buildOrbitWaiter } from '../lib/orbit-waiter';

let { waitForSource } = buildOrbitWaiter('data-source:rails');

export default {
  create(injections = {}) {
    return waitForSource(new JSONAPISource(injections));
  }
}

@dgeb
Copy link
Member

dgeb commented Jun 16, 2021

Looks good @ef4 - thanks for sharing! I've opened tracking issue #341 to ensure that we add your work, or something similar, to ember-orbit soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants