Code Monkey home page Code Monkey logo

apollo-live-server's People

Contributors

lgandecki avatar moberegger avatar theodordiaconu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

apollo-live-server's Issues

Hybrid Reactive Data Graphs

If i'm requesting:

query {
   user {
       billingProfile { status }
   }
}

and a subscription with the same pattern.

The subscription needs to be intelligent enough to detect that it uses links.

apollo-live-server is kinda constructed around Meteor either way. But with this approach we're gonna introduce a dependency on Grapher. Which I think is ok, better to be in one ecosystem than deal with 4 diff packages.

So the logic would be that we don't have reactivity for underlying data, we have only for the parent.
This means that added() events should trigger a graph run for that item.
And changed() needs to detect whether a link storage field has changed that is related to a certain sub-collection so we can requery it.

This need to happen automatically without any other configuration such as hooking into resolve() and applying it based on the changed events.

Can't get subscriptions to work reliably

Hi guys,

After hours of trying pretty much everything I could come up with, I gave up for now - I can't get GraphQL subscriptions to work reliably. Randomly it kinda works, most of the time it does not.

Following setup:

  • Meteor v.1.8.1 App with React frontend and Grapher
  • apollo-live-server
  • apollo-live-client

What do I want to achieve (for now): Just load some items from a collection with a limit and skip (pagination). If something changes in the currently loaded (e.g. 20) items, the subscription should update the items - obviously. ๐Ÿ˜„

some code:

SERVER:

load({
  typeDefs: `
    type Query {
      lists(listId: ID, limit: Int, skip: Int): [List]
    }
    
    type List @mongo(name: "listsbody") {
      _id: ID
      itemId: ID,
      listItem: ListItem @link(field: "itemId")
      list_id: ID
      row_id: Int
    }

    type ListItem @mongo(name: "items") {
      _id: ID
      created_at: String
      supplier_id: ID,
      item_name: String
    }

    type Subscription {
      lists(listId: ID, limit: Int, skip: Int): SubscriptionEvent
    }

  `,
  // https://github.com/cult-of-coders/grapher/blob/master/docs/graphql.md
  resolvers: {
    Query: {
      lists(_, {listId, limit, skip}, { db }, ast) {
        return db.listsbody.astToQuery(ast, {
          $filters: { list_id: listId },
          $options: { limit, skip, sort: { row_id: 1 } }
        }).fetch();
      },
    },
    List: {
      listItem(parent, args, { db }, ast) {
        return parent.listItem;
      },
    },
    Subscription: {
      lists: {
        resolve: ({event, doc}, args, { db }, ast) => {
          if(event === Event.CHANGED) {
            Object.assign(doc, {
              listItem: db.items.findOne({ _id: doc.itemId })
            });
            // this is very infrequently called, for some reason this is NOT called everytime I change something in the DB, sometimes it is but after a verly large delay of many seconds.
          }
          console.log('resolve() doc:', doc);
          return {event, doc};
        },
        subscribe(_, {listId, limit, skip}, { db }, ast) {
          console.log('params', {listId, limit, skip});
          const observer = db.listsbody.find({ list_id: listId }, { limit, skip, sort: { row_id: 1 } });
          console.log('FETCH!', observer.fetch()); // again, this is sometimes called, sometimes it is not, sometimes with a very big delay ...
          return asyncIterator(observer);
        }
      }
    }
  },
});
initialize();

Any my Client:

const GET_LIST = gql`
  query($listId: ID, $limit: Int, $skip: Int) {
    lists(listId: $listId, limit: $limit, skip: $skip) {
      _id
      list_id
      row_id
      itemId
    }
  }
`

const SUBSCRIBE_LIST = gql`
  subscription($listId: ID, $limit: Int, $skip: Int) {
    lists(listId: $listId, limit: $limit, skip: $skip) {
      event
      doc
    }
  }
`

class Test extends React.Component {
  constructor() {
    super();
    this.state = {
      page: 1
    }
  }
  prevPage = () => {
    this.setState({ page: this.state.page - 1 });
  }
  nextPage = () => {
    this.setState({ page: this.state.page + 1 });
  }
  // https://www.apollographql.com/docs/react/v2.5/api/react-apollo/#optionsfetchpolicy
  render(){
    const {page} = this.state;
    const variables = {listId: "pshLYD4optX3yj9Pw", limit: 20, skip: (page-1)*20};
    console.log('variables', variables);
    return (
      <Fragment>
        <ul>
          <ReactiveQuery
            query={GET_LIST}
            variables={variables}
            subscription={SUBSCRIBE_LIST}
            fetchPolicy='no-cache'
          >
            {
              ({ loading, error, data }) => {
                if(loading) return <h2>loading</h2>
                if(error) {
                  console.log(error)
                  return <h2>Error</h2>
                }                
                let { lists } = data;
                console.log(lists);
                lists = lists.map(list => (
                  <li key={list._id}>
                    {list._id} - {list.itemId} - { list.listItem && list.listItem.item_name ||ย 'N/A' } : {list.row_id}
                  </li>
                ));
                // this is NOT working at all - no reloads, no updates, no nothing when I change anything in the DB - basically the subscription is dead alltogether         
                return lists
              }
            }
          </ReactiveQuery>
        </ul>
        <br />
        Seite {this.state.page}
        <button onClick={this.prevPage}>&lt;</button>
        <button onClick={this.nextPage}>&gt;</button>
      </Fragment>
    )
  }
}

I really really hope someone can help. I would be glad to even pay for maybe 30min - 1h of your time. I am pretty desperate right now, as I think my setup is pretty basic and it is not working at all.

Thanks a bunch for any help in advance! Cheers, Patrick

Allow for different PubSub alternatives?

I noticed that this package uses the default PuBSub which I believe is not recommended for production. Is there a facility to specify a different PubSub, or is this handled somewhere else in the cult-of-coders/apollo package?

Remove listeners when no longer needed.

W20180326-16:27:07.173(3)? (STDERR) (node:48927) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 removeListener listenersadded. Use emitter.setMaxListeners() to increase limit

Reactive Counts

type Subscription {
  notificationsCount: Int
}
  Subscription: {
    notificationsCount: {
      resolve: payload => payload,
      subscribe(_, args, { db }, ast) {
        return asyncIteratorInterval(() => return db.notifications.find().count(), 1000);
      }
    }
  }
  • We won't use observeChanges() here because it's far less performant than just your standard .count(). Especially when we're talking about counts for 1000, it'll have to keep 1000 _id's in the store. Too much.
  • Make sure that when subscription is stopped to clear the interval
  • Would be nice if there was a way to re-use this? But for now it's not crucial.

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.