Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
LOGISTICS_SERVICE_PORT=8002
DJANGO_PORT=8000
KAFKA_BROKER_URL=kafka:9092
7 changes: 1 addition & 6 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Wait for Kafka to be ready
run: |
echo "Waiting for Kafka..."
sleep 20 # adjust based on startup time
pip install --no-cache-dir -r requirements.txt

- name: Run Django tests (including Kafka)
run: |
Expand Down
36 changes: 36 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Use official Python slim image
FROM python:3.12-slim

LABEL maintainer="kevin"

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV DJANGO_PORT=8000

# Set working directory
WORKDIR /app

# Install system dependencies
RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
curl \
&& apt-get clean && rm -rf /var/lib/apt/lists/*

# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy project files
COPY . .

# Copy entrypoint script
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Expose port (match DJANGO_PORT env)
EXPOSE ${DJANGO_PORT}

# Run entrypoint script
ENTRYPOINT ["/entrypoint.sh"]
17 changes: 16 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
version: '3.8'

services:
zookeeper:
image: confluentinc/cp-zookeeper:7.4.0
Expand All @@ -14,5 +15,19 @@ services:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
depends_on:
- zookeeper

logistics-service:
build: .
container_name: logistics-service
ports:
- "${LOGISTICS_SERVICE_PORT:-8002}:8000"
environment:
- DJANGO_PORT=8000
- KAFKA_BROKER_URL=kafka:9092
env_file: .env
depends_on:
- kafka
10 changes: 10 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh

echo "Running makemigrations..."
python manage.py makemigrations --noinput

echo "Running migrate..."
python manage.py migrate --noinput

echo "Starting Django server on port ${DJANGO_PORT}..."
python manage.py runserver 0.0.0.0:${DJANGO_PORT}
5 changes: 4 additions & 1 deletion logistics_core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,10 @@
ENABLE_FLEET_EXTENDED_MODELS = False

# kafka settings
KAFKA_BROKER_URL = "localhost:9092"
import os

KAFKA_BROKER_URL = os.getenv("KAFKA_BROKER_URL", "localhost:9092")


CORS_ALLOWED_ORIGINS = [
"http://localhost:4200",
Expand Down
25 changes: 19 additions & 6 deletions order_simulator.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
from confluent_kafka import Producer
import os
import django
import json
from confluent_kafka import Producer

# Setup Django (assuming this file is at the project root level)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'logistics_core.settings')
django.setup()

producer = Producer({'bootstrap.servers': 'localhost:9092'})
from django.conf import settings

# Fallback if env not set
bootstrap_servers = getattr(settings, 'KAFKA_BROKER_URL', 'localhost:9092')

producer = Producer({'bootstrap.servers': bootstrap_servers})

event = {
"order_id": "ORD9999",
"origin_warehouse_id": "WH001",
"destination_warehouse_id": "WH002"
"order_id": "ORD001",
"origin": {"lat": 6.9271, "lng": 79.8612},
"destination": {"lat": 7.2906, "lng": 80.6337},
"demand": 25
}

producer.produce('orders.created', json.dumps(event).encode('utf-8'))
producer.flush()
print("Published mock order event.")

print("✅ Published mock order event to 'orders.created'")
5 changes: 3 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
absl-py==2.2.2
asgiref==3.8.1
confluent-kafka==2.10.0
Django==5.2
django-cors-headers==4.7.0
django-filter==25.1
djangorestframework==3.16.0
drf-yasg==1.21.10
Expand All @@ -15,11 +17,10 @@ pluggy==1.5.0
protobuf==5.29.4
pytest==8.3.5
python-dateutil==2.9.0.post0
python-dotenv==1.1.0
pytz==2025.2
PyYAML==6.0.2
six==1.17.0
sqlparse==0.5.3
tzdata==2025.2
uritemplate==4.1.1
confluent-kafka~=2.10.0
django-cors-headers
3 changes: 2 additions & 1 deletion shipments/tests/test_integration_kafka.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
from shipments.models import Shipment
from confluent_kafka import Producer
from shipments.consumers.order_events import run_consumer_once
from django.conf import settings

logger = logging.getLogger(__name__)

class KafkaE2ETest(TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.producer = Producer({'bootstrap.servers': 'localhost:9092'})
cls.producer = Producer({'bootstrap.servers': settings.KAFKA_BROKER_URL})

def test_order_event_creates_shipment(self):
order_id = "KAFKA_E2E_01"
Expand Down