downloading folders from google drive.

I wanted to download some course material on RL shared by the author via Google drive using the command line.  I got a bunch of stuff using wget a folder in google drive was a challenge. I looked it up in SO which gave me a hint but no solution. I installed gdown using pip and then used: gdown --folder --continue https://drive.google.com/drive/folders/1V9jAShWpccLvByv5S1DuOzo6GVvzd4LV if there are more than 50 files you need to use --remaining-ok and only get the first 50. In such a case its best to download using the folder using the UI and decompress locally. Decompressing from the command line created errors related to unicode but using the mac UI I decompressed without a glitch.

GraphQL with Apollo

My notes from Alexey Kureev's talk titled "Apollo Client: the stuff no-one ever told ya" by  @klarna 
in the React & React Native Meetup.

Meetup link:
REST is very widely used but as web applications have evolved over time with most of the processing happening at the client some of its features are now seen as performance bottlenecks. Some examples are that endpoint are separated as well as the entities but we typically want to query for data representing some relation between endpoint and slices of the entities. With REST this would require multiple requests and getting the full entities. GraphQL lets us do this using a single request and provides a more sophisticated way to make queries.

GraphQL is the evolution... Benchmarks published by facebook claim a 

The slides show how to consume a GraphQL data source using react.

Rest is now vintage - separated endpoint with separated entities
REST cons:
  • it provides deterministic URIs,
  • caching on the HTTP level

GraphQL supports reactive subscription data aggregation that doesn't really fit REST architecture that well.  With GraphQL, we need only one. As the name implies, GraphQL is a graph query language that changes the way you think of data. Instead of operating separated entities, you start to operate on data graphs. Let's take a closer look:

Operation pattern

GraphQL provides three operation types:

  1. Query
  2. Mutation
  3. Subscription

op_type Op_Name (op_params) {
  field_1
  field_2 (field_params) {
    subfields
  }
}

Query


query UserQuery ($id: Int!) {
  user (id: $id) {
    name
    email
  }
}

Mutation


mutation UserNameMutation ($id: Int!, name: String!) {
  editUserName (id: $id, name: $name) {
    name
  }
}

Subscription


subscription UserQuery ($id: Int!) {
  user (id: $id) {
    name
    email
  }
}
GraphQL shopping list example
GraphQL shopping list example - mockup

Shopping cart example


Shopping Cart Query


query ShoppingCartList {
  products {
    id
    title
    preview
    price
  }
}

Details query

 

query ProductInfo($id: Int!) {
  product(id: $id) {
    id
    title
    preview
    price
    isAvailable
    discountValue
    description
  }
}

We can now utilise reusable fragments


Define


fragment preview on Product {
  title
  preview
  price
}

Define


fragment details on Product {
  isAvailable
  discountValue
  description
}

Use


query ShoppingCartList {
  products {
    id
    ...preview
  }
}

Use


query ProductInfo($id: Int!) {
  product(id: $id) {
    id
    ...preview
    ...details
  }
}

But this is going to fetch - from the web


fragments can be cached separately.
so they can save transfer bandwidth.
1. readQuery

const { todo } = client.readQuery({
  query: gql`
    query Product($id: Int!) {
      product(id: $id) {
        title
        preview
      }
    }
  `,
  variables: { id: 5 }
});
2. readFragment

const todo = client.readFragment({
  id: 5, 
  fragment: gql`
    fragment productFragment on Product {
      title
      preview
    }
  `,
});
Memory cache
Only reads from local storage but will fail if some of the query is missing .
3. <Query fetchPolicy="cache-only" />

Only reads from local storage but will fail if some of the query is missing 
<Query 
  query={cacheQuery} 
  variables={{ id }}
  fetchPolicy="cache-only"
>
  {({ data = {} }) => <SomeComponent />
</Query>
for example: Shopping List screen
<Query query={shoppingCartList}>
  {({ loading, data }) =>  (
    <View>
      {loading && <Loading />}
      {!loading && <Products data={data.products} />}
    </View>
  )}
</Query>
But we want to get some data from local cache
and some from the server

1. Cached data query


query ProductInfoCache($id: Int!) {
  product(id: $id) {
    id
    ...preview
  }
}

And display via


<Query 
  query={productInfoCache} 
  variables={{ id }} 
  fetchPolicy="cache-only"
>
  {({ data = {} }) => // ...
</Query>



2. Missing (details) data query


query ProductInfo($id: Int!, $full: Boolean!) {
  product(id: $id) {
    id
    ...preview @include(if: $full)
    ...details
  }
}


Or Declaratively


<Query 
  query={productInfo}
  variables={{ id, full: !data.product }}
>
  ({ loading, data }) => //...
</Query>
Add cache redirect
const cache = new InMemoryCache({
  cacheRedirects: {
    Query: {
      product: (_, { id }) =>
        toIdValue(cache.config.dataIdFromObject({ 
          __typename: "Product", id
        })
      )
    }
  }
});

TRY IT OUT


Optimistic response … Every mutation or update - update is called

Optimistic UIs don’t wait for an operation to finish to update to the final state.

They immediately switch to the final state, showing fake data for the time while the real operation is still in-progress.

Remove item form the cached list

mutate({
  variables: { id },
  optimisticResponse: {
    __typename: 'Mutation',
    removeCartItem: {
      __typename: 'Product',
    },
  },
  update: (proxy) => {
    const data = proxy.readQuery({ query: ShoppingCartList });
    const filteredProducts = data.products.filter(product => product.id !== id);

    proxy.writeQuery({ 
      query: ShoppingCartList, 
      data: {...data, products},
    });
  },
});

P.S. graphics are by shadow.x.q84@gmail.com

Summing up: Alexey Kureev is an amazing story teller, able to take this complex technical topic 
and make it both interesting and exciting. I definitely will be looking into using GraphQL and
Apollo in future projects.

See also:


Comments

Popular posts from this blog

Moodle <=< Mediawiki SUL integration - first thoughts

downloading folders from google drive.

Insight into progressive web apps