Skip to content

Interaction Tracking -- Observer context switching lifecycle. #10

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

Merged
merged 9 commits into from
Aug 4, 2018
Merged

Interaction Tracking -- Observer context switching lifecycle. #10

merged 9 commits into from
Aug 4, 2018

Conversation

salazarm
Copy link

@salazarm salazarm commented Aug 2, 2018

This PR builds on PR facebook#13234 which Introduces an experimental Interaction Tracking API.

The goal of this PR is to add a lifecycle around the context switching that happens inside of Interaction Tracking so that we can implement a profiler that can reconstruct the DAG of execution (InteractionProfiler.js)

The changes in this PR are:

  1. Make the ZoneContext type an actual Object rather than ANY type. This was done primarily so that we could have an ID field that observers could use to identify execution blocks within the same instance of an interaction.
  2. Added a Lifecycle around context switching onContextScheduled, onContextStarting, onContextEnded.
  3. Added a getSettableContext method to be used in conjunction with startContinuation. getSettableContext calls the onContextScheduled lifecycle which will trigger our Observer to increment the reference count for the current interaction contexts.

@salazarm
Copy link
Author

salazarm commented Aug 2, 2018

Forgive my poor commit hygiene, lets comment on the Files Changed tab rather than on commits =O

Copy link
Owner

@bvaughn bvaughn left a comment

Choose a reason for hiding this comment

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

Left some initial thoughts. Let's chat again after you've had a chance to read them.

By the way, you'll need to fetch and pull the branch you're based on. It's outdated and there are conflicts.

git fetch bvaughn
git rebase bvaughn/interaction-tracking

) => void;
}

const observers: Array<InteractionContextObserver> = [];
Copy link
Owner

Choose a reason for hiding this comment

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

The creation of this Array should be done within a __PROFILE__ conditional so it's only included in development and profiling builds (and not production).


export function registerInteractionContextObserver(
observer: InteractionContextObserver,
): void {
Copy link
Owner

Choose a reason for hiding this comment

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

Similarly, these methods should all be no-ops for production builds, e.g.:

export function registerInteractionContextObserver(
  observer: InteractionContextObserver,
): void {
  if (!__PROFILE__) {
    return;
  }
  observers.push(observer);
}

* LICENSE file in the root directory of this source tree.
*
* @flow
*/
Copy link
Owner

Choose a reason for hiding this comment

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

I don't think this module should be part of the interaction-tracking package. Seems like it should be part of a separate package that depends on interaction-tracking?

Copy link
Author

Choose a reason for hiding this comment

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

Yes correct, this was included as a proof of concept just to show how we'd use the API. I'll remove it.

startZoneContinuation(interactions);
let contextIDDispenser: number = 0;

export function startContinuation(context: SettableContext | null): void {
Copy link
Owner

@bvaughn bvaughn Aug 3, 2018

Choose a reason for hiding this comment

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

This changed from an array of Interactions to a single SettableContext. That seems wrong to me. Whoops, disregard this comment. I meant to delete it.

}
}

