Skip to content
This repository was archived by the owner on Aug 17, 2020. It is now read-only.
This repository was archived by the owner on Aug 17, 2020. It is now read-only.

Separate table change observation from querying #80

@m6s

Description

@m6s

Add a method Observable<List<String>> observeTables(String... tables) or similar to BriteDatabase, that notifies observers with a set of affected tables, but does not create any query.

Scenario: We sync cats and dogs stored on our backend, and persist them using a transaction.(pseudo-code, cursor/cv mapping omitted)

try (Transaction transaction = database.newTransaction()) {
    for(Cat cat: cats) {
        database.insert("cat", cat);
    }
    for(Dog dog: dogs) {
        database.insert("dog", dog);
    }
    transaction.markSuccessful();
}

We fetch all cats and dogs when initializing our view. (In real code in a background thread, obviously)

List cats = database.query("SELECT * FROM cat");
List dogs = database.query("SELECT * FROM dog");
catAndDogView.setCatsAndDogs(cats, dogs);

How do I make this reactive?

Observable<List> cats = database.createQuery("cat", "SELECT * FROM cat");
Observable<List> dogs = database.createQuery("dog", "SELECT * FROM dog");
Observable.combineLatest(cats, dogs, (cats, dogs) -> new Object[]{cats, dogs})
    .subscribe(objects -> catAndDogView.setCatsAndDogs(objects[0], objects[1]));

This is flawed, because I'm now getting two updates per transaction. Replacing combineLatest() with zip() won't do neither, because then I'm missing out on updates that involve only cats, or only dogs. A work-around is having each query triggered by changes on either table, but that comes at the expense of running some redundant queries.

As an added benefit of my proposal, having the opportunity to react to table changes myself, would allow me to create DAOs with synchronous methods, and reusing these methods when I want to create reactive versions.

class DAO {
    List<Cat> findBlackCats(BriteDatabase database) {
        return database.query("SELECT * FROM cat WHERE color = black");
    }
}

Observable<List<Cat>> blackCats = database.observeTables("cat")
    .map(ignore -> dao.findBlackCats(database));

My proposal is based on what SquiDB seems to offer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions