React: The Documentary

The documentary on the origins of React is finally out! This technology fundamentally changed the way the world did front-end development and how we create web application. I’m super proud and honored to be representing the innovative folks at Netflix who were brave enough to adopt this transformative new technology and outrun the competition.

Simple Cache Expiration for Apollo GraphQL Queries

The Problem

There are times when you want to fetch data from your server that is occasionally changed. For example, getting the number of unread messages in an application. There are a few possible solutions for keeping the data up-to-date with the backend. 1) You can poll the server every X minutes, or 2) you can use “cache-and-network” to utilize the cache first, but also check the server for updated data.

Polling

If you choose to poll for new messages, you run the risk of your application constantly calling the server for data even though the user has not recently interacted with the page. Think, checking another tab or walking away from the computer for a while. While not detrimental, this results in a lot of wasted calls and network requests.

Cache and Network

This method ensures you always have the most up-to-date information from the server, but also results in a lot of needless calls to the server. The client is constantly saying, “Ok, I’ll use the cache, but let me still call the server to check for updated data.” This query/hook may run multiple times on a single user interaction and is still to aggressive for data that only updates every few minutes.

The Solution

What we really want is the best of both worlds. We want to utilize the cache as much as possible, but also set an expiration for when to grab fresh data from the server. We can use a simple technique of utilizing Map and dates to accomplish this goal.

We’ll simply make a unique “key” for our query and record the last time we fetched that key. When we call useQuery, we pass it our “key” and the expected expiration time. If the “key” is still valid, we return to useQuery the fetchPolicy of “cache-first.” This means, use the cache if it exists and otherwise fetch from the server. If the “key” is invalid, we call useQuery with “network-only” which calls the server to refresh the data. And at the same time, we update the last fetched time of the key.

Let’s take a look at an example of the getFetchPolicyForKey() function and its implementation.

useUnreadMessages.ts

import { getFetchPolicyForKey, ONE_MINUTE } from "./hooks/useCacheWithExpiration";

export const useUnreadMessages = (): number => {
    let unreadMessages: number = 0;

    const { data, error } = useQuery(UNREAD_MESSAGES_DOC, {
        fetchPolicy: getFetchPolicyForKey("unreadMessages", ONE_MINUTE * 5),
    });

    if (isDefined(data)) {
        unreadMessages = data.unreadMessages
    }

    return unreadMessages;
}

And here’s the implementation of the cache check and when to return each fetch policy.

getFetchPolicyForKey.ts

// Record of keys and the last fetched timestamp
// These are universal for all calls and hooks
const keys = new Map<string, number>();

export const ONE_MINUTE = 1000 * 60;

/**
 * This function accepts a unique key and an expiration date. It returns "network-only" if the cache key is expired
 * or "cache-first" if the key is still valid for the given expiration time
 *
 * @param key - the unique name you want to give this expiration key
 * @param expirationMs)
 */
export const getFetchPolicyForKey = (key: string, expirationMs: number): WatchQueryFetchPolicy => {
    const lastFetchTimestamp = keys[key];
    const diffFromNow = lastFetchTimestamp ? Date.now() - lastFetchTimestamp : Number.MAX_SAFE_INTEGER;
    let fetchPolicy: WatchQueryFetchPolicy = "cache-first";

    // Is Expired?
    if (diffFromNow > expirationMs) {
        keys[key] = Date.now();
        fetchPolicy = "network-only";
    }

    return fetchPolicy;
};

Financial Overview V2 – Track your stock portfolio and retirement accounts with Google Sheets

I’d like to share the spreadsheet I use for tracking my entire financial overview. I’ve always preferred keeping track of my accounts in a spreadsheet for 2 reasons. (1) I don’t like giving my personal financial information to a 3rd party. (2) I can use spreadsheets to analyze data and even perform custom calculations. Such as, what’s the delta on the current price vs the 52 week low.

I’ve been slowly building this over the last few years and it is finally time to share V2. Here are the main features I like about this spreadsheet:

  • Tracks investments across multiple institutions and account types (IRA, 401k, brokerage)
  • Shows portfolio distribution by holding type and account
  • Tracks heaviest investments across all accounts
  • Live charts for stocks
  • Live expense ratios for ETFs and Funds
  • Track heaviest positions across stocks and funds
  • See your diversification across accounts and investment categories

So without further ado, here is the spreadsheet for you to copy.

See types of diversification
Track heaviest positions

Custom PM Sensor for Poor Air Quality

We’ve been having bad air in the Bay Area for a few weeks now and it got me wondering how much was seeping into my house and garage. After a little tinkering, I finished a custom, portable PM2.5 and PM10.0 sensor. The initial build used a SDS011, which promptly died after a week. I moved on to the “less” accurate PMS5003 and have been quite happy with the results. Here’s the sensor in action.

Google Sheet for Tracking Your Portfolio

I’d like to share the spreadsheet I use for tracking my portfolio. I’ve always preferred keeping track of my portfolio in a spreadsheet for 2 reasons. (1) I don’t like giving my personal financial information to a 3rd party. (2) I can use spreadsheets to analyze data and even perform custom calculations. Such as, what’s the delta on the current price vs the 52 week low.

I’ve been slowly building this over the last few years and it is finally time to share. Here are the main features I like about this spreadsheet:

  • Tracks investments across multiple institutions and account types (IRA, 401k, brokerage)
  • Shows portfolio distribution by holding type and account
  • Tracks heaviest investments across all accounts
  • Live charts for stocks
  • Live expense ratios for ETFs and Funds

So without further ado, here is the spreadsheet for you to copy.