improve async node flattening and apply resolver cache to async nodes#694
improve async node flattening and apply resolver cache to async nodes#694
Conversation
33236d4 to
c45c574
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #694 +/- ##
==========================================
+ Coverage 90.32% 90.63% +0.30%
==========================================
Files 336 341 +5
Lines 21258 21409 +151
Branches 2128 2173 +45
==========================================
+ Hits 19202 19404 +202
+ Misses 2038 1989 -49
+ Partials 18 16 -2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
331debd to
6cd630d
Compare
|
/canary |
6551459 to
c3bb8d1
Compare
| ### AsyncTransform | ||
| `createAsyncTransform` is a helper function to create the transform for async asset. The function takes a set of options that help adjust the transform generated to your needs: | ||
| - flatten (Optional. Default: true) - Whether or not to flatten chained results of the same asset type into a single container. | ||
| - path (Optional. Default: ["values"]) - The path to the array within the `wrapperAssetType` that will contain the async content. |
There was a problem hiding this comment.
what's the benefit of giving this as an option?
There was a problem hiding this comment.
The path option here is to allow for cases where maybe the warpperAssetType wants its values somewhere else. The best example I can think of would be if someone had something like a table asset with rows instead of values as the path.
| - transformAssetType (Required) - The asset type that the transform is matching against. | ||
| - wrapperAssetType (Required) - The asset type that will contain the async content. | ||
| - getNestedAsset (Optional) - Function to get any nested asset that will need to be extracted and kept when creating the wrapper asset. This is useful when combined with `flatten: true` to help chain async content with a single asset type. | ||
| - getAsyncNodeId (Optional) - Function to get the id for the generated async node. By default it uses a format of `async-{asset.id}` |
|
|
||
| const asyncTransform = (node: Node.ViewOrAsset) => { | ||
| const id = getAsyncNodeId(node); | ||
| const asset = getNestedAsset?.(node); |
There was a problem hiding this comment.
maybe i'm not understanding this properly, the usage of this function is weird. This is entrusting the consumers to pass in a proper getNestedAsset function so we can use it to retrieve the nested asset in our multi-node?
should we not be the one doing this?
There was a problem hiding this comment.
The getNestedAsset replaces what the asset argument in the original asyncTransform did. Since we need to repeat it here I decided to use a function. We could alternatively take a nestedAssetPath that defaults to value and get it ourselves I think. Pretty much, this allows for transforms other than our chat-message use case where maybe the chained assets are somewhere else.
| return childOptions === undefined | ||
| ? multiNode | ||
| : [ | ||
| { | ||
| path: [...childOptions.path, childOptions.key], | ||
| value: multiNode, | ||
| }, | ||
| ]; |
There was a problem hiding this comment.
The changes in here allow multi nodes to be parsed if they are the root object. This is to allow async node results to return arrays of data that can either be used to flatten into a higher level multi-node or just to produce a multi node for some property.
| asyncChanges?.forEach((id) => { | ||
| let current: Node.Node | undefined = prevAsyncIdMap.get(id); | ||
| while (current && prevASTMap.has(current)) { | ||
| const next = prevASTMap.get(current); | ||
| if (next && this.resolveCache.has(next)) { | ||
| this.resolveCache.delete(next); | ||
| } | ||
| current = current.parent; | ||
| } | ||
| }); |
There was a problem hiding this comment.
This setup here lets us clear some of the cache when an async node updates. I wonder if we can use something similar to the dependency tracker used for data changes here instead?
| for (const id of resolvedAST.asyncNodesResolved ?? []) { | ||
| nextAsyncIdMap.set(id, resolvedAST); |
There was a problem hiding this comment.
The use of asyncNodesResolved is a special case made necessary by some of the changes to how flattening is handled for async nodes. Because these nodes are resolved by and flattened when the parent node is doing onBeforeResolve, the parent needs to be aware of the async ids that were resolved so it can have its cache cleared if that node updates.
| .filter((index) => index !== -1); | ||
|
|
||
| const newValues = resolvedAST.values.map((mValue) => { | ||
| resolvedAST.values = resolvedAST.values.flatMap((mValue) => { |
There was a problem hiding this comment.
The changes here and below are just removing some of the flattening work since it's handled by the async node plugin now.
| public updateAsync(asyncNode: string): void { | ||
| const update = this.resolver?.update(new Set(), new Set([asyncNode])); |
There was a problem hiding this comment.
Can't used undefined for the data changes since that clears the whole cache.
|
|
||
| const asyncTransform = (node: Node.ViewOrAsset) => { | ||
| const id = getAsyncNodeId(node); | ||
| const asset = getNestedAsset?.(node); |
There was a problem hiding this comment.
The getNestedAsset replaces what the asset argument in the original asyncTransform did. Since we need to repeat it here I decided to use a function. We could alternatively take a nestedAssetPath that defaults to value and get it ourselves I think. Pretty much, this allows for transforms other than our chat-message use case where maybe the chained assets are somewhere else.
| ### AsyncTransform | ||
| `createAsyncTransform` is a helper function to create the transform for async asset. The function takes a set of options that help adjust the transform generated to your needs: | ||
| - flatten (Optional. Default: true) - Whether or not to flatten chained results of the same asset type into a single container. | ||
| - path (Optional. Default: ["values"]) - The path to the array within the `wrapperAssetType` that will contain the async content. |
There was a problem hiding this comment.
The path option here is to allow for cases where maybe the warpperAssetType wants its values somewhere else. The best example I can think of would be if someone had something like a table asset with rows instead of values as the path.
| wrapperAssetType, | ||
| asset, | ||
| flatten, | ||
| flatten = true, |
There was a problem hiding this comment.
is this backwards compatible?
There was a problem hiding this comment.
Oops, no, I meant to undo this after moving stuff to the createAsyncTransform. Good catch, will remove.
…o include node extraction logic for async nodes
…lugin implementation
…or better flattening
185649d to
9a9ee75
Compare
Change Type (required)
Indicate the type of change your pull request is:
patchminormajorN/ADoes your PR have any documentation updates?
Release Notes
📦 Published PR as canary version:
0.12.1--canary.694.25095Try this version out locally by upgrading relevant packages to 0.12.1--canary.694.25095