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

Imperative cache API #58

Closed
AlecAivazis opened this issue Mar 5, 2021 · 11 comments · Fixed by #748
Closed

Imperative cache API #58

AlecAivazis opened this issue Mar 5, 2021 · 11 comments · Fixed by #748
Labels
Enhancement A new feature or improvement to Houdini's public API Priority An issue that will be prioritized by the maintainers

Comments

@AlecAivazis
Copy link
Collaborator

Houdini needs to provide the user a way to interact with the cache imperatively to handle situations that aren't covered by the declarative API

@AlecAivazis
Copy link
Collaborator Author

AlecAivazis commented Mar 21, 2022

The biggest hurdle atm is how to compute the storage key for particular piece of data in the cache. I think the current selection object is not friendly enough for a user facing API so I think we need to come up with something different.

Fundamentally, writing data to the cache relies on 3 things besides the value: the ID of the object, the key of the field, and the type of the value (to marshal any complex values the user might provide).

Some use cases the API should cover:

  • Providing a new value for a field or link
  • Marking a certain field as stale
  • Refresh all current queries/stores

Some random thoughts:

  • if schema information is stored as users navigate the page it must be tied into garbage collection so we can delete it
    • this complicates manually preloading data since the schema isn't known before hand.
  • must be written to the top-most non-optimistic layer of the cache at write time
  • specifying the key manually can be made more ergonomic if we hide it behind something like myObject.getField("firstName", {arg: "Hello"})
  • store api's can be used to embed type information without having to store it in some global place
    • ie MyFragmentStore.writeToCache({ }) or MyFragmentStore.preload but that might be confusing on a QueryStore
    • Maybe something like cache.writeDocument({ document: MyFragmentStore, data: {}, variables: {} }) is better since its more clear its happening to the store itself
    • Specify a fragment means asking for the parent ID means giving the user a way to calculate the ID that doesn't couple them to the exact format used internally
  • are these methods on the cache, or methods on objects that represent an entity in the cache?
    • cache.write("User", "2", { ... }) looks alright but writeLink gets really gnarly since you need to embed a parent and a target which is just asking for arbitrary names that are hard to remember.

@AlecAivazis AlecAivazis moved this to To Do in Roadmap Jun 17, 2022
@AlecAivazis AlecAivazis added Enhancement A new feature or improvement to Houdini's public API Priority An issue that will be prioritized by the maintainers labels Jun 24, 2022
@jycouet
Copy link
Contributor

jycouet commented Jul 17, 2022

Not an easy topic, thx for putting a starting point 👍
I would also like to collect "Use Cases" to understand the different things to handle and provide THE good API.
I'll put notes here when I hit some

@m4tr1k
Copy link
Contributor

m4tr1k commented Oct 26, 2022

@AlecAivazis @jycouet so I found an interesting use case for this (I'm actually doing this on one of my projects):

  • so I have an entity (let's call it A) that has a list of other entity (let's call it B)
  • I have a mutation to delete B, and when deleting B I need to update A to reflect those changes on the screen
  • so I call the B delete mutation, and then I get all B from the list inside A to filter the deleted B
  • then I call Cache.write() function to update A with the new list of B

@jycouet
Copy link
Contributor

jycouet commented Nov 10, 2022

After a call with @AlecAivazis , let's put down a few thoughts:

// reset everything 
cache.markAllStale()

// root
const rootCache = cache.getRoot()

// reset all `quoteEdge`
rootCache.markStale("quoteEdge")
// GQL_quoteEdge.markStale();

// reset some fields
const quoteEdge = rootCache.getFields("quoteEdge")
quoteEdge.markStale("nodes")
quoteEdge.markStale("totalCount")
quoteEdge.set("totalCount", 10)

// set a reference
user.set("favoriteFood", cache.get("Recipe", {id: 5})

// reset some fields when specific inputs
rootCache.markStale("quoteEdge",  {edge: { pagination: { skip: 0 }, filters: { creatorUserId: null} }})
rootCache.markStale("user", { name: 'JYC'} )

// add an updater to the layer 
quoteEdge.set("totalCount", count => count + 1)

A lot of things are subject to change... but it's a start 😊

@frederikhors
Copy link
Contributor

Don't have this is a HUGE BLOCKER for us to switching from urql to houdini.

I wish you to work on it expressing the best of yourself. 😄

@AlecAivazis
Copy link
Collaborator Author

@frederikhors it's looking like this will be the next thing we focus on. stay tuned!

@AlecAivazis AlecAivazis mentioned this issue Dec 7, 2022
18 tasks
@AlecAivazis
Copy link
Collaborator Author

@frederikhors mind telling me which features/ use cases you need most out of the imperative api? I'm assuming marking data as stale is an important one but I'm curious if there are others?

@frederikhors
Copy link
Contributor

frederikhors commented Dec 8, 2022

For now I only need invalidation.

We're using it hard because we invalidate & refetch in case of update/delete of an item.

I'll let you know if something else is needed.

@AlecAivazis
Copy link
Collaborator Author

Awesome! Thanks for the quick reply. Would you want a way to automatically trigger refetches of the deleted value or is that something you would do by hand? Or just the next time the query is fired?

@frederikhors
Copy link
Contributor

I think this depends each time.

All the options? It's difficult?

@AlecAivazis
Copy link
Collaborator Author

Nope, not difficult just trying to figure out the priority for all of the features. There's a lot that I'd like to be able to do with this API but with 1.0 coming soon I'll have to shift focus over to accommodating some of the recent changes that will effect houdini so I'm trying to get something out quickly before I get distracted

Repository owner moved this from Backlog to Completed in Roadmap Dec 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement A new feature or improvement to Houdini's public API Priority An issue that will be prioritized by the maintainers
Projects
No open projects
Status: Completed
Development

Successfully merging a pull request may close this issue.

4 participants