RxRealm icon indicating copy to clipboard operation
RxRealm copied to clipboard

[bug] change gets swollen when using synchronous first element

Open icanzilb opened this issue 8 years ago • 3 comments

As described here: https://github.com/realm/realm-cocoa/issues/4761#issuecomment-290911721

Demo code:

class Test: Object {
    dynamic var name = ""
    override var description: String {
        return "[name => '\(name)']"
    }
}

class ViewController: UIViewController {

    private let bag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        test()
    }

    var token: NotificationToken?

    func test() {
        let realm = try! Realm()
        let obj = Test()

        try! realm.write {
            realm.deleteAll()
            realm.add(obj)
        }

        let tests = realm.objects(Test.self)

        DispatchQueue.global(qos: .background).async {
            let realm = try! Realm()
            let obj = realm.objects(Test.self).first!

            try! realm.write {
                obj.name = "Test0"
            }
        }

        Observable.array(from: tests)
            .subscribe(onNext: { value in
                print("rx next: \(flatten(value))")
            })
            .addDisposableTo(bag)

        token = tests.addNotificationBlock { changes in
            switch changes {
            case .initial(let tests):
                print("realm initial: \(flatten(tests))")
            case .update(let tests, _, _, _):
                print("realm changed: \(flatten(tests))")
            default: break
            }
        }

    }

}


icanzilb avatar Apr 01 '17 10:04 icanzilb

Anything new on this? Any workaround?

tristangrichard avatar Nov 24 '20 10:11 tristangrichard

Hey Tristan, To the best of my knowledge there is currently no maintainer/owner for this project. If you or someone you know wants to take responsibility and ownership for fixing it up and cutting a new release, I’m happy to provide permissions to do so.

Shai On Nov 24, 2020, 12:31 PM +0200, Tristan Richard [email protected], wrote:

Anything new on this? Any workaround? — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe.

freak4pc avatar Nov 24 '20 10:11 freak4pc

Demo code may be even simplier:

let realm: Realm = try! Realm()
try! realm.write {
    realm.add(MyObject())
}

let results = realm.objects(MyObject.self)

_ = Observable
    .array(from: results, synchronousStart: true, on: .main)
    .subscribe(onNext: { objects in
        print("Objects count: \(objects.count)")
    })

try! realm.write {
    realm.delete(results)
}

Expected output:

Objects count: 1
Objects count: 0

Actual output:

Objects count: 1

The issue is that we need to check both collections for equality to decide if we should or should not emit an event in initial which is cumbersome and close to impossible in practice.

RxRealm is just a wrapper around Realm and shouldn't bring unexpected side effects like this one. The other issue is that synchronousStart doesn't care about queue parameter so the initial event might even come from an unexpected queue. I really got hurt by this one spending days investigating so my proposal is to remove the synchronousStart parameter at all and do everything async. This one will be a major change though.

If that's approved I'll create a pull request

anton-plebanovich avatar Dec 07 '21 12:12 anton-plebanovich