3

If I want to use nested data structure, which data structure is better choose.

eg.

enter image description here

For eg1 case, It seems can not load children DDS data in 'hasInitialized()'.

For eg2, it seems a little complicated.

Is anyone can show some example for this case?

lemon
  • 300
  • 1
  • 6

1 Answers1

3

A DataObject contains a collection of one or more DDSes and nesting them allows you to create organizational structure. DDSes themselves can also be nested and retrieved in the initialization steps.

There are a few ways you can solve eg1 and I highlight two below.

For eg2 you're right that it's a bit complicated and generally not a pattern we are pushing at the moment. There are some example in the repo but you will find that they use a slightly different developer model then the HelloWorld. The SimpleComponentEmbed and the Pond are the best starting points if you want to explore DataObject embedding.

Using root SharedDirectory for nesting

The root SharedDirectory allows you to create sub-directories. This is a great way to manage collections of nested maps. Using sub-directories instead of putting a SharedMap on the root ensures creation and setting happens as one atomic action instead of two actions, (one to create and one to set).

The current draw back to this at the moment is that you have to listen to events on the root directory and see if it corresponds to your sub-directory. Eventing on sub-directories is being tracked with Issue #1403

protected async initializingFirstTime() {
    const subDirectory = this.root.createSubDirectory("sub-dir");
    subDirectory.createSubDirectory("sub-sub-dir");
}

protected async hasInitialized() {
    const subDirectory = this.root.getSubDirectory("sub-dir");
    const ssDir = subDirectory.getSubDirectory("sub-sub-dir");

    this.root.on("valueChanged", (changed: IDirectoryValueChanged) => {
        if (changed.path === ssDir.absolutePath) {
            const newValue = ssDir.get(changed.key);
            console.log(newValue);
        }
    });

    // An easy way to trigger/test the above handler without user interaction
    setTimeout(() => {
        ssDir.set("foo", "bar2");
    }, 10000); // 10 seconds
}

Using Nested DDSes

You can also store nested DDSes. The thing you need to remember is that you are storing/ retrieving the handle to the DDS. In the below example we are creating map1 with a key/value. We are string map1 in map2 which is being stored on the root DDS. We will then get the value from map1 by first getting map2 then map1 then the value.

protected async initializingFirstTime() {
    const map1 = SharedMap.create(this.runtime);
    map1.set("foo", "bar");

    const map2 = SharedMap.create(this.runtime);
    map2.set("map1", map1.handle);

    this.root.set("map2", map2.handle);
}

protected async hasInitialized() {
    const map2 = await this.root.get<IFluidHandle<SharedMap>>("map2").get();
    const map1 = await map2.get<IFluidHandle<SharedMap>>("map1").get();

    console.log(map1.get("foo"));
}
Skyler Jokiel
  • 318
  • 2
  • 11
  • I use SharedMap and SharedObjectSequence build a nested DDSes, but I could not insert new node asynchronously, does you have any useful info for this case, link is [here](https://stackoverflow.com/questions/64351159/how-to-insert-sharedmap-into-sharedobjetsequence) – lemon Oct 14 '20 at 10:23