Giter Site home page Giter Site logo

Comments (11)

AlecAivazis avatar AlecAivazis commented on July 20, 2024 1

Great! I'm happy to hear that it's working as expected. I'm going to go ahead and close this issue but I think you do bring up a good point about documenting subscription patterns so I'll open up another to track that effort.

from houdini.

AlecAivazis avatar AlecAivazis commented on July 20, 2024

Hey @thormuller!

Before we get too far, can you confirm that the subscription you have is returning a data field which is store whose value holds the most recent payload from the subscription? The cache should be storing and updating what it runs into but it won't know how to add them to another query's result. One helpful debugging tip is to attach your cache to the window so you can see what's going on from your browser's console. Eventually, I'd love to add a UI to interact with the cache (similar to the urql dev tools) but for now, this is the easiest way to check what records and values are known by the cache.

It sounds like what you are looking for is a "live query", however subscriptions in GraphQL are much more akin to a traditional event system. In order to support a live query from a single subscription, the server should return the full list of items in the subscription payload every time one of the fields in the selection changes. With that in place, you should be able to just replace the top-level query with a subscription (although that will prevent the data from being loaded for SSR since the server doesn't open a socket connection).

If you are looking for the payload of a subscription to be added to a query that's already triggered, you should be able to use same fragments from the connection mutation documentation in your subscription payload.

If you are instead looking to collect all of the results in a single list as the events come through, you should be able to use a reactive statement to push the contents of the store onto a list in your component's local state.

from houdini.

AlecAivazis avatar AlecAivazis commented on July 20, 2024

Oh, can you also confirm that the artifact that was generated for your subscription has a selection field that references the fields in the CardItem fragment? I want to make sure you aren't getting bitten by the compiler trying to be too smart

from houdini.

thormuller avatar thormuller commented on July 20, 2024

Here is the WS response. It has the payload/data and the items from the CardItem fragment, though is that what you mean by selection field?
"{"type":"data","id":"1","payload":{"data":{"allItems" : [{"id":"1ee4f35589430384d14b","title":"Mom's Kimchi ","klImages":"fe4f7814214fb7a15a9e498de8e17b3d.jpg"}]}}}

In any case I agree with you, I'm thinking that observing the cache would be the next best step for zeroing in on the solution. Where would you recommend attaching it to window in the context of ssr?

(P.S. Love your idea of direct interaction with the cache)

from houdini.

AlecAivazis avatar AlecAivazis commented on July 20, 2024

Don't worry about the selection bit, we can go down that rabbit hole later if its necessary.

Also, before you start interacting with the cache directly, I'd like to confirm that the subscription function is behaving as it should. Could you add something like this to your component?

const { data } = subscription(...)

$: console.log($data)

And make sure that you are seeing values for data that you expect? It should start off as null and then get the value you showed above

from houdini.

thormuller avatar thormuller commented on July 20, 2024

Yes, t is generating the results as expected. I double checked with an update on the server and it responded properly.

from houdini.

thormuller avatar thormuller commented on July 20, 2024

Oh, how would you recommend logging the cache? I still think that would be helpful at this stage.

from houdini.

AlecAivazis avatar AlecAivazis commented on July 20, 2024

Ah yea sorry I forgot about that. The quickest way to do it is to import the cache directly in your environment.ts and assign it to the window, inside of an if (browser) check. It would look something like:

import cache from '$houdini/runtime/cache'
import { browser } from '$app/env'

if (browser) {
    window.cache = cache
}

Please keep in mind that the cache is not really ready for direct use and shouldn't be used for anything outside of debugging. If you find yourself needing to use it in your application logic, please let me know so we can see if there's a better approach.
Probably worth mentioning that I definitely think the cache should usable in application logic, its just not there yet. In fact, I think mixing reactive statements with a programmatic cache API make for a very nice alternative to the updater functions that relay and apollo force on us but until #58 goes in, you should consider interacting with the cache as totally unstable. That api is likely to change unannounced

from houdini.

thormuller avatar thormuller commented on July 20, 2024

Great explanation. Thanks! I have what I need now.

from houdini.

thormuller avatar thormuller commented on July 20, 2024

One other mystery–though it's not a blocking issue for me at present, it may be relevant for debugging and documentation.

The subscription on the full list is working well and it's straightforward to update a Svelte store as we've discussed. However, I wanted to understand the other pattern in the Example project where the subscription is on the component fragment, so I implemented that. The good news is that it updates the cache as I'd expect. But I'm seeing the following behavior which is inexplicable to me.

First, I observed that the component that should be re-rendered with new data upon the subscription update was instead empty. When I then logged the reactive value of { data } for the original AllMyItems query I saw that it was indeed returning an empty array after the subscription update, despite what appears to be an accurate cache. I've confirmed that all other data appears to be the same between the original and the updated cache.

from houdini.

draylegend avatar draylegend commented on July 20, 2024

how can I use subscriptions with ssr enabled?

I get the error:

6:57:18 PM [vite] Error when evaluating SSR module /src/environment.js:
Error: WebSocket implementation missing
    at Proxy.createClient (D:\dev\web\tests\todo\node_modules\graphql-ws\lib\client.js:76:15)
    at /src/environment.js:30:13
    at async instantiateModule (D:\dev\web\tests\todo\node_modules\vite\dist\node\chunks\dep-63d4bd14.js:75119:9)
6:57:18 PM [vite] Error when evaluating SSR module /src/lib/config.ts:
Error: WebSocket implementation missing
    at Proxy.createClient (D:\dev\web\tests\todo\node_modules\graphql-ws\lib\client.js:76:15)
    at /src/environment.js:30:13
    at async instantiateModule (D:\dev\web\tests\todo\node_modules\vite\dist\node\chunks\dep-63d4bd14.js:75119:9)
6:57:18 PM [vite] Error when evaluating SSR module /src/routes/__layout.svelte:
Error: WebSocket implementation missing
    at Proxy.createClient (D:\dev\web\tests\todo\node_modules\graphql-ws\lib\client.js:76:15)
    at /src/environment.js:30:13
    at async instantiateModule (D:\dev\web\tests\todo\node_modules\vite\dist\node\chunks\dep-63d4bd14.js:75119:9)
WebSocket implementation missing
Error: WebSocket implementation missing
    at Proxy.createClient (D:\dev\web\tests\todo\node_modules\graphql-ws\lib\client.js:76:15)
    at /src/environment.js:30:13
    at async instantiateModule (D:\dev\web\tests\todo\node_modules\vite\dist\node\chunks\dep-63d4bd14.js:75119:9)

environment.js

import { browser } from '$app/env';
import { Environment } from '$houdini';
import { createClient } from 'graphql-ws';

const ws = browser
	? createClient({
			url: 'wss://bu3ff.sse.codesandbox.io/graphql',
	  })
	: null;

console.log(ws);

export default new Environment(async function ({ text, variables = {} }) {
	// send the request to the api
	const result = await this.fetch('https://bu3ff.sse.codesandbox.io/graphql', {
		method: 'POST',
		headers: {
			'Content-Type': 'application/json',
		},
		body: JSON.stringify({
			query: text,
			variables,
		}),
	});

	// parse the result as json
	return await result.json();
}, ws);

svelte.config.js

import houdini from 'houdini-preprocess';
import { resolve } from 'path';
import preprocess from 'svelte-preprocess';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	preprocess: [houdini(), preprocess()],

	kit: {
		target: '#svelte',
		vite: {
			resolve: {
				alias: {
					$components: resolve('.', 'src', 'components'),
					$houdini: resolve('.', '$houdini'),
				},
			},
		},
	},
};

export default config;

from houdini.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.