Spaces:
Runtime error
Runtime error
feat: synchronize text-to-sql-bot codebase with Hugging Face Space repository, including Docker build configurations
6086e71 | """ | |
| PlainSQL Load Test β Simulates real user behavior across all query types. | |
| Run locally: | |
| locust -f tests/load/locustfile.py --host=http://localhost:8000 | |
| Web UI opens at http://localhost:8089 β configure users, ramp-up, and duration. | |
| Recommended scenarios: | |
| Smoke: 5 users, 1/sec ramp, 2 min | |
| Normal: 30 users, 5/sec ramp, 10 min | |
| Peak: 100 users, 10/sec ramp, 10 min | |
| Soak: 30 users, 5/sec ramp, 60 min (memory leak detection) | |
| """ | |
| from locust import HttpUser, task, between, tag | |
| import random | |
| # ββ Realistic query distribution βββββββββββββββββββββββββ | |
| EASY_QUERIES = [ | |
| "Show top 5 employees by salary", | |
| "List all products", | |
| "Show me customers from North America", | |
| "What is the most expensive product?", | |
| "Show me products with low stock", | |
| ] | |
| MEDIUM_QUERIES = [ | |
| "Total sales revenue by region", | |
| "Which department has the highest average salary?", | |
| "How many employees are in each department?", | |
| "Average product price by category", | |
| ] | |
| HARD_QUERIES = [ | |
| "Who are the top 3 salespeople by total revenue?", | |
| "Compare sales between Q1 and Q2", | |
| "Monthly sales trend for the last 6 months", | |
| "Which employees have sold more than the department average?", | |
| ] | |
| CHAT_QUERIES = [ | |
| "Hello", | |
| "What can you do?", | |
| "Thanks!", | |
| "Who are you?", | |
| "How does this work?", | |
| ] | |
| # ββ Repeat queries to test cache hit behavior ββββββββββββ | |
| CACHED_QUERIES = [ | |
| "Show top 5 employees by salary", | |
| "What is the total sales revenue?", | |
| ] | |
| class PlainSQLUser(HttpUser): | |
| """Simulates a real user interacting with PlainSQL.""" | |
| wait_time = between(2, 8) # 2-8 seconds between requests (realistic pacing) | |
| def on_start(self): | |
| """Login and get JWT token on user spawn.""" | |
| response = self.client.post( | |
| "/api/v1/auth/login", | |
| json={"username": "analyst", "password": "analyst123"}, | |
| name="/auth/login", | |
| ) | |
| if response.status_code == 200: | |
| self.token = response.json().get("access_token", "") | |
| self.headers = {"Authorization": f"Bearer {self.token}"} | |
| else: | |
| self.headers = {} | |
| def _chat(self, question: str, label: str): | |
| """Helper to send a chat request with auth headers.""" | |
| self.client.post( | |
| "/chat", | |
| json={"question": question, "history": []}, | |
| headers=self.headers, | |
| name=f"/chat [{label}]", | |
| ) | |
| def easy_query(self): | |
| """Simple data queries β should complete in 1-3s.""" | |
| self._chat(random.choice(EASY_QUERIES), "easy") | |
| def medium_query(self): | |
| """Aggregation queries β medium complexity.""" | |
| self._chat(random.choice(MEDIUM_QUERIES), "medium") | |
| def hard_query(self): | |
| """Complex JOIN queries β expected 2-4s.""" | |
| self._chat(random.choice(HARD_QUERIES), "hard") | |
| def chat_message(self): | |
| """Conversational messages β should return in <100ms (no LLM).""" | |
| self._chat(random.choice(CHAT_QUERIES), "chat") | |
| def cached_query(self): | |
| """Repeat queries β should be served from cache in <10ms.""" | |
| self._chat(random.choice(CACHED_QUERIES), "cached") | |
| def health_check(self): | |
| """Health endpoint β should always respond in <50ms.""" | |
| self.client.get("/api/v1/health", name="/health") | |