apollographql / apollo-ios

📱  A strongly-typed, caching GraphQL client for iOS, written in Swift.
https://www.apollographql.com/docs/ios/
MIT License
3.87k stars 717 forks source link

Watcher not firing after failure to decode response #3342

Closed sameers27 closed 6 months ago

sameers27 commented 7 months ago

Summary

In our usage, we use watchers as a source of truth for response handling. The setup is to start a watcher on load, fetch when needed, expect the watcher to fire when changes occur due to the fetch, and allow the watcher to process the response.

This allows us to ensure that any changes to the underlying objects due to auxiliary requests or changes occurring to the objects due to a fetch are all centralized in the watcher result handler.

One issue we've observed is that if we receive a decoding error on the initial watch (backend sends something unexpected), and we enter the failure block on the result handler of the watcher, the watcher will never fire again on subsequent fetches or changes where data received during the fetch is correct.

Version

1.9.0

Steps to reproduce the behavior

Here's an example watcher, query, and setup

query HomeQuery {
    home {
        sections {
            id
            name
        }
    }
}

func watchHome() {
     homeWatcherCancellable = apollo.watch(query: HomeQuery(), resultHandler: { [weak self] response in
        switch response {
            case .success(let data):
                self?.home = data.home
            case .failure(let error):
                self?.failedWithError = error
        }
     }
}

func fetchHome() {
     homeFetchCancellable = apollo.fetch(query: HomeQuery())
}

func onLoad() {
    watchHome()
}

func refresh() {
    fetchHome()
}

Logs

No response

Anything else?

We also use a similar setup for subscriptions, where the watcher is responsible for handling the response.

AnthonyMDev commented 6 months ago

Hey there @sameers27. This does seem to be working as intended honestly. In order for the watcher to be able to watch for changes, it needs to get back the initial response, because that tells it what objects in the cache it needs to watch for changes on.

If your watcher is getting an error response form the server, the first thing I'd be concerned about is fixing whatever is causing that error (of course that's often easier said than done 😅).

Aside from that, if your watcher fails, you'll need to call it's refetch method and get a successful response for it to start actually watching those returned objects.

Theoretically, we could add something where the watcher watches for any successful response on the same exact query, but that's a departure from how they currently work. They are set up so that if the objects in the normalized cache change, from the same query or any other queries that happen to fetch the same objects, they will trigger. And for that, we are looking at the objects returned by the server, not the query operation that was sent.

If you would like to contribute that feature to query watchers, I would be happy to work with you on the design. But this isn't something that we plan on adding to our roadmap any time soon.

github-actions[bot] commented 6 months ago

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo iOS usage and allow us to serve you better.