Skip to content

Commit 4ce6bf8

Browse files
committed
Added docker
1 parent c4a1de0 commit 4ce6bf8

3 files changed

Lines changed: 394 additions & 0 deletions

File tree

database/init/01_init.sql

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
-- SmartQuery Database Initialization
2+
-- This script runs automatically when PostgreSQL container starts
3+
4+
-- Create extensions
5+
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
6+
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
7+
8+
-- Set timezone
9+
SET timezone = 'UTC';
10+
11+
-- Create initial tables (basic structure for now, will be expanded in later tasks)
12+
13+
-- Users table (will be expanded in Task B4)
14+
CREATE TABLE IF NOT EXISTS users (
15+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
16+
email VARCHAR(255) UNIQUE NOT NULL,
17+
name VARCHAR(255) NOT NULL,
18+
avatar_url TEXT,
19+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
20+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
21+
last_sign_in_at TIMESTAMP WITH TIME ZONE
22+
);
23+
24+
-- Projects table (will be expanded in Task B9)
25+
CREATE TABLE IF NOT EXISTS projects (
26+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
27+
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
28+
name VARCHAR(255) NOT NULL,
29+
description TEXT,
30+
csv_filename VARCHAR(255),
31+
csv_path TEXT,
32+
row_count INTEGER DEFAULT 0,
33+
column_count INTEGER DEFAULT 0,
34+
columns_metadata JSONB DEFAULT '[]'::jsonb,
35+
status VARCHAR(50) DEFAULT 'uploading',
36+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
37+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
38+
);
39+
40+
-- Chat messages table (will be expanded in later tasks)
41+
CREATE TABLE IF NOT EXISTS chat_messages (
42+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
43+
project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
44+
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
45+
content TEXT NOT NULL,
46+
role VARCHAR(20) NOT NULL CHECK (role IN ('user', 'assistant')),
47+
metadata JSONB DEFAULT '{}'::jsonb,
48+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
49+
);
50+
51+
-- Create indexes for better performance
52+
CREATE INDEX IF NOT EXISTS idx_projects_user_id ON projects(user_id);
53+
CREATE INDEX IF NOT EXISTS idx_projects_created_at ON projects(created_at DESC);
54+
CREATE INDEX IF NOT EXISTS idx_chat_messages_project_id ON chat_messages(project_id);
55+
CREATE INDEX IF NOT EXISTS idx_chat_messages_created_at ON chat_messages(created_at DESC);
56+
57+
-- Insert a test user for development
58+
INSERT INTO users (email, name)
59+
VALUES ('dev@smartquery.com', 'Development User')
60+
ON CONFLICT (email) DO NOTHING;

