Skip to content

KingJoe-14/Pulse-Check-API

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pulse-Check-API — Dead Man's Switch Monitor

A production-grade backend service that monitors remote devices (solar farms, weather stations, etc.) and triggers escalating alerts when a device stops sending heartbeats.

Built with Python + Django + Redis.


Architecture Diagram

image

How It Works

  1. A device registers a monitor with a timeout (e.g. 60 seconds)
  2. Redis starts a countdown (TTL key)
  3. The device sends heartbeats to reset the timer
  4. If no heartbeat arrives before the timer hits zero, Redis fires an expiry event
  5. A background listener catches the event and fires escalating alerts
  6. A maintenance technician can pause monitoring to avoid false alarms

Setup Instructions

Requirements

  • Python 3.10+
  • Redis server
  • pip

Installation

1. Clone the repository

git clone https://github.com/KingJoe-14/Pulse-Check-API.git
cd Pulse-Check-API

2. Create and activate a virtual environment

python -m venv venv
source venv/bin/activate

3. Install dependencies

pip install -r requirements.txt

4. Set up your environment variables

Create a .env file in the root directory:

touch .env

Then add the following variables to the .env file: SECRET_KEY=your-secret-key-here DEBUG=True REDIS_HOST=127.0.0.1 REDIS_PORT=6379 REDIS_DB=0

Variable Description Default
SECRET_KEY Django secret key required
DEBUG Debug mode True
REDIS_HOST Redis server host 127.0.0.1
REDIS_PORT Redis server port 6379
REDIS_DB Redis database number 0

5. Start Redis

sudo service redis-server start

6. Enable Redis keyspace notifications

redis-cli config set notify-keyspace-events Ex

7. Run database-free check

python manage.py check

Running the Service

You need two terminals running simultaneously:

Terminal 1 — API server

python manage.py runserver

Terminal 2 — Keyspace listener

python manage.py start_listener

API Documentation

Base URL

http://127.0.0.1:8000


1. Register a Monitor

POST /monitors/

Registers a new device monitor and starts the countdown timer.

Request body:

{
    "id": "device-123",
    "timeout": 60,
    "alert_email": "admin@critmon.com"
}

Responses:

Status Description
201 Monitor created successfully
400 Missing or invalid fields
409 Monitor with this ID already exists

Example response (201):

{
    "message": "Monitor for device-123 created successfully",
    "monitor": {
        "id": "device-123",
        "timeout": 60,
        "alert_email": "admin@critmon.com",
        "status": "active",
        "created_at": "2026-06-06T19:37:30.260117+00:00"
    }
}

2. Send Heartbeat

POST /monitors/{id}/heartbeat/

Resets the countdown timer. Automatically unpauses a paused monitor.

No request body needed.

Responses:

Status Description
200 Timer reset successfully
404 Monitor not found
400 Monitor is down — use /recover to resume

Example response (200):

{
    "id": "device-123",
    "status": "active",
    "message": "Heartbeat received — timer reset",
    "updated_at": "2026-06-06T19:45:00.000000+00:00"
}

3. Pause a Monitor

POST /monitors/{id}/pause/

Freezes the timer completely. No alerts will fire while paused. Sending a heartbeat automatically resumes the monitor.

No request body needed.

Responses:

Status Description
200 Monitor paused successfully
400 Monitor is already paused or is down
404 Monitor not found

Example response (200):

{
    "id": "device-123",
    "status": "paused",
    "message": "Monitor paused — no alerts will fire",
    "updated_at": "2026-06-06T19:50:00.000000+00:00"
}

4. List All Monitors

GET /monitors/

Returns all registered monitors and their current status.

Example response (200):

[
    {
        "id": "device-123",
        "timeout": "60",
        "alert_email": "admin@critmon.com",
        "status": "active",
        "created_at": "2026-06-06T19:37:30.260117+00:00",
        "updated_at": "2026-06-06T19:45:00.000000+00:00"
    }
]

