automerge / automerge-swift

Swift language bindings presenting Automerge

Home Page:https://automerge.org/automerge-swift/documentation/automerge/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Send doc.objectWillChange outside of sync queue?

jessegrosjean opened this issue · comments

Right now Automerge.Document uses this pattern for modifications:

try sync {
    try self.doc.wrapErrors {
        sendObjectWillChange()
        ...
    }
}

The problem is this means there's no way to read document state from the objectWillChange callback (unless you debounce, but then you will be getting post change state), since reading also requires access to the same queue. So for example there's no way to record the heads() before the document changes.

This will fail waiting for queue:

automergeDoc.objectWillChange.sink {
    automergeDoc.heads()
}

Does it make sense to move sendObjectWillChange outside the sync block?

Even with the naming of objectWillChange, I've never been terribly clear on what the timing requirements are far, and how those process in terms of the current runloop through synchronous calls. I've no qualms with generally calling this outside (prior) to the dispatchqueue sync protection lock, although I think I recall in some places I'm actually checking to see if there's any change to be made, and skipping calls to change if contents are identical, that might stymie some of this. But i'm saying that without coffee yet this morning and no code in front of me. ;-)

Even with the naming of objectWillChange, I've never been terribly clear on what the timing requirements are far, and how those process in terms of the current runloop through synchronous calls.

Agreed. I don't really know either, and it's always been a weird looking call.

Right now it's the only way to subscribe for changes in Automerge, I think maybe that's the biggest problem. Really need a real event, instead of trying to bend this one to do what I want.

With that said I still think the current setup where you get an exception when trying to access the document (unless you debounce) doesn't seem right to me and I would think is sure to generate errors for others.

I don't immediately see anywhere that you are checking to see if there will be a change before calling objectWillChange. I guess my vote would be to move it outside of the sync block and see if MeetingNotes still behaves.

Ah - found what I was thinking about - there's calls in Counter & AutomergeText objects (reference type overlays that dynamically read/write into Document as changes are made to them) that also expose ObservableObject, and it's in there that I'm doing the "post-change" checking - the vague-ish-workaround being that I wanted to know if any given 'objectWillChange' was the a relevant result for the part of the schema that the object tracks. The change signals from a document coming from any of: user interactions, calls to merge other docs, applying sync messages, or even encoded changes locally.

In those cases the "objectDidChange" is far more of how I coded it up - with the sole purpose behind those being "do I need to send a signal to UI frameworks to re-render the content", and not at all the "can I capture the state markers of the document" kind of thing. Anyway, shouldn't be an issue to muck with the Document calls directly and move them outside of the DispatchQueue.sync

@jessegrosjean Take a look over #179 - I've added a test that mostly is verifying that the specific thing we're after (capturing heads prior to a change) is, in fact, possible (test crashed prior to the code changes, as expected with attempting synchronous access to Document).