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

Subscribe #121

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
Open

Subscribe #121

wants to merge 10 commits into from

Conversation

JeffML
Copy link

@JeffML JeffML commented Jun 17, 2020

subscribe impl notes

  • added graphql-subscriptions as a dev dependency
  • added optional pubsub arg to createSqlMancerClient(); type of any (TODO: typedef)
  • added pubsub to options arg that is passed to resolvers
  • added pubsub to BuilderOptions type
  • in tests/postgres/schema.ts I added Subscription type and resolver
    • imported PubSub from graphql-subscriptions; called by resolver
  • created a test (thanks for your help!) in integration.test.js.
  • you'll notice I'm exporting a pubsub instance from schema.js and using that for the tests

Other miscellaneous stuff

  • I added another test that attempts to use a trigger an event by using an actual mutation, but it doesn't work. It might be something to do with the mock but I didn't get too deep into it.
  • added a testOnly script in package.json that omits the --coverage flag
    • I used env DB=postgres POSTGRES_PASSWORD=testpassword npm run testOnly integration to run the tests
  • added sakila.db to .gitignore, because it was an empty file

I would call this a proof-of-concept implementation, nothing more. I'm sure there are improvements.

Remaining work:

  1. write a test that goes through the client to create a customer and trigger publish()
  2. add an argument to publish to pass as subscription payload
  3. write implementations for CreateMany, DeleteById, DeleteMany, UpdateById, and UpdateMany
  4. implement for other databases

Question:
Why the heck is setimmediate required in the test? I think this has something to do with lazy initialization of the AsyncIterator returned by graphql-subscriber publish(), but my thinking is pretty fuzzy on how setImmediate resolves that.

@coveralls
Copy link

coveralls commented Jun 17, 2020

Coverage Status

Coverage decreased (-0.03%) to 90.791% when pulling a0dde86 on JeffML:subscribe into 167681c on danielrearden:develop.

@danielrearden
Copy link
Owner

@JeffML Thanks for all your work on this. I'm sorry I still haven't had a chance to review it -- will do so as soon as possible

@JeffML
Copy link
Author

JeffML commented Jun 18, 2020 via email

@JeffML
Copy link
Author

JeffML commented Jun 19, 2020

I think the reduce coverage is due to my not implementing for other databases yet, so they are not getting the extra pubsub parameter.

Copy link
Owner

@danielrearden danielrearden left a comment

Choose a reason for hiding this comment

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

Sorry for the delay. This looks like a good start. I left a few comments. Feel free to leave additional replies to any comment, or ping me on discourse if you think a longer discussion is warranted

.gitignore Outdated Show resolved Hide resolved
src/types.ts Outdated Show resolved Hide resolved
src/types.ts Outdated Show resolved Hide resolved
src/__tests__/postgres/integration.test.ts Outdated Show resolved Hide resolved
src/__tests__/postgres/integration.test.ts Outdated Show resolved Hide resolved
Copy link
Author

@JeffML JeffML left a comment

Choose a reason for hiding this comment

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

All test seem to be passing, and I've run prettier on the code before pushing to my branch. To my understanding, this automatically updates the pull request.

Coveralls is still showing a fractional drop in coverage (-0.03%), but I can't seem to find the link that shows me what source is not covered. Anyhow, if you can re-review, great. I can go forward with the other databases, or we might talk first about how to DRY up some of the testing.

Copy link
Owner

@danielrearden danielrearden left a comment

Choose a reason for hiding this comment

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

Left additional comments.

@@ -6,4 +6,4 @@ node_modules
*.iml
*.code-workspace
.DS_Store
sakila.db
Copy link
Owner

Choose a reason for hiding this comment

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

suggestion: sakila.db is created and modified while running the SQLite integration tests. We don't want to check it by accident, so this should be left as-is.

@@ -79,6 +80,7 @@
"graphql": "15.1.0",
"graphql-middleware": "4.0.2",
"graphql-scalars": "1.1.5",
"graphql-subscriptions": "^1.1.0",
Copy link
Owner

Choose a reason for hiding this comment

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

suggestion: This should be in dependencies since it will be used during runtime and not just during build time

@@ -394,4 +394,62 @@ describeMaybeSkip('integration (postgres)', () => {
expect(errors).toBeUndefined()
expect(data?.films.some((f: any) => f.sequel && f.sequel.id)).toBe(true)
})

test('subscriptions', async () => {
Copy link
Owner

Choose a reason for hiding this comment

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

suggestion: This test can be removed.

This test is extraneous because it's not testing anything specific to the library.

expect(data.create).toBe('FLUM!')
})

// this skipped test is returning "GraphQLError: Cannot return null for non-nullable field Subscription.create" at `expect(subErrors).toBeUndefined()`
Copy link
Owner

Choose a reason for hiding this comment

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

suggestion: This comment is no longer necessary.

})

// this skipped test is returning "GraphQLError: Cannot return null for non-nullable field Subscription.create" at `expect(subErrors).toBeUndefined()`
test('subscription triggered by mutation', async () => {
Copy link
Owner

Choose a reason for hiding this comment

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

suggestion: This probably needs to be converted to a unit test for now.

Like I said before, we should probably start with unit tests to directly exercise any methods that are being added. The unit tests include a harness that lets you roll back any changes when doing mutations so that the tests don't have to worry about side-effects. We should probably add something similar to the integration tests. Right now I don't have any mutations included in the integration tests for this reason.

`)

const query = `mutation {
deleteCustomer(id: 1009)
Copy link
Owner

Choose a reason for hiding this comment

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

question: Why are we deleting a customer here?

const query = `mutation {
deleteCustomer(id: 1009)

createCustomer (input: {
Copy link
Owner

Choose a reason for hiding this comment

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

praise: Thanks for modifying this to exercise the publish method.

@@ -38,7 +38,8 @@ export type GenericSqlmancerClient = Knex & {

export function createSqlmancerClient<T extends GenericSqlmancerClient = GenericSqlmancerClient>(
glob: string,
knex: Knex
knex: Knex,
pubSub?: any
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
pubSub?: any
import { PubSub } from 'graphql-subscriptions'
pubSub: PubSub

In TypeScript, classes represent both types and values. PubSub describes both the type of an instance of PubSub and the underlying ES class.

@@ -74,6 +74,7 @@ export type Association = {
export type BuilderOptions = {
knex: Knex
dialect: Dialect
pubSub?: any
Copy link
Owner

Choose a reason for hiding this comment

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

see previous comment

* Publishes and event notifying subscriber of Change
*/
public publish(): this {
if (this._options.pubSub) {
Copy link
Owner

Choose a reason for hiding this comment

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

suggestion: Add tests to cover both branches of this if statement

You can view test coverage issues by clicking on the "Details" link under the failing Coveralls check

Screen Shot 2020-07-04 at 8 33 50 PM

Click on the "CHANGED" tab to view changed files

Screen Shot 2020-07-04 at 8 34 11 PM

Files with less coverage are shown in red

Screen Shot 2020-07-04 at 8 34 21 PM

Click the file link for a detailed view with problem areas highlighted

Screen Shot 2020-07-04 at 8 34 41 PM

The current test only exercises this method when this._options.pubSub is truthy. We need to also account for scenarios where that's not the case. This is also something that's better handled through unit tests than the integration tests.

@JeffML
Copy link
Author

JeffML commented Jul 5, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants