Question about intention of subdocument flow

I’m busy implementing subdocument support for a custom provider. It’s going fine, but I had one question about the intended lifecycle of subdocs. The documentation seem to be a bit out of date compared to the code, but even so there are some spots I’m unclear on.

Based on the code, my understanding is that the first step is to load the document, which can be easily tracked with isLoaded. Then it needs to be synced and that process can flip-flop arbitrarily many times as the provider gains and loses connection. The related promise is re-created as needed so that’s very clear and fine. And when you’re done with the document you should destroy it.

Once it’s loaded, though, it…stays loaded forever? The docs state: A subdocument can be destroyed doc.destroy() to free all used memory and destroy existing data bindings. The document can be accessed again to force the provider to load the content again. But destruction does not seem to change any properties on the subdoc, so isLoaded would still be true if you checked it after calling destroy() on the object. It’s quite possible I’m just missing something which is done by the super.destroy() call, so if so please let me know.

It’s not intended to access a destroyed document afterwards, that’s clear from the docs, but in my system there’s no central repository of knowledge about whether a given subdoc has been destroyed (and thus should be re-synced before the next access). I need to check a property on a given document to know. I can check whether _item is null for now, which does work but obviously isn’t ideal.

It naively seems to me that destroy() should at least reset isLoaded to false, which is probably not exactly the right answer as load() is idempotent. Have I overlooked anything or is this just something that hasn’t been considered (since subdocs don’t seem to be widely used). I can also listen to the destroy event and mark the document unsynced myself, but that also feels hacky as it’s not merely unsynced but entirely unusable at that point.

Assume that const subdoc = ymap.get('subdoc') yields a subdocument.

After calling subdoc.destroy(), the instance shouldn’t be used anymore. ymap.get('subdoc') will yield a new instance, hence ymap.get('subdoc') !== subdoc, although ymap.get('subdoc').guid === subdoc.guid will always yield true.

I believe there is a isDestroyed property on the subdoc instance as well. Maybe that will help to avoid using destroyed instances. If not, I’d be happy to add it.

That aligns with my expectations. There isn’t currently an isDestroyed property (I’m checking for _item === null to do the same thing) but an explicit property for that would be perfect :slight_smile:

That should work too!

I also added ydoc.isDestroyed which will be available in yjs@13.6.19

2 Likes