Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic region tracking for ValueObservation #586

Merged
merged 25 commits into from
Aug 5, 2019

Conversation

groue
Copy link
Owner

@groue groue commented Aug 3, 2019

This pull request introduces a new very simple way to define a ValueObservation 😍

// NEW!
let observation = ValueObservation.tracking { db in
    // Just fetch and return the values you want to track
}

For example:

// Observe all players
let observation = ValueObservation.tracking { db in
    try Player.fetchAll(db)
}

observation.start(
    in: dbQueue,
    onError: { error in ... }
    onChange: { (players: [Player]) in
        print("Fresh players: \(players).")
    })

The old method tracking(_:fetch:) is still present, but is now presented as an optimized version which can help reduce write contention when you use a DatabasePool and the fetch is slow:

// Optimized for DatabasePool and slow fetches
let observation = ValueObservation.tracking(region, ...) { db in
    // Fetch and return values
}

There are two new internal features behind this pull request:

  • Observations are now able to automatically infer their tracked region from the executed fetch request(s):

    // Observes the row of id 1 in the player table
    let observation = ValueObservation.tracking { db in
        try Player.fetchOne(db, key: 1)
    }
  • The database region tracked by an observation is able to change as time passes and observed values are refreshed.

    This allows to perform conditionals (if, guard, switch) during the fetch.

    For example, the observation below tracks only the team database table, or both the team and player tables, depending on the presence or absence of the tracked team as time passes and database gets modified:

    let teamId = 123
    let observation = ValueObservation.tracking { db -> (Team, [Player])? in
        guard let team = try Team.fetchOne(db, key: teamId) else {
            return nil
        }
        let players = Player.filter(teamId: teamId).fetchAll(db)
        return (team, players)
    }

@groue groue added this to the GRDB 4.2.0 milestone Aug 3, 2019
@groue groue merged commit 82d80d4 into development Aug 5, 2019
@groue groue deleted the dev/value-observation-variable-region branch August 5, 2019 17:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant