Live Results

Live Results

The live results page is displayed for the week when the City Nature Challenge occurs. During this time, participating cities/organizations submit their results to either iNaturalist or other aggregators such as Observations.org.

The live results page must call these APIs periodically (i.e. every minute) to ensure that the CNC site is reporting up to date information. This documentation outlines the backend that collates these responses.

Vercel Serverless functions

The switch over to Next.js allowed for the City Nature Challenge site to leverage API routes provided by Vercel. Currently, the route for the serverless function that calls the aggregator APIs is /api/results. The corresponding Node file is located at: /pages/api/results.js. For more information on Next.js' API routes, please consult Serverless Functions Overview (opens in a new tab).

Using Vercel's Cron Jobs functionality, /api/results is called every minute. The results.js Node script calls the iNaturalist endpoint and each of the additional aggregator endpoints. The results for these cities/organizations are cleaned to ensure that city names display uniformly in the results table (more on the frontend below).

Once the results have been cleaned and appended to an array of results objects, they are saved to the results.json.

Digital Ocean Spaces

New results are sent to a json saved in a Digital Ocean Spaces space (or bucket to use Amazon S3 terminology). This solution was chosen to account for Serverless functions statelessness (i.e. they offer no persistent storage/state) and the desire to not require a full-fledged database for the week long live results.

Load testing

To ensure that DO Spaces was production ready (considering the high volume of traffic during the challenge), stress testing was conducted using locust.io, a Python library for load testing. DO Spaces limits (opens in a new tab), at the time of this document's writing, has the following limitations:

  • 800 requests/second/bucket
  • 1,500 requests per IP address per second to all buckets on all accounts

Requests include GET requests, which are particularly pertinent for the City Nature Challenge as clients request the results.json every 30 seconds.

Using locust.io two scenarios were tested:

  1. More than 800 requests per second (RPS) for the results.json not on the CDN
  2. More than 800 requests per second (RPS) for the results.json on the CDN

1. Without CDN

Load testing of DO Spaces without CDN

When the results.jsonwas requested at a rate over 800 requests per second, DO Spaces began failing to serve the file.

2. With CDN

Load testing of DO Spaces without CDN

When the locust.io test was ran with the same parameters as the first test, DO Spaces did not fail to serve results.json.

Given these results, the CDN endpoint was used in production and its TTL parameter set to 30 seconds to ensure fresh data was served to clients requesting updates.

Client-side

Give the dynamic nature of live results, the Live Results Next.js component fetches the results.json from Digital Ocean Spaces on page load and every 30 seconds.

To add the Live Results component to a page, simply add the Strapi component titled "Live Results".

The Live Results component requires that a file named results.json exists in the cnc-assets DO Spaces space.

The Next.js client side component will fetch the results.json and then display a Stat Row and Table component (see below).

Load testing of DO Spaces without CDN