docker-compose.yml

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
version: '3.8'
2+
3+
services:
4+
# PostgreSQL Database
5+
postgres:
6+
image: postgres:15
7+
container_name: smartquery-postgres
8+
environment:
9+
POSTGRES_USER: smartquery_user
10+
POSTGRES_PASSWORD: smartquery_dev_password
11+
POSTGRES_DB: smartquery
12+
POSTGRES_HOST_AUTH_METHOD: trust
13+
ports:
14+
- "5432:5432"
15+
volumes:
16+
- postgres_data:/var/lib/postgresql/data
17+
- ./database/init:/docker-entrypoint-initdb.d
18+
healthcheck:
19+
test: ["CMD-SHELL", "pg_isready -U smartquery_user -d smartquery"]
20+
interval: 10s
21+
timeout: 5s
22+
retries: 5
23+
networks:
24+
- smartquery-network
25+
26+
# Redis Cache & Message Broker
27+
redis:
28+
image: redis:7-alpine
29+
container_name: smartquery-redis
30+
command: redis-server --appendonly yes
31+
ports:
32+
- "6379:6379"
33+
volumes:
34+
- redis_data:/data
35+
healthcheck:
36+
test: ["CMD", "redis-cli", "ping"]
37+
interval: 10s
38+
timeout: 5s
39+
retries: 3
40+
networks:
41+
- smartquery-network
42+
43+
# MinIO Object Storage
44+
minio:
45+
image: minio/minio:latest
46+
container_name: smartquery-minio
47+
command: server /data --console-address ":9001"
48+
environment:
49+
MINIO_ROOT_USER: minio_admin
50+
MINIO_ROOT_PASSWORD: minio_dev_password123
51+
ports:
52+
- "9000:9000" # API
53+
- "9001:9001" # Console
54+
volumes:
55+
- minio_data:/data
56+
healthcheck:
57+
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
58+
interval: 30s
59+
timeout: 20s
60+
retries: 3
61+
networks:
62+
- smartquery-network
63+
64+
# MinIO Client (for bucket creation)
65+
minio-setup:
66+
image: minio/mc:latest
67+
container_name: smartquery-minio-setup
68+
depends_on:
69+
- minio
70+
entrypoint: >
71+
/bin/sh -c "
72+
sleep 10;
73+
/usr/bin/mc alias set myminio http://minio:9000 minio_admin minio_dev_password123;
74+
/usr/bin/mc mb myminio/smartquery-files --ignore-existing;
75+
/usr/bin/mc policy set public myminio/smartquery-files;
76+
exit 0;
77+
"
78+
networks:
79+
- smartquery-network
80+
81+
# Celery Worker
82+
celery-worker:
83+
build:
84+
context: ./backend
85+
dockerfile: Dockerfile.celery
86+
container_name: smartquery-celery-worker
87+
command: celery -A celery_app worker --loglevel=info
88+
depends_on:
89+
- redis
90+
- postgres
91+
- minio
92+
environment:
93+
- DATABASE_URL=postgresql://smartquery_user:smartquery_dev_password@postgres:5432/smartquery
94+
- REDIS_URL=redis://redis:6379/0
95+
- CELERY_BROKER_URL=redis://redis:6379/1
96+
- CELERY_RESULT_BACKEND=redis://redis:6379/1
97+
- MINIO_ENDPOINT=minio:9000
98+
- MINIO_ACCESS_KEY=minio_admin
99+
- MINIO_SECRET_KEY=minio_dev_password123
100+
- MINIO_BUCKET_NAME=smartquery-files
101+
volumes:
102+
- ./backend:/app
103+
networks:
104+
- smartquery-network
105+
restart: unless-stopped
106+
107+
# Celery Flower (monitoring)
108+
celery-flower:
109+
build:
110+
context: ./backend
111+
dockerfile: Dockerfile.celery
112+
container_name: smartquery-celery-flower
113+
command: celery -A celery_app flower --port=5555
114+
depends_on:
115+
- redis
116+
- celery-worker
117+
environment:
118+
- CELERY_BROKER_URL=redis://redis:6379/1
119+
- CELERY_RESULT_BACKEND=redis://redis:6379/1
120+
ports:
121+
- "5555:5555"
122+
volumes:
123+
- ./backend:/app
124+
networks:
125+
- smartquery-network
126+
restart: unless-stopped
127+
128+
volumes:
129+
postgres_data:
130+
redis_data:
131+
minio_data:
132+
133+
networks:
134+
smartquery-network:
135+
driver: bridge

