HoudiniGraphql / houdini

The disappearing GraphQL client
http://www.houdinigraphql.com
MIT License
895 stars 94 forks source link

List operations (append and update) from subscriptions does not work if the root type is a union #1305

Open adminorcail opened 2 months ago

adminorcail commented 2 months ago

Describe the bug

Hi! First of all, thanks for maintaining Houdini, it is a really nice thing to have as a dev :)

We recently ran into an issue using Houdini: we are using both query operations to fetch a list of records (that is stored using the @list directive), and subscribe to changes on these records.

Here are the declared GraphQL types: schema.graphql

type Subscription {
    onSummaryEvent(input: SubscribeToSummaryEvents!): SummaryEvent
    onNewSummary(input: SubscribeToSummaryEvents!): Summary
}

When we try to insert a record into the list using this subscription: +page.svelte

const onNewSummary = graphql(`
    subscription SubscribeToNewSummaries($input: SubscribeToSummaryEvents!) {
        onNewSummary(input: $input) {
            __typename
            ...Game_Ordered_Summaries_insert
        }
    }
`);

it works flawlessly.

However, because we want to limit the number of subscriptions, we group insertion, updates and removal of a record into a single union type: schema.graphql

interface EntityEvent {
    eventId: String!
    eventType: EventType!
}

type SummaryCreatedEvent implements EntityEvent {
    eventId: String!
    eventType: EventType!
    gameId: ULID!
    summaryId: ULID!
    payload: Summary!
}

type SummaryUpdatedEvent implements EntityEvent {
    eventId: String!
    eventType: EventType!
    gameId: ULID!
    summaryId: ULID!
    payload: Summary!
}

type SummaryDeletedEvent implements EntityEvent {
    eventId: String!
    eventType: EventType!
    gameId: ULID!
    summaryId: ULID!
    payload: Summary!
}

union SummaryEvent = SummaryCreatedEvent | SummaryUpdatedEvent | SummaryDeletedEvent

On the server-side, we return the appropriate __typename for each type, and this is successfully retrieved by this subscription: +page.svelte

const onSummaryEvent = graphql(`
    subscription SubscribeToSummaryEvents($input: SubscribeToSummaryEvents!) {
        onSummaryEvent(input: $input) {
            ... on SummaryCreatedEvent {
                __typename
                payload {
                    ...Game_Ordered_Summaries_insert
                }
            }
            ... on SummaryUpdatedEvent {
                __typename
            }
            ... on SummaryDeletedEvent {
                __typename
                payload {
                    ...Game_Ordered_Summaries_remove
                }
            }
        }
    }
`);

When we subscribe to the store and log the received events, we can see that, indeed, everything looks fine. But appart from the remove list operation, neither the insert nor the update operations work, which is strange considering that this is the exact same thing as the single onNewSummary subscription, except it's now based on union types resolution.

I think it's a bug, but I could be wrong, could you help me with this situation?

As a workaround, we could update the cache manually, it's just more code and not as nice as the automatic list operations.

Reproduction

No response

AlecAivazis commented 2 months ago

Ah damn! I knew this day was coming. It is a bug - something I have known about for a good while and keep telling myself I need to fix. I will try to find some time to dig into it but It might take me awhile. If you or someone at work has the time to dig into it, I can show you pretty much exactly where the problem is.

AlecAivazis commented 1 month ago

I found some time to dig into this and I'm not confident that this is being caused by what I thought. it might be hard to debug this one over an issue. would it be possible to put together a reproduction?