app.py
4.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
"""
Main FastAPI application for the search service.
Usage:
uvicorn api.app:app --host 0.0.0.0 --port 8000 --reload
"""
import os
import sys
from typing import Optional
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
import argparse
# Add parent directory to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from config import ConfigLoader, CustomerConfig
from utils import ESClient
from search import Searcher
from query import QueryParser
# Global instances
_config: Optional[CustomerConfig] = None
_es_client: Optional[ESClient] = None
_searcher: Optional[Searcher] = None
_query_parser: Optional[QueryParser] = None
def init_service(customer_id: str = "customer1", es_host: str = "http://localhost:9200"):
"""
Initialize search service with configuration.
Args:
customer_id: Customer configuration ID
es_host: Elasticsearch host URL
"""
global _config, _es_client, _searcher, _query_parser
print(f"Initializing search service for customer: {customer_id}")
# Load configuration
config_loader = ConfigLoader("config/schema")
_config = config_loader.load_customer_config(customer_id)
# Validate configuration
errors = config_loader.validate_config(_config)
if errors:
raise ValueError(f"Configuration validation failed: {errors}")
print(f"Configuration loaded: {_config.customer_name}")
# Initialize ES client
_es_client = ESClient(hosts=[es_host])
if not _es_client.ping():
raise ConnectionError(f"Failed to connect to Elasticsearch at {es_host}")
print(f"Connected to Elasticsearch: {es_host}")
# Initialize query parser
_query_parser = QueryParser(_config)
print("Query parser initialized")
# Initialize searcher
_searcher = Searcher(_config, _es_client, _query_parser)
print("Searcher initialized")
print("Search service ready!")
def get_config() -> CustomerConfig:
"""Get customer configuration."""
if _config is None:
raise RuntimeError("Service not initialized")
return _config
def get_es_client() -> ESClient:
"""Get Elasticsearch client."""
if _es_client is None:
raise RuntimeError("Service not initialized")
return _es_client
def get_searcher() -> Searcher:
"""Get searcher instance."""
if _searcher is None:
raise RuntimeError("Service not initialized")
return _searcher
def get_query_parser() -> QueryParser:
"""Get query parser instance."""
if _query_parser is None:
raise RuntimeError("Service not initialized")
return _query_parser
# Create FastAPI app
app = FastAPI(
title="E-Commerce Search API",
description="Configurable search engine for cross-border e-commerce",
version="1.0.0"
)
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.on_event("startup")
async def startup_event():
"""Initialize service on startup."""
customer_id = os.getenv("CUSTOMER_ID", "customer1")
es_host = os.getenv("ES_HOST", "http://localhost:9200")
try:
init_service(customer_id=customer_id, es_host=es_host)
except Exception as e:
print(f"Failed to initialize service: {e}")
print("Service will start but may not function correctly")
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
"""Global exception handler."""
return JSONResponse(
status_code=500,
content={
"error": "Internal server error",
"detail": str(exc)
}
)
@app.get("/")
async def root():
"""Root endpoint."""
return {
"service": "E-Commerce Search API",
"version": "1.0.0",
"status": "running"
}
# Include routers
from .routes import search, admin
app.include_router(search.router)
app.include_router(admin.router)
if __name__ == "__main__":
import uvicorn
parser = argparse.ArgumentParser(description='Start search API service')
parser.add_argument('--host', default='0.0.0.0', help='Host to bind to')
parser.add_argument('--port', type=int, default=8000, help='Port to bind to')
parser.add_argument('--customer', default='customer1', help='Customer ID')
parser.add_argument('--es-host', default='http://localhost:9200', help='Elasticsearch host')
parser.add_argument('--reload', action='store_true', help='Enable auto-reload')
args = parser.parse_args()
# Set environment variables
os.environ['CUSTOMER_ID'] = args.customer
os.environ['ES_HOST'] = args.es_host
# Run server
uvicorn.run(
"api.app:app",
host=args.host,
port=args.port,
reload=args.reload
)