How would you design a resource allocation app?
In urban infrastructure, chambers serve as crucial connection points, facilitating various utilities. With the increasing demand for high-speed internet services, efficiently managing chambers becomes imperative. In this article, we'll delve into designing a web application using the Command Query Responsibility Segregation (CQRS) pattern to streamline chamber management.
And a bit more data in a table format:
The Problem
We've had an influx of new customers wanting our 10Gbps internet product! We need a way of identifying the
closest chamber to the potential customer, ensuring we have capacity to connect them, and give us a heads
up when we might need to increase capacity near a chamber.
Write a web application that allows a Vorboss sales team member to enter details about a new customer
ordering our 10Gbps internet product. The application should call a backend API that does the following:
Persist the details of the new customer in a data store
Provide the user with the ID of the closest chamber that has available capacity.
Alert the user if the nearest chamber doesn't have capacity, but still provide the next closest that does have capacity.
Alert the user if the provided chamber is now at capacity with the addition of the new customer.
Then High Level Architecture Design:
High Level API Design
Please have a look at our swagger here and These will be the lists
- Auth (Login,Register,Forgot,Reset,Resend)
- Package (ListPackages)
- Chamber (AvailableChambersPerPackage)
- Order (Create, GetAllByUser, Change, GetOrdersByUser)
- User (GetProfile, GetAllCustomersCreatedByMe, create)
Two roles: sales | customer
UI layout and the User Flow:
The Key points of implementations:
If you want to know the little issues and technical solutions:
- How to write down seeding the data to postgres using Prisma
await prisma.$executeRaw`
INSERT INTO "Chamber" (id, latitude, longitude, total_capacity, used_capacity, geom)
VALUES
(
'VORB-X8734',
51.52466903333144,
-0.08320212364196779,
100,
70,
ST_SetSRID(ST_MakePoint(-0.08320212364196779, 51.52466903333144), 4326)
),
(
'VORB-Z4784',
51.523641015718525,
-0.08601307868957521,
100,
10,
ST_SetSRID(ST_MakePoint(-0.08601307868957521, 51.523641015718525), 4326)
),
(
'VORB-N2837',
51.523434943212514,
-0.08114755153656007,
100,
40,
ST_SetSRID(ST_MakePoint(-0.08114755153656007, 51.523434943212514), 4326)
),
(
'VORB-V9345',
51.52211691871454,
-0.0851869583129883,
100,
30,
ST_SetSRID(ST_MakePoint(-0.0851869583129883, 51.52211691871454), 4326)
),
(
'VORB-Q9547',
51.523304662537235,
-0.08331477642059326,
100,
70,
ST_SetSRID(ST_MakePoint(-0.08331477642059326, 51.523304662537235), 4326)
);
`;
- Then make sure your Dockerfile for your backend works
FROM node:lts-iron as build
RUN apt-get update -y
RUN apt-get install -y openssl
RUN apt-get install -y apt-utils
ARG DATABASE_URL=""
ARG NODE_ENV=production
ARG PORT=8000
ARG JWT_SECRET=""
ENV NODE_ENV=$NODE_ENV
ENV PORT=$PORT
ENV DATABASE_URL=$DATABASE_URL
ENV JWT_SECRET=$JWT_SECRET
WORKDIR /app
COPY package*.json ./
RUN npm install
RUN npm install --only=dev
COPY . .
RUN npx prisma generate
EXPOSE 8000
CMD ["npm", "start"]
- And to query the closest chamber, you can use postgres native features:
const chambers = await pg.query( `
SELECT * FROM "Chamber"
${ids?.length ? `WHERE id IN (${ids.join(",")})` : ""}
ORDER BY ST_Distance(
geom,
ST_SetSRID(ST_MakePoint($1, $2), 4326)
)
LIMIT $3;
`,
[longitude, latitude, limit || 1]
);
- For DB you can just have a docker-compose.yml file
version: "3.8"
services:
db:
image: postgis/postgis
environment:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
restart: unless-stopped
- And for frontend, you can use RemixJS with Docker and Tailwind
FROM node:lts-iron as build
RUN apt-get update -y
RUN apt-get install -y openssl
RUN apt-get install -y apt-utils
ARG NODE_ENV=production
ARG PORT=3000
ARG REACT_APP_API_URL=http://localhost:8000
WORKDIR /app
ENV NODE_ENV=development
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
ENV NODE_ENV=production
ENV PORT=$PORT
ENV REACT_APP_API_URL=$REACT_APP_API_URL
EXPOSE 3000
CMD ["npm", "start"]
- And Finally a docker-composer.yml on the root folder can handle everything easily
# docker compose
version: '3.8'
services:
database:
container_name: app-database
image: postgis/postgis
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
restart: unless-stopped
volumes:
- database-data:/var/lib/postgresql/data
backend:
container_name: app-backend
build:
context: ./backend
dockerfile: Dockerfile
args:
NODE_ENV: development
DATABASE_URL: postgres://postgres:postgres@database:5432/mydb?schema=public&connect_timeout=300
JWT_SECRET: randomsecret
PORT: 8000
ports:
- "8000:8000"
depends_on:
- database
links:
- database
restart: unless-stopped
frontend:
container_name: app-frontend
build:
context: ./frontend
dockerfile: Dockerfile
args:
NODE_ENV: production
PORT: 3000
REACT_APP_API_URL: http://backend:8000
depends_on:
- backend
links:
- backend
ports:
- "3000:3000"
restart: unless-stopped
volumes:
database-data:
Implementing CQRS in our chamber management application allows for efficient handling of commands and queries, optimizing resource allocation and enhancing user experience. By leveraging robust backend APIs and modern frontend frameworks, we can provide Vorboss sales team members with a streamlined order process while ensuring optimal chamber utilization.