cloud-run-direct-vpc/index.js (88 lines of code) (raw):
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
const express = require('express');
const app = express();
app.use(express.json());
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`API listening on port ${port}`);
});
const redisClient = require('redis').createClient(
process.env.REDIS_PORT,
process.env.REDIS_HOST
);
// Read one artist, by id.
app.get('/artist/:id', async (req, res) => {
try {
const id = req.params.id;
const artist = await getArtistFromCache(id);
if (artist) {
res.json(artist);
return;
}
else {
res.status(404).json({error: `Artist ${id} not found`});
}
}
catch(ex) {
res.status(500).json({error: ex.toString()});
}
})
async function getArtistFromDatabase(id) {
const sleep = require('util').promisify(setTimeout);
await sleep(3000); // Simulate a slow database query.
return artistsInDatabase.find(artist => artist.id==id);
}
async function getArtistFromCache(id) {
const { promisify } = require("util");
const redisGet = promisify(redisClient.get).bind(redisClient);
const redisExists = promisify(redisClient.exists).bind(redisClient);
if (! await redisExists(id)) {
const artist = await getArtistFromDatabase(id);
if (artist) {
redisClient.set(id, JSON.stringify(artist));
}
}
return JSON.parse(await redisGet(id));
}
// Return all artists currently in the database.
app.get('/database', async (req, res) => {
res.json(artistsInDatabase);
})
// Return all artists currently in the cache.
app.get('/cache', async (req, res) => {
const { promisify } = require("util");
const redisKeys = promisify(redisClient.keys).bind(redisClient);
const redisGet = promisify(redisClient.get).bind(redisClient);
const ids = await redisKeys('*');
const artistsInCache = [];
for (id of ids) {
const artist = JSON.parse(await redisGet(id));;
artistsInCache.push(artist);
}
res.json(artistsInCache);
})
// Delete all artists from the Redis cache.
app.post('/flush-cache', async (req, res) => {
redisClient.flushdb((err, succeeded) => {
res.json({status: "Cache flushed"});
});
})
// This array is the fake database. Using a fake database to make it easier to
// experiment with caching strategies without having to set up and maintain a
// real database.
const artistsInDatabase = [
{
id: '1',
name: 'Frida Kahlo',
born: 'July 6, 1907, Coyoacán, Mexico City, Mexico',
died: 'July 13, 1954, Coyoacán, Mexico City, Mexico',
notableWorks: [
'The Two Fridas (1939)',
'Self-Portrait with Thorn Necklace and Hummingbird (1940)',
'The Broken Column (1944)'
],
},
{
id: '2',
name: 'Diego Rivera',
born: 'December 8, 1886, Guanajuato City, Mexico',
died: 'November 24, 1957, Mexico City, Mexico',
notableWorks: [
'Detroit Industry Murals (1933)',
'Man, Controller of the Universe (1934)',
'The History of Mexico (1935)'
],
},
]