who-owns-what icon indicating copy to clipboard operation
who-owns-what copied to clipboard

Fall back to something if we exceed our Google Maps street view quota

Open toolness opened this issue 5 years ago • 2 comments

We have a quota of 2,500 street view uses per day and it gets exhausted near the end of the day, but it's super expensive to increase our quota, so it'd be nice to have a fallback when the quota goes over.

I found a Stack Overflow question about this and Google seems to make it unusually hard to detect when such a condition has occurred.

According to Google's docs, if we define a global function called gm_authFailure(), it will be called in the event of an authentication failure, but as far as I can tell it isn't called when we're over our quota limit (it does get called if I change our API key to something invalid).

One way to do it is by overriding console.log or console.error or something, but that feels weird to me for some reason. I guess I am concerned that a browser's developer tools may overwrite our monkeypatch or something, or maybe it's just because we're using the console object for non-development purposes, I'm not sure.

Another method, which isn't really much better, is to just check the DOM for any sign of what Google shows us when we've exceeded our quota:

image

The text This page can't load Google Maps correctly is in a <span> and there aren't many spans in the Google Street View widget, so one option is to just regularly check the widget's DOM to see if it has a span with that text.

Below is a Create React App proof-of-concept that seems to work okay in practice, although it's very rough and could use lots of improvements:

import React, { createRef, useState, useEffect } from 'react';
import {withScriptjs, withGoogleMap, StreetViewPanorama} from 'react-google-maps'
import './App.css';

const pos = { lat: 49.2853171, lng: -123.1119202 };

const MyMapRaw: React.FC = props => {
  return (
    <StreetViewPanorama visible defaultPosition={pos} options={{
      disableDefaultUI: true,
      enableCloseButton: false,
      panControl: true,
      fullscreenControl: true
    }} />
  );
};

const MyMap = withScriptjs(withGoogleMap(MyMapRaw));

const MyMapWithFallback: React.FC = props => {
  const ERR_TEXT = "This page can't load Google Maps correctly.";
  const ERR_TEXT_CHECK_MS = 250;
  const key = 'AIzaSyCuf0Ca1EvxogvbZQKOBl_40y0UWm4Fk30';
  const mapURL = `https://maps.googleapis.com/maps/api/js?key=${key}&v=3.exp&libraries=geometry,drawing,places`;
  const ref = createRef<HTMLDivElement>();
  const [isOverQuota, setIsOverQuota] = useState(false);

  useEffect(() => {
    const interval = window.setInterval(() => {
      if (ref.current) {
        const spans = ref.current.querySelectorAll('span');
        for (let i = 0; i < spans.length; i++) {
          if (spans[i].textContent === ERR_TEXT) {
            setIsOverQuota(true);
            window.clearInterval(interval);
          }
        }
      }
    }, ERR_TEXT_CHECK_MS);

    return () => {
      window.clearInterval(interval);
    };
  }, [ref]);

  return (
    <div ref={ref}>
      {!isOverQuota && <MyMap
        googleMapURL={mapURL}
        loadingElement={<div>LOADING?!</div>}
        containerElement={<div style={{height: '400px', width: '400px'}}></div>}
        mapElement={<div style={{height: '100%'}}></div>}
      />}
    </div>
  );
};

const App: React.FC = () => {
  return (
    <div className="App">
      <header className="App-header">
        <MyMapWithFallback/>
      </header>
    </div>
  );
}

export default App;

This code snippet is dependent on us upgrading to the latest version of react-google-maps (#197).

toolness avatar Dec 04 '19 01:12 toolness

Um so in https://github.com/JustFixNYC/who-owns-what/pull/200#issuecomment-561656193 we realized that part of the reason we're going over our quota might be because we're instantiating a panorama widget twice for each page, which could be doubling our costs. I've fixed this (for most browsers) in #201 so we might not actually need this fallback fix, at least not until we get lots more traffic. I'll keep this issue updated as we learn more about what's going on.

toolness avatar Dec 04 '19 17:12 toolness

So, since we've now doubled our Maps Javascript API daily quota, we now don't come anywhere near our limit even on high traffic days, so I would consider this low priority for now.

sraby avatar May 27 '20 15:05 sraby