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: tree index api prototype #22491

Draft
wants to merge 37 commits into
base: main
Choose a base branch
from
Draft

Conversation

jenn-le
Copy link
Contributor

@jenn-le jenn-le commented Sep 12, 2024

Description

  • TreeIndex is an interface based off of ReadonlyMap that indexes can adhere to
  • AnchorTreeIndex indexes anchors nodes on given keys that can be customized per schema
  • createSimpleTreeIndex is a public api that allows users to define the schemas and related keyfinders they want to index on, indexing TreeNodes
  • createIdentifierIndex creates an index that keys nodes on their identifiers

TODO expand out this description if we want to use this for the API review but maybe it'd be better to just review off the doc?

Reviewer Guidance

The review process is outlined on this wiki page.

@github-actions github-actions bot added the area: dds Issues related to distributed data structures label Sep 12, 2024
@github-actions github-actions bot added area: dds: tree base: main PRs targeted against main branch labels Sep 12, 2024
const nodes = this.nodes.get(key);
if (nodes !== undefined) {
// if the key already exists in the index, the anchor node is appended to its list of nodes
this.nodes.set(key, [...nodes, anchorNode]);
Copy link
Contributor

Choose a reason for hiding this comment

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

any reason to clone the array rather than push to it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the array is readonly for api purposes and gets super ugly (not even sure if it's completely feasible) to make a bunch of casts

Copy link
Contributor

Choose a reason for hiding this comment

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

don't we just need the output type (the thing we hand to getValue) to implement readonly array...which array does? can we not just type our internal type as arry, e.g. private readonly nodes = new Map<TKey, AnchorNode[]>();

Copy link
Contributor

Choose a reason for hiding this comment

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

we filter the array (meaning allocate a new one) before handing it to getValue anyway, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh yeah, you're right, I was just doing something stupid when I tried it the first time

}

// index any new trees that are created later
forest.on("afterRootFieldCreated", (fieldKey) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

is this event guaranteed to fire for all content created in the tree, including modifications of value fields (e.g. user does foo.x = 5, and the x field is indexed)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is not, I created a skipped test and added a todo to use a different event. Will add the proposal for it in the api doc

Copy link
Contributor

Choose a reason for hiding this comment

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

wait, so are indexes not totally broken until that works? is there another forest event that is fired when that happens that we can subscribe to?

Copy link
Contributor

Choose a reason for hiding this comment

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

@noencke is claiming that primitives are wrapped in nodes and so even value nodes start out detached and are moved in. this sounds vaguely familiar. have you tested this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok, that's what I thought too but then I wrote that skipped test to make sure and it failed

@github-actions github-actions bot added changeset-present public api change Changes to a public API and removed public api change Changes to a public API changeset-present labels Sep 16, 2024
Copy link
Contributor

🔗 No broken links found! ✅

Your attention to detail is admirable.

linkcheck output


> [email protected] ci:linkcheck /home/runner/work/FluidFramework/FluidFramework/docs
> start-server-and-test ci:start 1313 linkcheck:full

1: starting server using command "npm run ci:start"
and when url "[ 'http://127.0.0.1:1313' ]" is responding with HTTP status code 200
running tests using command "npm run linkcheck:full"


> [email protected] ci:start
> http-server ./public --port 1313 --silent


> [email protected] linkcheck:full
> npm run linkcheck:fast -- --external


> [email protected] linkcheck:fast
> linkcheck http://localhost:1313 --skip-file skipped-urls.txt --external

Crawling...

Stats:
  405680 links
    3151 destination URLs
       2 URLs ignored
       0 warnings
       0 errors


@@ -27,6 +27,9 @@ export interface CommitMetadata {
readonly kind: CommitKind;
}

// @public (undocumented)
export function createSimpleTreeIndex<TKey extends TreeValue, TValue, TSchema extends TreeNodeSchema>(context: FlexTreeContext, indexer: (schema: TSchema) => KeyFinder<TKey> | undefined, getValue: (nodes: TreeIndexNodes<NodeFromSchema<TSchema>>) => TValue, indexableSchema: readonly TSchema[]): SimpleTreeIndex<TKey, TValue>;
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume these will go away (public and beta)?

export function createIdentifierIndex(context: FlexTreeContext): IdentifierIndex;

// @alpha
export function createSimpleTreeIndex<TKey extends TreeValue, TValue>(context: FlexTreeContext, indexer: (schema: TreeNodeSchema) => KeyFinder<TKey> | undefined, getValue: (nodes: TreeIndexNodes<TreeNode>) => TValue): SimpleTreeIndex<TKey, TValue>;
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we want this in alpha in the current form. Having users provide a KeyFinder (and take the burden of determinism/inval) seems like a bug pit. I feel like a reduced scope form (maybe they provide simple tree schema type + a value field pair and we have a KeyFinder that knows how to handle those) should be exposed first.

Copy link
Contributor

@taylorsw04 taylorsw04 Sep 16, 2024

Choose a reason for hiding this comment

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

We definitely can't expose it until the value field mutation inval issue is solved (if it exists at all)

return value;
}

describe.only("tree indexes", () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

we should have a clear-box test that checks that nodes that are GC'd after being removed are deleted from the index (triggered by "afterDestroy")


this.anchors.set(anchorNode, anchor);
// when the anchor node is destroyed, delete it from the index
anchorNode.on("afterDestroy", () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

having talked to Noah, we think this might be better written as a delta visitor instead of event subscriptions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: dds: tree area: dds Issues related to distributed data structures base: main PRs targeted against main branch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants