Home Kolin, Delegated (Lazy) Properties and GraphQL
Post
Cancel

Kolin, Delegated (Lazy) Properties and GraphQL

TLDR; Use lazy properties to avoid unecessary database connections and queries. Also use optional properties to avoid n+1 queries.

The big backstory is that I’m working on an API gateway that allows clients to access various backend services without knowing the specific data shapes expected by, and returned by, each, what content type each service is expecting, or even what data comes from wich. You know, an API gateway. It was decided that this gateway would implement a GraphQL interface using the graphql-kotlin library. I’ll go more into this decision in a future post (hopefully). This post covers a solution I came across for a situation involving data sourced from two different databases. I wanted to avoid making unecessary queries, both via overfetching, and n+1 queries.

Schema and Query

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Book {
  authors: String
  id: Int!
  imageUrl: String
  product: Product
  product_id: Int
  title: String
}
type Product {
  id: Int!
  name: String!
  price: Float!
}

In the data shape above we have a clear split between Book metadata and Product sales information. This split makes sense from a schema perspective because the situations where product information is needed is a distinct group (Store Page, Shopping Cart). Whereas the metadata is useful in those situations, as well as other (content production). In addition, this makes implementation a bit easier.

The actual data is stored within two separate services. Book metadata is stored in a service that handles user ownership (Bookshelf), and user generated content, such as annotations, bookmarks, and highlights. The product information is stored by service that handles sales operations (Shop) In order to satisfy a query like the one below at least two queries would have to be performed, one to the Bookshelf and one to the Shop service

1
2
3
4
5
6
7
8
9
10
11
query($searchParameters: BookSearchParametersInput!) {
  searchBooks(searchParameters: $searchParameters) {
    id
    imageUrl
    productId
    title
    product {
      price
    }
  }
}

Initial Implementation

Lampshade the passthrough layer (using jooq directly)

1
// slimed down version that makes request in one go

(Explaintaion on why this wont work). If we were to make the following query, an unecessary request would be made against the Shop database

Soloution 1: Lazy Properties

Problem 2: A shit load of queries

This works ok, but can lead to n+1 queries (brief explain). This is a massive was of time and network resources.

Solution 2: Optionally set the Product info on creation.

Look at graphql query env, see if product is in there, make the query (dollar sign)

-->