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

[FEAT] TrackableRequests for when async leakage is detected #5545

Merged
merged 1 commit into from
Aug 17, 2018

Conversation

runspired
Copy link
Contributor

@runspired runspired commented Jul 27, 2018

This feature enables app developers to better use async ... await while simultaneously detecting asynchronous test leaks in their data layer. It is best paired with ember-qunit's setupTestIsolationValidation feature.

When running an ember-cli application in non-production environments, this feature adds a test-waiter per-store instance that works with the settled() test-helper. This test-waiter does not cause waiting by default, in order to prevent immediately breaking any apps that upgrade to this version of ember-data that do have test leaks without warning.

This feature comes with two feature flags, only configurable in non-production environments, that live on the store instance. Both of these flags are currently false by default.

  1. store.shouldTrackAsyncRequests

When true, requests initiated via the store will be assigned a token, and while any tokens have not resolved the test-waiter (and thus await settled()) will wait.

When true, any detected leaks will throw an error when the store is destroyed after a test, causing the test to fail. The leaks will be logged, with a descriptive label for the request that was initiated, and potentially a trace (see below) for where the request initiated from.

When false, any detected leaks will be emitted as warnings when the store is destroyed after a test.

  1. store.generateStackTracesForTrackedRequests

When true, a stack trace will be captured at the point that a request is initiated and saved onto the token used to track the request. For requests other than findRecord, these traces will include the point in app code that caused this request to be initiated. For findRecord these traces currently point back to flushPendingFetches; however, we also capture a trace at the point that we schedule these fetches, and will soon thread those traces through so that where the request initiated in app code is clear.


if (index !== -1) {
this._trackedAsyncRequests.splice(index, 1);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If their is no index, something seems wrong. We should explore/consider the impact of throwing.

tracked.map(o => o.label).join('\n\t - ')
);
} else {
warn(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by default, we may want to warn here. That way apps who violate this, have some grace period to cut over.

Erroring hard, make simply make it hard to upgrade with little upside. That being said, in the future we should strongly consider this being on by default.

// debugging. Ideally we would have a tracked queue for requests with
// labels or local IDs that could be used to merge this trace with
// the trace made available when we detect an async leak
pendingFetchItem.trace = trace;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eventually we should thread this through, and it super supersede the _trackAsyncRequestStart trace


test('the waiter properly waits for pending requests', async function(assert) {
let stepResolve;
let stepPromise = new Promise(resolveStep => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findRecordWasInvoked


assert.equal(waiter(), false, 'We return false to keep waiting while requests are pending');

await request.catch(e => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert.rejects if present in this version of QUnit, could be used to provide better test failure messages.

more context: https://github.com/qunitjs/qunit/pull/1238/files#diff-78b865bceaf70054fdd9917848e7ddd8R43

improve waiter erroring

improve trace infra and add tests

only run waiter tests in dev
@runspired runspired merged commit c83849d into master Aug 17, 2018
@runspired runspired deleted the add-traces-to-leaks branch August 18, 2018 01:27
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

Successfully merging this pull request may close these issues.

2 participants