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

feature: Configure Redwood Realtime in GraphQL Yoga #8397

Merged

Conversation

dthyresson
Copy link
Contributor

@dthyresson dthyresson commented May 23, 2023

This PR:

  • updates the GraphQLYogaOptions to include config for "realtime" and HandlerOption (no omit this)
  • realtime config lets you pass in setting to setup subscriptions and live queries
  • if realtime config is provided, then Yoga will add a useRedwoodRealtime Yoga plugin to add the live directive to the schema and also register the useLiveQuery plugin automatically with the provided live query store which is also is added to the context for use in services/resolvers
  • If realtime subscription configuration is provide, subscriptions are merged into the executable schema and a the pubSub transport is added to the context for use in services/resolvers
// api/server.ts

await fastify.register(redwoodFastifyGraphQLServer, {
    loggerConfig: {
      logger: logger,
      options: { query: true, data: true, level: 'trace' },
    },
    graphiQLEndpoint: '/.redwood/functions/graphql',
    sdls,
    services,
    directives,
    allowIntrospection: true,
    allowGraphiQL: true,
    realtime: {
      subscriptions: { subscriptions, pubSub },
      liveQueries: { liveQueryStore },
    },
  })

will need the pubSub and liveQueryStore say from

// api/src/lib

import { createPubSub, InMemoryLiveQueryStore } from '@redwoodjs/graphql-server'

export const liveQueryStore = new InMemoryLiveQueryStore()

export type PubSubChannels = {
  newMessage: [payload: { from: string; body: string }]
}

export const pubSub = createPubSub<PubSubChannels>()

and then can use the store and pubSub

import { logger } from 'src/lib/logger'

export const room = ({ id }) => [id]

// import type { PubSubChannels } from 'src/lib/realtime'
// important to be async!
export const send = async (
  { input }: { input: { roomId: string; from: string; to: string } },
  { context }: { context: { pubSub } }
) => {
  logger.debug({ input }, 'send input')

  const { roomId, ...newMessage } = input

  context.pubSub.publish(roomId, newMessage)

  return input
}

or

export const bid = async ({ input }, { context }) => {
  const { auctionId, amount } = input

  const index = auctions.findIndex((a) => a.id === auctionId)

  const bid = { amount }

  auctions[index].bids.push(bid)
  logger.debug({ auctionId, bid }, 'Added bid to auction')

  const key = `Auction:${auctionId}`
  context.liveQueryStore.invalidate(key)

  logger.debug({ key }, 'Invalidated auction key in liveQueryStore')

  return bid
}

OUT OF DATE: I did figure out a way to add the directive in the schema generation, but see comment below about detecting if a project is "serverful" or can "support realtime".

Note: The one outstanding issue is that the @live directive is not generated when generated the graphql schema and types.

I may be able to solve this with a setup realtime that adds the sdl:

"""
Instruction for establishing a live connection that is updated once the underlying data changes.
"""
directive @live(
  """Whether the query should be live or not."""
  if: Boolean = true

  """
  Propose a desired throttle interval ot the server in order to receive updates to at most once per "throttle" milliseconds. The server must not accept this value.
  """
  throttle: Int
) on QUERY

This issue is that the recommended approach is to do:

import { makeExecutableSchema } from "@graphql-tools/schema";
import { astFromDirective } from "@graphql-tools/utils";
import { GraphQLLiveDirective } from "@n1ru4l/graphql-live-query";
import { print, GraphQLSchema } from "graphql";

const typeDefinitions = /* GraphQL */ `
  type Query {
    ping: Boolean
  }
`;

const resolvers = {
  Query: {
    ping: () => true
  }
};

const liveDirectiveTypeDefs = print(
  astFromDirective(GraphQLLiveDirective)
);

