Skip to content

Instantly share code, notes, and snippets.

@mayankchoubey
Created October 20, 2023 05:46
Show Gist options
  • Save mayankchoubey/f17dfeb4ca1fd3ff34c86387324db6b7 to your computer and use it in GitHub Desktop.
Save mayankchoubey/f17dfeb4ca1fd3ff34c86387324db6b7 to your computer and use it in GitHub Desktop.
Node.js - Express Clustered URL shortener service in PostgreSQL
import { DataTypes, Sequelize } from "sequelize";
const dbUser = process.env.dbUser;
const dbUserPass = process.env.dbUserPass;
const dbName = process.env.dbName;
const sequelize = new Sequelize(
`postgres://${dbUser}:${dbUserPass}@localhost:5432/${dbName}`,
{
logging: false,
pool: {
max: 10,
min: 10,
},
},
);
await sequelize.authenticate();
const ShortenedUrl = sequelize.define("shortenedurl", {
id: {
type: DataTypes.STRING,
primaryKey: true,
},
srcurl: DataTypes.STRING,
created: DataTypes.DATE,
lastaccessed: DataTypes.DATE,
}, {
timestamps: false,
});
export async function save(id, srcUrl) {
await ShortenedUrl.create({
id,
srcurl: srcUrl,
created: new Date(),
lastaccessed: new Date(),
});
return true;
}
import { shorten } from "./service.mjs";
export async function handleRequest(req, res) {
if (!(req.body && req.body.srcUrl)) {
return res.status(400).send({ errMsg: "Parameter 'srcUrl' is missing" });
}
const srcUrl = req.body.srcUrl;
if (srcUrl.length > 250) {
return res.status(400).send({
errMsg: "Parameter 'srcUrl' must not be more than 250 characters",
});
}
if (!(srcUrl.startsWith("http://") || srcUrl.startsWith("https://"))) {
return res.status(400).send({
errMsg: "Parameter 'srcUrl' must start with http:// or https://",
});
}
const shortenedUrl = await shorten(srcUrl);
if (!shortenedUrl) {
return res.status(500).send({ errMsg: "Failed to shorten" });
}
res.json({ srcUrl, shortenedUrl });
}
import cluster from "node:cluster";
import express from "express";
import { handleRequest } from "./expressController.mjs";
const numClusterWorkers = parseInt(process.argv[2] || 1);
if (cluster.isPrimary) {
for (let i = 0; i < numClusterWorkers; i++) {
cluster.fork();
}
cluster.on(
"exit",
(worker, code, signal) => console.log(`worker ${worker.process.pid} died`),
);
} else {
const app = express();
app.use(express.json());
app.post("/shorten", handleRequest);
app.listen(3000);
}
import { nanoid } from "nanoid";
import { save } from "./db.mjs";
const baseUrl = "http://test.short/";
export async function shorten(srcUrl) {
if (!srcUrl) {
return;
}
const urlId = nanoid(10);
const shortenedUrl = `${baseUrl}${urlId}`;
const dbStatus = await save(urlId, srcUrl);
return dbStatus ? shortenedUrl : undefined;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment