mongodb / stitch-ios-sdk

Apache License 2.0
42 stars 25 forks source link

STITCH-1992 Add watch to RemoteMongoCollection #143

Closed adamchel closed 5 years ago

adamchel commented 5 years ago

This adds support for opening watch streams on a RemoteMongoCollection. The interface to do this is pretty different from JavaScript, as I tried to mimic Foundation's URLSession to create a ChangeStreamSession. This was a bit complicated by the fact that ChangeEvents are generic on document type, but I was able to come up with an interface that I think will be pretty clean.

Below is a usage sample that might help in your review:

// this is a delegate that might be used to react to change events with a normal document type
class MyChangeStreamDelegate: ChangeStreamDelegate {
    // this delegate interacts with normal BSON documents
    typealias DocumentT = Document

    func didReceive(event: ChangeEvent<Document>) {
        // react to event
    }

    func didReceive(streamError: Error) {
        // react to error
    }

    func didOpen() {
        // react to stream opening
    }

    func didClose() {
        // react to stream closing
    }
}

class MyCustomTypeChangeStreamDelegate: ChangeStreamDelegate {
    // this delegate interacts with BSON documents of a custom user-defined type
    typealias DocumentT = MyCustomType

    func didReceive(event: ChangeEvent<MyCustomType>) {
        // react to event
    }

    func didReceive(streamError: Error) {
        // react to error
    }

    func didOpen() {
        // react to stream opening
    }

    func didClose() {
        // react to stream closing
    }
}

func myWatchSample() {
    // self.coll is assumed to be a remote mongo collection acting on normal documents
    let myDelegate = MyChangeStreamDelegate.init()
    let stream1 = self.coll.watch(["some_string_id", ObjectId("some_hex_string")], myDelegate)

    // self.customTypeColl is assumed to be a remote mongo collection acting on custom type docs
    let myCustomDelegate = MyCustomTypeChangeStreamDelegate.init()
    let stream2 = self.customTypeColl.watch(["some_other_id"], myCustomDelegate)

    // this won't compile, because the delegate is incompatible with the collection type
    let streamWontCompile = self.coll.watch(["some_other_id"], myCustomDelegate)

    // delegates can be hot-swapped 
    let someNewDelegate = MyDelegate.init()
    stream1.delegate = someNewDelegate

    // streams can be closed by closing their session
    stream1.close()
    stream2.close()
}