Skip to content

Harshini2410/fission-assignment

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mini Event Platform - MERN Stack

A full-stack web application where users can create events and RSVP to them, with strict capacity enforcement and race condition handling to prevent overbooking.

Table of Contents

Project Overview

This is a production-ready MERN (MongoDB, Express.js, React.js, Node.js) application that allows users to:

  • Create accounts and authenticate using JWT
  • Create events with details like title, description, date/time, location, capacity, and images
  • Browse upcoming events with search and date filtering
  • RSVP to events with strict capacity enforcement
  • View personal dashboard showing created events and events they're attending

The application ensures data integrity and prevents overbooking even under concurrent access scenarios using MongoDB atomic operations and transactions.

Tech Stack

Backend

  • Node.js - Runtime environment
  • Express.js - Web framework
  • MongoDB - Database (MongoDB Atlas)
  • Mongoose - MongoDB ODM
  • JWT - Authentication
  • Multer - File upload handling
  • Cloudinary - Image storage (optional, can use local storage)

Frontend

  • React.js - UI library
  • React Router - Routing
  • Axios - HTTP client
  • Tailwind CSS - Styling
  • Vite - Build tool

Deployment

  • Backend: Render or Railway
  • Frontend: Vercel or Netlify
  • Database: MongoDB Atlas

Features

Authentication

  • User signup with password hashing (bcrypt)
  • User login with JWT tokens
  • Protected routes
  • Token-based authentication

Event Management

  • Create events with all required fields
  • View all upcoming events
  • View individual event details
  • Edit/Delete events (creator only)
  • Image upload support
  • Search events by title
  • Filter events by date

RSVP System

  • RSVP to events with capacity enforcement
  • Leave events (cancel RSVP)
  • View RSVP status
  • Real-time remaining seats display
  • Race condition handling to prevent overbooking

User Dashboard

  • View all events created by the user
  • View all events the user is attending

How to Run Locally

Prerequisites

  • Node.js (v18 or higher)
  • MongoDB Atlas account (or local MongoDB)
  • Cloudinary account (optional, for image storage)

Backend Setup

  1. Navigate to the server directory:
cd server
  1. Install dependencies:
npm install
  1. Create a .env file in the server directory:
PORT=5000
MONGODB_URI=your_mongodb_atlas_connection_string
JWT_SECRET=your_jwt_secret_key_here
CLOUDINARY_CLOUD_NAME=your_cloudinary_cloud_name
CLOUDINARY_API_KEY=your_cloudinary_api_key
CLOUDINARY_API_SECRET=your_cloudinary_api_secret
  1. Start the server:
npm run dev

The backend will run on http://localhost:5000

Frontend Setup

  1. Navigate to the client directory:
cd client
  1. Install dependencies:
npm install
  1. Create a .env file in the client directory:
VITE_API_URL=http://localhost:5000/api
  1. Start the development server:
npm run dev

The frontend will run on http://localhost:5173 (or another port if 5173 is taken)

Note on Cloudinary

If you don't want to use Cloudinary:

  1. You can skip the Cloudinary environment variables in the backend .env
  2. The application will still work, but images won't be uploaded (imageUrl will be empty)

Deployed URLs

  • Frontend: [To be deployed on Vercel/Netlify]
  • Backend: [To be deployed on Render/Railway]
  • MongoDB: MongoDB Atlas

Deployment Instructions

Backend Deployment (Render/Railway)

  1. Push your code to GitHub
  2. Create a new Web Service on Render (or Railway)
  3. Connect your GitHub repository
  4. Set build and start commands:
    • Build Command: cd server && npm install
    • Start Command: cd server && npm start
  5. Add environment variables:
    • PORT (usually auto-set by platform)
    • MONGODB_URI (your MongoDB Atlas connection string)
    • JWT_SECRET (a secure random string)
    • CLOUDINARY_CLOUD_NAME (optional)
    • CLOUDINARY_API_KEY (optional)
    • CLOUDINARY_API_SECRET (optional)
  6. Deploy!