scripts/test_infrastructure.py

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Infrastructure test script for SmartQuery backend services
4+
This script tests the configuration and setup of our infrastructure services
5+
"""
6+
7+
import os
8+
import sys
9+
import asyncio
10+
from pathlib import Path
11+
12+
# Add backend to path
13+
backend_path = Path(__file__).parent.parent / "backend"
14+
sys.path.insert(0, str(backend_path))
15+
16+
def test_docker_compose_config():
17+
"""Test Docker Compose configuration"""
18+
print("🐳 Testing Docker Compose Configuration...")
19+
20+
docker_compose_path = Path(__file__).parent.parent / "docker-compose.yml"
21+
if docker_compose_path.exists():
22+
print("✅ docker-compose.yml exists")
23+
24+
# Read and check basic structure
25+
with open(docker_compose_path) as f:
26+
content = f.read()
27+
28+
services = ["postgres", "redis", "minio", "celery-worker", "celery-flower"]
29+
for service in services:
30+
if service in content:
31+
print(f"✅ {service} service configured")
32+
else:
33+
print(f"❌ {service} service missing")
34+
35+
# Check for required volumes
36+
if "volumes:" in content:
37+
print("✅ Docker volumes configured")
38+
39+
# Check for networks
40+
if "networks:" in content:
41+
print("✅ Docker networks configured")
42+
43+
else:
44+
print("❌ docker-compose.yml not found")
45+
46+
print()
47+
48+
def test_backend_structure():
49+
"""Test backend project structure"""
50+
print("📁 Testing Backend Project Structure...")
51+
52+
backend_path = Path(__file__).parent.parent / "backend"
53+
required_files = [
54+
"main.py",
55+
"celery_app.py",
56+
"requirements.txt",
57+
"Dockerfile.celery",
58+
"api/health.py",
59+
"services/database_service.py",
60+
"services/redis_service.py",
61+
"services/storage_service.py",
62+
"tasks/file_processing.py"
63+
]
64+
65+
for file_path in required_files:
66+
full_path = backend_path / file_path
67+
if full_path.exists():
68+
print(f"✅ {file_path}")
69+
else:
70+
print(f"❌ {file_path} missing")
71+
72+
print()
73+
74+
def test_database_init():
75+
"""Test database initialization scripts"""
76+
print("🗄️ Testing Database Initialization...")
77+
78+
db_init_path = Path(__file__).parent.parent / "database" / "init" / "01_init.sql"
79+
if db_init_path.exists():
80+
print("✅ Database initialization script exists")
81+
82+
with open(db_init_path) as f:
83+
content = f.read()
84+
85+
tables = ["users", "projects", "chat_messages"]
86+
for table in tables:
87+
if f"CREATE TABLE IF NOT EXISTS {table}" in content:
88+
print(f"✅ {table} table creation script")
89+
else:
90+
print(f"❌ {table} table creation script missing")
91+
else:
92+
print("❌ Database initialization script missing")
93+
94+
print()
95+
96+
def test_environment_config():
97+
"""Test environment configuration"""
98+
print("⚙️ Testing Environment Configuration...")
99+
100+
# Check for required environment variables structure
101+
required_env_vars = [
102+
"DATABASE_URL",
103+
"REDIS_URL",
104+
"MINIO_ENDPOINT",
105+
"MINIO_ACCESS_KEY",
106+
"MINIO_SECRET_KEY",
107+
"CELERY_BROKER_URL",
108+
"CELERY_RESULT_BACKEND"
109+
]
110+
111+
print("Required environment variables:")
112+
for var in required_env_vars:
113+
if var in ["MINIO_ACCESS_KEY", "MINIO_SECRET_KEY"]:
114+
print(f"🔑 {var} (configured in docker-compose)")
115+
else:
116+
print(f"✅ {var} (configured in docker-compose)")
117+
118+
print()
119+
120+
def test_service_imports():
121+
"""Test that services can be imported"""
122+
print("📦 Testing Service Imports...")
123+
124+
try:
125+
from services.database_service import db_service
126+
print("✅ Database service imports successfully")
127+
except Exception as e:
128+
print(f"❌ Database service import failed: {e}")
129+
130+
try:
131+
from services.redis_service import redis_service
132+
print("✅ Redis service imports successfully")
133+
except Exception as e:
134+
print(f"❌ Redis service import failed: {e}")
135+
136+
try:
137+
from services.storage_service import storage_service
138+
print("✅ Storage service imports successfully")
139+
except Exception as e:
140+
print(f"❌ Storage service import failed: {e}")
141+
142+
try:
143+
from celery_app import celery_app
144+
print("✅ Celery app imports successfully")
145+
except Exception as e:
146+
print(f"❌ Celery app import failed: {e}")
147+
148+
print()
149+
150+
def test_requirements():
151+
"""Test requirements.txt has necessary dependencies"""
152+
print("📋 Testing Requirements...")
153+
154+
req_path = Path(__file__).parent.parent / "backend" / "requirements.txt"
155+
if req_path.exists():
156+
with open(req_path) as f:
157+
content = f.read()
158+
159+
dependencies = [
160+
"psycopg2-binary",
161+
"redis",
162+
"celery",
163+
"minio",
164+
"sqlalchemy"
165+
]
166+
167+
for dep in dependencies:
168+
if dep in content:
169+
print(f"✅ {dep}")
170+
else:
171+
print(f"❌ {dep} missing from requirements")
172+
else:
173+
print("❌ requirements.txt not found")
174+
175+
print()
176+
177+
def main():
178+
"""Run all infrastructure tests"""
179+
print("🚀 SmartQuery Infrastructure Test Suite")
180+
print("=" * 50)
181+
print()
182+
183+
test_docker_compose_config()
184+
test_backend_structure()
185+
test_database_init()
186+
test_environment_config()
187+
test_service_imports()
188+
test_requirements()
189+
190+
print("✨ Infrastructure test completed!")
191+
print()
192+
print("📝 Next steps:")
193+
print("1. Install Docker and Docker Compose")
194+
print("2. Run: docker compose up -d")
195+
print("3. Test with: cd backend && python main.py")
196+
print("4. Check health: curl http://localhost:8000/health/")
197+
198+
if __name__ == "__main__":
199+
main()

0 commit comments

Comments
 (0)