export const schema = makeExecutableSchema({
  typeDefs: [typeDefinitions, liveDirectiveTypeDefs],
  resolvers
});```

But the way sdl is consumed via the CodeFileLoader in codeine, string interpolation isn't allowed, so the actual live directive cannot be loaded. And I don't want to add the dependencies in internal to import the live query packages..

@dthyresson dthyresson self-assigned this May 23, 2023
@dthyresson dthyresson added the release:feature This PR introduces a new feature label May 23, 2023
@dthyresson dthyresson force-pushed the dt-use-redwood-live-query-plugin branch from fd1449f to 05fead0 Compare May 24, 2023 15:08
@dthyresson dthyresson changed the title DRAFT: feature: Configure Redwood Realtime in GraphQL Yoga feature: Configure Redwood Realtime in GraphQL Yoga May 24, 2023
@replay-io
Copy link

replay-io bot commented May 24, 2023

18 replays were recorded for eadb7b3.

image 0 Failed
image 18 Passed

View test run on Replay ↗︎

@dthyresson dthyresson requested a review from jtoar May 25, 2023 12:12
@@ -20,6 +20,11 @@ export const generateGraphQLSchema = async () => {
'subscriptions/**/*.{js,ts}': {},
}

// If we are serverful, we need to include the live directive for realtime support
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jtoar It would be nice to have a convenience method to know if one is "server" capable or not.

It helps here because I know to add the live query directive to the schema, since it is only really possible when realtime is possible.

It could help also with the Inngest plugin codemod to know if the GraphQL config should be modified in the handler function or in the server file declaration to create Yoga.

Could there be a a config toml setting the the server file? And then something there to see if "serverful"?

Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I move this as a convenience function in project-config?

@dthyresson dthyresson marked this pull request as ready for review May 25, 2023 12:17
Copy link
Collaborator

@Josh-Walker-GM Josh-Walker-GM left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally with @dthyresson and it worked great. There's some discussion to have around config values and the best place for them to live but that shouldn't block this just now.

@dthyresson dthyresson force-pushed the dt-use-redwood-live-query-plugin branch from 2c84d4a to bdb7d05 Compare June 1, 2023 14:48
dthyresson and others added 2 commits June 1, 2023 11:04
Co-authored-by: Josh GM Walker <56300765+Josh-Walker-GM@users.noreply.github.com>
@dthyresson dthyresson force-pushed the dt-use-redwood-live-query-plugin branch from bdb7d05 to fc0cf00 Compare June 1, 2023 15:04
@dthyresson dthyresson enabled auto-merge (squash) June 1, 2023 15:05
@dthyresson dthyresson merged commit 29edb41 into redwoodjs:main Jun 1, 2023
25 checks passed
@redwoodjs-bot redwoodjs-bot bot added this to the next-release milestone Jun 1, 2023
jtoar pushed a commit that referenced this pull request Jun 1, 2023
* Implement useRedwoodLiveQuery

* Test useRedwoodLiveQuery

* Rename to Realtime, add pub sub

* Handle RedwoodRealtimeOptions and auto allow subs if ok

* Refactor for realtime yoga config

* Document realtime types

* Apply suggestions from code review

* Fix yarn.lock

* Changes PubSub type

* include the live directive for realtime support

* Adds realtime graphql schema test case for live query directive

* Ensure live query actually added to schema (just once)

* Remove stray console.debug

* yarn dedupe

* Update test snapshot

* Update packages/graphql-server/src/createGraphQLYoga.ts

Co-authored-by: Josh GM Walker <56300765+Josh-Walker-GM@users.noreply.github.com>

* Improved the should update schema with live directive test

---------

Co-authored-by: Josh GM Walker <56300765+Josh-Walker-GM@users.noreply.github.com>
@jtoar jtoar modified the milestones: next-release, temp Jun 2, 2023
@steveoOn
Copy link

steveoOn commented Jun 6, 2023

Hey guys, does this feature add to the latest release 5.2.4? I really need GraphQL Subscription for realtime data query with OpenAI stream completion

@dthyresson
Copy link
Contributor Author

Hey guys, does this feature add to the latest release 5.2.4? I really need GraphQL Subscription for realtime data query with OpenAI stream completion

Hi @steveoOn No, this is not in 5.2.4 but is in canary. That said, this PR is just one milestone of a much longer roadmap https://www.notion.so/redwoodjs/Public-Roadmap-6ade052af6414aca897cfd0bf3ae0641?pvs=4 for Realtime. I don't think the milestones are publicly available, but still to come are:

  • get auth to work
  • document
  • get working with a serverful deploy -- this does not work in serverless nor will it
  • update to latest Yoga v4 subscriptions
  • DX for generating subscriptions
  • and more

The goal for realtime is to have it in v6 and we'll have updates along the way.

When the auth and serverful deploy items are sorted out, I hope to have this in a release candidate for people to try.

It won't be long and we'll make an announcement -- so it's coming, but just not ready to try out at the moment.

Thanks for your interest -- it's a long coming and exciting new feature!

@jtoar jtoar modified the milestones: next-release, v6.0.0 Jun 6, 2023
jtoar added a commit that referenced this pull request Jun 6, 2023
@steveoOn
Copy link

steveoOn commented Jun 7, 2023

Hey guys, does this feature add to the latest release 5.2.4? I really need GraphQL Subscription for realtime data query with OpenAI stream completion

Hi @steveoOn No, this is not in 5.2.4 but is in canary. That said, this PR is just one milestone of a much longer roadmap https://www.notion.so/redwoodjs/Public-Roadmap-6ade052af6414aca897cfd0bf3ae0641?pvs=4 for Realtime. I don't think the milestones are publicly available, but still to come are:

  • get auth to work
  • document
  • get working with a serverful deploy -- this does not work in serverless nor will it
  • update to latest Yoga v4 subscriptions
  • DX for generating subscriptions
  • and more

The goal for realtime is to have it in v6 and we'll have updates along the way.

When the auth and serverful deploy items are sorted out, I hope to have this in a release candidate for people to try.

It won't be long and we'll make an announcement -- so it's coming, but just not ready to try out at the moment.

Thanks for your interest -- it's a long coming and exciting new feature!

Hi @dthyresson , Thanks for your reply~ I'm very exciting about this feature, I believe we have lots of Redwood JS fans who need it. I've been paying attention at Redwood since 2019 and really love it, now I use it to develop AI products, the DX is fantastic! I'm really looking forward to getting this in v6 as soon as possible, and maybe it takes a best-practice example to interact with OpenAI 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release:feature This PR introduces a new feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants