CodeXDevloper commited on
Commit
2c070a4
·
verified ·
1 Parent(s): 90fa5ae

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -27
app.py CHANGED
@@ -1,60 +1,99 @@
1
  from fastapi import FastAPI, HTTPException, Query
 
2
  import duckdb
 
3
  from contextlib import asynccontextmanager
 
4
 
5
- # Global connection object
6
- con = duckdb.connect()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
- # Lifespan use karke app start hote hi heavy initialization ek baar karenge
9
  @asynccontextmanager
10
  async def lifespan(app: FastAPI):
11
- print("DuckDB extensions load ho rahi hain aur View ban raha hai...")
12
- con.execute("INSTALL httpfs; LOAD httpfs;")
13
-
14
- # Parquet file ka correct URL
15
- PARQUET_URL = "https://huggingface.co/datasets/CodeXDevloper/Inddatainonefile/resolve/main/users_data.parquet"
16
-
17
- # Startup par hi Ek baar View bana kar metadata cache kar lete hain
18
- # Isse har API request par network par load nahi padega
19
- con.execute(f"CREATE OR REPLACE VIEW users_view AS SELECT * FROM read_parquet('{PARQUET_URL}')")
20
- print("View taiyar hai! API requests ke liye taiyar hai.")
21
  yield
22
- con.close()
 
 
23
 
24
  app = FastAPI(title="Super Fast Search API", lifespan=lifespan)
25
 
 
 
 
 
 
 
 
 
26
  @app.get("/")
27
  def home():
28
- return {"message": "Fast API online hai! Use /search?mobile=YOUR_NUMBER"}
 
 
 
 
 
 
 
 
 
29
 
30
  @app.get("/search")
31
  async def search_mobile(mobile: str = Query(..., description="Enter mobile number to search")):
 
 
 
32
  try:
33
- # Ab hum direct cache kiye hue 'users_view' se data nikalenge
 
34
  query = """
35
  SELECT mobile, name, fname, address, alt, circle, id, email
36
  FROM users_view
37
- WHERE mobile = ?
38
  LIMIT 1
39
  """
40
-
41
- result = con.execute(query, [str(mobile)]).fetchall()
42
-
43
  if not result:
44
  return {
45
- "status": "error",
46
  "message": f"Mobile number {mobile} nahi mila."
47
  }
48
-
49
- # Data mapping
50
  columns = [desc[0] for desc in con.description]
51
  row_dict = dict(zip(columns, result[0]))
52
-
53
  return {
54
  "status": "success",
55
  "data": row_dict
56
  }
57
-
58
  except Exception as e:
59
- # Internal error ko secure rakhne ke liye mask kiya hai
60
- raise HTTPException(status_code=500, detail="Query timeout ya process nahi ho payi.")
 
 
 
1
  from fastapi import FastAPI, HTTPException, Query
2
+ from fastapi.middleware.cors import CORSMiddleware
3
  import duckdb
4
+ import threading
5
  from contextlib import asynccontextmanager
6
+ import os
7
 
8
+ # Thread-local storage — har thread ka apna connection hoga
9
+ # Isse concurrent requests pe crash nahi hoga
10
+ _local = threading.local()
11
+
12
+ PARQUET_URL = "https://huggingface.co/datasets/CodeXDevloper/Inddatainonefile/resolve/main/users_data.parquet"
13
+
14
+ def get_con():
15
+ """Har thread ke liye alag DuckDB connection dega"""
16
+ if not hasattr(_local, 'con') or _local.con is None:
17
+ con = duckdb.connect()
18
+ con.execute("INSTALL httpfs; LOAD httpfs;")
19
+ con.execute(f"""
20
+ CREATE OR REPLACE VIEW users_view AS
21
+ SELECT * FROM read_parquet('{PARQUET_URL}')
22
+ """)
23
+ _local.con = con
24
+ return _local.con
25
 
 
26
  @asynccontextmanager
27
  async def lifespan(app: FastAPI):
28
+ print("API start ho rahi hai...")
29
+ # Main thread ka connection startup pe bana lo
30
+ try:
31
+ con = get_con()
32
+ # Ek test query — parquet file check karo
33
+ con.execute("SELECT COUNT(*) FROM users_view").fetchone()
34
+ print("✅ Parquet file load ho gayi! API ready hai.")
35
+ except Exception as e:
36
+ print(f"⚠️ Startup error: {e}")
 
37
  yield
38
+ # Cleanup
39
+ if hasattr(_local, 'con') and _local.con:
40
+ _local.con.close()
41
 
42
  app = FastAPI(title="Super Fast Search API", lifespan=lifespan)
43
 
44
+ # CORS — kisi bhi frontend se API call ho sake
45
+ app.add_middleware(
46
+ CORSMiddleware,
47
+ allow_origins=["*"],
48
+ allow_methods=["GET"],
49
+ allow_headers=["*"],
50
+ )
51
+
52
  @app.get("/")
53
  def home():
54
+ return {
55
+ "message": "Super Fast Search API online hai!",
56
+ "usage": "/search?mobile=YOUR_NUMBER",
57
+ "status": "running"
58
+ }
59
+
60
+ @app.get("/health")
61
+ def health():
62
+ """Keep-alive ping ke liye yeh endpoint use karo"""
63
+ return {"status": "ok"}
64
 
65
  @app.get("/search")
66
  async def search_mobile(mobile: str = Query(..., description="Enter mobile number to search")):
67
+ if not mobile.strip().isdigit():
68
+ return {"status": "error", "message": "Sirf numbers enter karein."}
69
+
70
  try:
71
+ con = get_con() # Thread-safe connection
72
+
73
  query = """
74
  SELECT mobile, name, fname, address, alt, circle, id, email
75
  FROM users_view
76
+ WHERE CAST(mobile AS VARCHAR) = ?
77
  LIMIT 1
78
  """
79
+ result = con.execute(query, [mobile.strip()]).fetchall()
80
+
 
81
  if not result:
82
  return {
83
+ "status": "error",
84
  "message": f"Mobile number {mobile} nahi mila."
85
  }
86
+
 
87
  columns = [desc[0] for desc in con.description]
88
  row_dict = dict(zip(columns, result[0]))
89
+
90
  return {
91
  "status": "success",
92
  "data": row_dict
93
  }
94
+
95
  except Exception as e:
96
+ print(f"Query error: {e}")
97
+ # Connection reset karo agar error aaye
98
+ _local.con = None
99
+ raise HTTPException(status_code=500, detail="Query process nahi ho payi. Dobara try karein.")