Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Dockerfile for the actual server

FROM yobasystems/alpine-docker:dind

WORKDIR /app

RUN apk update && apk add --no-cache build-base
RUN apk add --update nodejs npm

COPY ./server /app
RUN npm install

EXPOSE 3000

CMD ["npm", "start"]
15 changes: 15 additions & 0 deletions Dockerfile.client
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Dockerfile for the client

FROM alpine:latest

WORKDIR /app

RUN apk update && apk add --no-cache build-base
RUN apk add --update nodejs npm

COPY ./client /app
RUN npm install

EXPOSE 5173

CMD ["npm", "run", "dev"]
63 changes: 58 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,60 @@
## Peetcode
It's an online algorithmic problem solving platform. Built as a joke during the full stack assignments by Harkirat Singh.
No intention of building this into a business.
# PeetCode Evaluator

This is a simple backend project which evaluates PeetCode submissions

### Disclaimer

- This is a very simple and crude implementation
- Compiles and rules only C++ programs for now
- Assumes that the solutions are simple integers
- Right now the problem numbers and their corresponding solutions are hardcoded

## Features

A simple backend system which gets new submissions, pushes it to a RabbitMQ queue.
A receiver reads it off the queue, starts (or creates) a container, and executes the code inside the sandbox environment.
The result of the evaluation is the passed back to the caller, which updates the frontend.

The whole backend has been containerised for better scaling, and uses K8s to manage the deployments. A docker in docker (DinD) is used, so that the code can be evaluated on a safe and secure container, which is deleted after usage.

## DevOps part
- Created a Dockerfile for the server which installs all the necessary components, and volumes as well for Docker in Docker to work
- Created a Dockerfile for the sandbox environment
- Created a Kubernetes file for the server, sandbox and RabbitMQ (which is used by the server)
- Created ClusterIPs for all the above three, so that the server can access those as and when required
- The architecture is scalable, since any number of problems can be solved, as the deployments will increases, and also beecause the sandbox containers are lightweight, and are created on demand.

## Tech stack used

- RabbitMQ
- NodeJS
- Docker
- Kubernetes
- Docker in Docker (DinD)

## Installation

- To run the program, it is expected that RabbitMQ is set up and running on port `5672`.
- Docker must be installed and running on the system
- A Kubernetes cluster must also be running on your machine (Minikube or Docker Desktop's Kubernetes)
- We can just use the startup script `startup.sh` provided to bring up all the necessary components
- Ensure that the file is executable, and execute it by running `./startup.sh`
- Since we are using NodePorts, we can access the client and the server from our local machine
- Visit `localhost:30002` or `<minikube-ip>:30002` depending on how you are running your Kubernetes cluster.

## Explanation
- All the required services (the backend server, RabbitMQ, and the Sandbox environments) are present as deployments, and have ClusterIP services to access them within cluster
- The client service has a pod and a NodePort to access it from the outside
- The service service too has a NodePort so that client can send requests to it from outside the cluster (eg. the browser)
- The sandbox environment and RabbitMQ pods are inaccessible from the outside
- The client (`localhost:30002`) sends requests to the server throught the NodePort on `localhost:30001`.

## Architecture of the backend
![archi](https://github.com/Adithya2907/peetcode/assets/56926966/0d875d15-2788-403a-9c29-246d2d31aade)


## Demo
https://github.com/Adithya2907/peetcode/assets/56926966/155b18a4-d272-4ea1-b77f-f55ae4222b7d


If you would like to win an Airpods though, feel free to go through the third part and build the bounty described in the video

Demo: https://peetcode.com
152 changes: 152 additions & 0 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.10.0"
Expand Down
11 changes: 5 additions & 6 deletions client/src/Components/AllProblems/AllProblems.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, {useEffect, useState} from 'react'
import React, { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import axios from 'axios';

import "./AllProblems.css"
import { backendUrl } from "../../constants.js";
Expand All @@ -8,11 +9,9 @@ const AllProblemsPage = () => {
const [problems, setProblems] = useState([]);

const init = async () => {
const response = await fetch(`${backendUrl}/problems`, {
method: "GET",
});
const response = await axios.get(`${backendUrl}/problems`);

const json = await response.json();
const json = response.data; // Access the response data
setProblems(json.problems);
}

Expand All @@ -31,7 +30,7 @@ const AllProblemsPage = () => {
<th>Acceptance</th>
</tr>

{problems.map((prob,index) => (
{problems.map((prob, index) => (
<tr>
<Link to={`/problems/:${prob.problemId}`}>
<td>{prob.title}</td>
Expand Down
Loading