export function registerInteractionContextObserver(observer) {
Copy link
Owner

Choose a reason for hiding this comment

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

Both getSettableContext and registerInteractionContextObserver could just be exported as-is from InteractionZone. If you update the version of my branch this PR is based on, that's what I'm doing for all but the track function (since it adds a small amount of additional behavior).

Or maybe we should just merge the two modules at this point. Especially since this PR has kind of coupled the zone's context type with Interaction.

@@ -64,6 +107,12 @@ export function startContinuation(context: ZoneContext | null): void {
);
continuationContext = context;
isInContinuation = true;
invariant(
Copy link
Owner

Choose a reason for hiding this comment

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

super tiny nit: Seems like this invariant belongs at the beginning of the function with the other one.

return ({
__context: context,
__id: id,
__startCount: 0,
Copy link
Owner

Choose a reason for hiding this comment

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

nit: Can't this just be a boolean?

}

let continuationContext: SettableZoneContext | null = null;
let currentContext: Array<ZoneContext> | null = null;
let isInContinuation: boolean = false;
Copy link
Owner

Choose a reason for hiding this comment

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

isInContinuation was only necessary when continuationContext was a nullable param to startContinuation. If it's non-nullable, we can remove isInContinuation and just check continuationContext !== null in our invariants.

const context = isInContinuation ? continuationContext : currentContext;
const id = ++executionID;
__onWrappedContextScheduled(context, id);
return ({
Copy link
Owner

Choose a reason for hiding this comment

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

The SettableZoneContext.__context type Array<ZoneContext> doesn't seem to line up with the fact that ZoneContext might be null. I think this function needs to check if context is null and just return null too if it is? I'm surprised Flow didn't catch this, unless I'm reading it wrong.


InteractionTracking.startContinuation(null);
expect(InteractionTracking.getCurrentEvents()).toEqual(null);
InteractionTracking.stopContinuation();
Copy link
Owner

Choose a reason for hiding this comment

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

Why'd you remove these tests? I think they're still useful.

Copy link
Author

Choose a reason for hiding this comment

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

You can't pass null to startContinuation anymore. We'll need some sort of unwrap method to accomplish what is attempted here.

Copy link
Owner

Choose a reason for hiding this comment

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

Hm. I think there's still a disconnect in nullability as my other comment mentioned. I'll check it out when I'm merging/rebasing.

@@ -42,19 +62,42 @@ export function wrap(callback: Function): Function {
}

const wrappedContext = currentContext;
const id = ++executionID;
Copy link
Owner

Choose a reason for hiding this comment

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

What's the value in differentiating the execution id and the context/interaction id(s)? It's fine, I'm just curious what it lets us do.

Copy link
Author

Choose a reason for hiding this comment

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

the execution ID allows us to pair up calls of onContextScheduled/Starting/Ended. Check out how InteractionProfiler is using the ID.

@bvaughn
Copy link
Owner

bvaughn commented Aug 3, 2018

The introduction of SettableContext also has tricky implications when it comes to calling track() while inside of a "continuation". track() won't actually mask the continuation in that case because of how "get current" always gives priority to the continuation.

I think the solution is to disallow track() calls when we're within a continuation. (Or to change the way continuation masking works entirely...)

if (!__PROFILE__) {
return null;
}
const context = isInContinuation ? continuationContext : currentContext;
Copy link
Owner

@bvaughn bvaughn Aug 3, 2018

Choose a reason for hiding this comment

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

Something about this seems wrong, but I might be getting your PR– and my updated branch– mixed up...but if getSettableContext() is called while in a continuation– and this function returns continuationContext– won't that cause an error the next time it's called?

I'll try to tackle this when merging things, but we may need to revisit this question.

@bvaughn
Copy link
Owner

bvaughn commented Aug 4, 2018

Okay. I merged my branch into this branch and addressed my own PR feedback. I am pretty satisfied with where we arrived.

@bvaughn
Copy link
Owner

bvaughn commented Aug 4, 2018

I'm going to move forward with this so I can start updating the integration PR (facebook#13253) but let's circle back and talk on Monday to address any concerns or feedback you have.

@bvaughn bvaughn merged commit 5a3df8d into bvaughn:interaction-tracking Aug 4, 2018
@bvaughn
Copy link
Owner

bvaughn commented Aug 4, 2018

Gah, actually– we'll still need to revisit continuations. Since multiple interactions might get batched into a single React commit, React will need the ability to continue multiple interactions at once.

I think this could be made to mostly work, but is a little tricky when it comes to the concept of an "execution id". Multiple IDs would potentially be "scheduled" individually and then subsequently continued in a batch. I guess the API could just accept an array of continuations to start/stop?

It's also a bit tricky, since React unwinds stacks of interactions in order to store them as a flat list of unique interactions. 🤔

@bvaughn
Copy link
Owner

bvaughn commented Aug 4, 2018

I also think it would probably be better if the API supported requesting a continuation for a specific interaction because– as it currently stands, React might end up requesting a lot of unnecessary continuations.

@bvaughn
Copy link
Owner

bvaughn commented Aug 5, 2018

I thought about this a lot on my afternoon run and I think I have some ideas that will work. Stay tuned!

@bvaughn
Copy link
Owner

bvaughn commented Aug 5, 2018

facebook@14dffc7

lunaruan pushed a commit that referenced this pull request Jun 15, 2021
* Fixes docker-compose & pg initialization

 - ./scripts/init_db.sh is not executable (/bin/bash: bad interpreter: Permission denied)
 - same script fails because user is already created, only table creation is necessary.

* Actually fix docker-compose development workflow

* Incorporate PR feedback

* Remove credentials.json
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