Frontend Deployment (Vercel/Netlify)

  1. Push your code to GitHub
  2. Create a new project on Vercel (or Netlify)
  3. Connect your GitHub repository
  4. Set build settings:
    • Root Directory: client
    • Build Command: npm run build
    • Output Directory: dist
  5. Add environment variables:
    • VITE_API_URL (your deployed backend URL, e.g., https://your-backend.onrender.com/api)
  6. Deploy!

Important: Make sure to update the VITE_API_URL in your frontend environment variables to point to your deployed backend URL.

RSVP Capacity & Concurrency Explanation

The Problem

When multiple users try to RSVP to an event simultaneously, there's a risk of overbooking. This is a classic race condition problem:

Example Scenario:

  • Event capacity: 10
  • Current attendees: 9
  • Two users (User A and User B) try to RSVP at exactly the same time

Without proper handling:

  1. Both requests check the current attendee count (9)
  2. Both see that there's space available (10 - 9 = 1 seat left)
  3. Both requests proceed to add the user
  4. Result: 11 attendees (OVERBOOKING!)

The Race Condition

A race condition occurs when:

  • Multiple operations execute concurrently
  • They access and modify the same shared resource (the event's attendees array)
  • The final result depends on the timing of these operations
  • Without synchronization, incorrect results can occur (overbooking)

The Solution: MongoDB Atomic Operations with Transactions

This application uses MongoDB atomic operations combined with transactions to ensure data integrity:

Implementation Strategy

The RSVP endpoint uses findOneAndUpdate with atomic operators and a transaction session:

const updatedEvent = await Event.findOneAndUpdate(
  {
    _id: eventId,
    $expr: { $lt: [{ $size: '$attendees' }, '$capacity'] }, // Atomic capacity check
    attendees: { $ne: userId }, // Atomic duplicate check
  },
  {
    $addToSet: { attendees: userId }, // Atomic add operation
  },
  {
    new: true,
    session: session,
  }
);

How It Prevents Overbooking

  1. Atomic Condition Check:

    • $expr: { $lt: [{ $size: '$attendees' }, '$capacity'] } ensures that the update only happens if attendees.length < capacity
    • This check happens atomically at the database level, not in application code
  2. Atomic Duplicate Prevention:

    • attendees: { $ne: userId } ensures the user is not already in the attendees array
    • Prevents duplicate RSVPs
  3. Atomic Add Operation:

    • $addToSet atomically adds the user to the attendees array only if they're not already present
    • All operations (check + update) happen as a single atomic operation
  4. Transaction Session:

    • Wraps the operation in a MongoDB transaction
    • Ensures all-or-nothing execution
    • If the update fails (capacity exceeded or duplicate), the transaction is aborted

Why This Works

  • Single Atomic Operation: MongoDB evaluates the query condition and performs the update as a single atomic operation at the database level
  • No Read-Modify-Write Gap: Traditional approaches (read count, check, then write) have a gap between read and write where race conditions can occur. Atomic operations eliminate this gap
  • Database-Level Enforcement: The capacity check happens in the database query itself, not in application logic, making it immune to race conditions
  • Transactional Safety: The transaction ensures that if any part fails, the entire operation is rolled back

Result

Even if 100 users try to RSVP simultaneously when only 1 seat is left:

  • Only one request will succeed (the one that reaches the database first)
  • All other requests will receive a 409 Conflict response indicating the event is full
  • No overbooking can occur

Testing Race Conditions

To test the race condition handling:

  1. Create an event with capacity: 1
  2. Use tools like curl or Postman to send multiple RSVP requests simultaneously
  3. Verify that only 1 RSVP succeeds, and all others return appropriate error messages

API Endpoints

Authentication

  • POST /api/auth/signup - Register a new user
  • POST /api/auth/login - Login user
  • GET /api/auth/me - Get current user (protected)

Events

  • GET /api/events - Get all upcoming events (supports ?search=...&date=...)
  • GET /api/events/:id - Get single event
  • POST /api/events - Create event (protected)
  • PUT /api/events/:id - Update event (protected, creator only)
  • DELETE /api/events/:id - Delete event (protected, creator only)
  • GET /api/events/user/dashboard - Get user's events (protected)

RSVP

  • POST /api/events/:id/rsvp - RSVP to event (protected)
  • DELETE /api/events/:id/rsvp - Leave event (protected)

Project Structure

.
├── server/                 # Backend
│   ├── config/            # Configuration files
│   │   ├── database.js    # MongoDB connection
│   │   └── cloudinary.js  # Cloudinary setup
│   ├── controllers/       # Route handlers
│   │   ├── authController.js
│   │   ├── eventController.js
│   │   └── rsvpController.js
│   ├── middleware/        # Middleware functions
│   │   └── auth.js        # JWT authentication
│   ├── models/            # Mongoose models
│   │   ├── User.js
│   │   └── Event.js
│   ├── routes/            # Express routes
│   │   ├── authRoutes.js
│   │   └── eventRoutes.js
│   ├── utils/             # Utility functions
│   │   └── generateToken.js
│   ├── app.js             # Express app setup
│   └── server.js          # Server entry point
│
└── client/                # Frontend
    ├── src/
    │   ├── components/    # Reusable components
    │   │   ├── Navbar.jsx
    │   │   └── PrivateRoute.jsx
    │   ├── context/       # React Context
    │   │   └── AuthContext.jsx
    │   ├── pages/         # Page components
    │   │   ├── Login.jsx
    │   │   ├── Signup.jsx
    │   │   ├── Events.jsx
    │   │   ├── EventDetail.jsx
    │   │   ├── CreateEvent.jsx
    │   │   └── Dashboard.jsx
    │   ├── utils/         # Utilities
    │   │   └── api.js     # Axios configuration
    │   ├── App.jsx        # Main app component
    │   └── main.jsx       # Entry point
    └── ...

Security Features

  • Password hashing with bcrypt
  • JWT token-based authentication
  • Protected routes (frontend and backend)
  • Input validation
  • Environment variables for sensitive data
  • CORS configuration
  • Error handling middleware

UI Features

  • Fully responsive design (mobile, tablet, desktop)
  • Clean and professional layout
  • Real-time capacity display
  • Visual progress bars for event capacity
  • Search and filter functionality
  • User-friendly error messages

Notes

  • The application uses MongoDB Atlas for database hosting
  • Image uploads are handled via Cloudinary (optional)
  • All API endpoints return JSON responses
  • Frontend communicates with backend via Axios with interceptors for authentication

Future Enhancements

  • Email notifications for RSVPs
  • Event categories and tags
  • User profiles
  • Event comments and ratings
  • Calendar integration
  • Social sharing features

Built with the MERN stack

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published