5. Get Single Monitor

GET /monitors/{id}/

Returns a single monitor by ID.

Responses:

Status Description
200 Monitor found
404 Monitor not found

Example response (200):

{
    "id": "device-123",
    "timeout": "60",
    "alert_email": "admin@critmon.com",
    "status": "active",
    "created_at": "2026-06-06T19:37:30.260117+00:00",
    "updated_at": "2026-06-06T19:45:00.000000+00:00"
}

6. Recover a Monitor

POST /monitors/{id}/recover/

Recovers a down monitor back to active state. Restarts the timer and clears all backoff alert keys. Only works when monitor status is down.

No request body needed.

Responses:

Status Description
200 Monitor recovered successfully
400 Monitor is not down
404 Monitor not found

Example response (200):

{
    "id": "device-123",
    "status": "active",
    "message": "Monitor device-123 recovered — timer restarted",
    "updated_at": "2026-06-09T14:19:27.970093+00:00"
}

7. Delete a Monitor

DELETE /monitors/{id}/

Permanently deletes a monitor and stops all associated timers and alerts. Works regardless of monitor status (active, paused, or down).

No request body needed.

Responses:

Status Description
200 Monitor deleted successfully
404 Monitor not found

Example response (200):

{
    "message": "Monitor device-123 deleted successfully"
}

Alert System

When a device misses its heartbeat the system fires three escalating alerts logged to the listener console:

Alert Severity When
Alert 1 WARNING Immediately when timer expires
Alert 2 URGENT 30 seconds after Alert 1
Alert 3 CRITICAL 90 seconds after Alert 2

Example alert output:

{"ALERT": "Device device-123 is down!", "severity": "WARNING", "email": "admin@critmon.com", "time": "2026-06-06T21:13:49.500142+00:00"}
{"ALERT": "Device device-123 is still down!", "severity": "URGENT", "email": "admin@critmon.com", "time": "2026-06-06T21:14:19.578988+00:00"}
{"ALERT": "Device device-123 is still down!", "severity": "CRITICAL", "email": "admin@critmon.com", "time": "2026-06-06T21:15:49.612045+00:00"}

Alerts stop escalating as soon as the device sends a heartbeat again.


Developer's Choice — Exponential Backoff Alerts

What it is

Instead of firing a single alert when a device goes down, the system escalates notifications with increasing urgency over time.

Why it was added

A single alert is easy to miss. In a critical infrastructure context (solar farms, unmanned weather stations), a missed alert could mean hours of downtime before anyone responds. Escalating alerts ensure that:

  • A first responder sees the WARNING immediately
  • If unacknowledged, the URGENT alert creates pressure to act
  • The CRITICAL alert signals a serious outage requiring immediate deployment

How it works

Redis backoff keys with expiring TTLs drive the escalation. Each alert schedules the next one by setting a new key with a delay. If the device recovers and sends a heartbeat, the backoff keys are cleared and escalation stops.


Project Structure

pulse-check-api/ ├── config/ # Django project settings │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── monitors/ # Core app │ ├── views.py # API endpoints │ ├── urls.py # URL routing │ ├── services/ │ │ ├── monitor_service.py # Register, heartbeat, pause, recover, delete logic │ │ └── alert_service.py # Alert firing and backoff │ └── management/commands/ │ └── start_listener.py # Redis keyspace event listener ├── redis_client/ │ └── client.py # Redis singleton ├── .env # Environment variables (not committed) ├── requirements.txt └── manage.py


Pre-Submission Checklist

  • ✅ Repository is public
  • ✅ No node_modules, .env, or sensitive files committed
  • ✅ Server starts with python manage.py runserver
  • ✅ Architecture diagram included
  • ✅ Original instructions replaced with this README
  • ✅ All endpoints documented with example requests
  • ✅ Multiple meaningful commits

About

This challenge is designed to test your ability to bridge Computer Science fundamentals with Modern Backend Engineering.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages