Ram2005 commited on
Commit
53f3bf4
Β·
verified Β·
1 Parent(s): e8609dd

Upload backend/database.py

Browse files
Files changed (1) hide show
  1. backend/database.py +67 -4
backend/database.py CHANGED
@@ -1,16 +1,24 @@
1
  """
2
  Bharat Tech Atlas β€” Database layer using SQLite with R-Tree spatial indexing.
 
 
3
  """
4
  import sqlite3
5
  import os
6
- import json
7
  import math
 
8
 
9
  DB_PATH = os.path.join(os.path.dirname(__file__), "..", "data", "bharattechatlas.db")
 
10
 
 
 
 
11
 
12
- def get_db():
13
- conn = sqlite3.connect(DB_PATH)
 
 
14
  conn.row_factory = sqlite3.Row
15
  conn.execute("PRAGMA journal_mode=WAL")
16
  conn.execute("PRAGMA foreign_keys=ON")
@@ -18,11 +26,34 @@ def get_db():
18
  conn.execute("PRAGMA mmap_size=67108864")
19
  conn.execute("PRAGMA synchronous=NORMAL")
20
  conn.execute("PRAGMA temp_store=MEMORY")
 
21
  return conn
22
 
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  def init_db():
25
- conn = get_db()
 
26
 
27
  conn.executescript("""
28
  CREATE TABLE IF NOT EXISTS entities (
@@ -148,10 +179,42 @@ def init_db():
148
  ('wealthtech', 'WealthTech', 'πŸ“ˆ', '#7C3AED', 'dpiit_category');
149
  """)
150
 
 
 
 
 
 
 
 
 
151
  conn.commit()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  conn.close()
153
 
154
 
 
 
 
 
 
 
 
 
 
 
155
  def haversine_distance(lat1, lon1, lat2, lon2):
156
  R = 6371
157
  dlat = math.radians(lat2 - lat1)
 
1
  """
2
  Bharat Tech Atlas β€” Database layer using SQLite with R-Tree spatial indexing.
3
+ v3.2: Added connection pooling, schema_version table for migrations, and
4
+ proper cleanup on shutdown.
5
  """
6
  import sqlite3
7
  import os
 
8
  import math
9
+ import threading
10
 
11
  DB_PATH = os.path.join(os.path.dirname(__file__), "..", "data", "bharattechatlas.db")
12
+ SCHEMA_VERSION = 2 # Bump when schema changes
13
 
14
+ # ─── Connection pool ──────────────────────────────────────────────────────────
15
+ _pool_lock = threading.Lock()
16
+ _pool = {}
17
 
18
+
19
+ def _create_connection():
20
+ """Create a new SQLite connection with optimized PRAGMAs."""
21
+ conn = sqlite3.connect(DB_PATH, check_same_thread=False)
22
  conn.row_factory = sqlite3.Row
23
  conn.execute("PRAGMA journal_mode=WAL")
24
  conn.execute("PRAGMA foreign_keys=ON")
 
26
  conn.execute("PRAGMA mmap_size=67108864")
27
  conn.execute("PRAGMA synchronous=NORMAL")
28
  conn.execute("PRAGMA temp_store=MEMORY")
29
+ conn.execute("PRAGMA busy_timeout=5000")
30
  return conn
31
 
32
 
33
+ def get_db():
34
+ """Get a connection from the pool (one per thread)."""
35
+ tid = threading.current_thread().ident
36
+ with _pool_lock:
37
+ if tid not in _pool or _pool[tid] is None:
38
+ _pool[tid] = _create_connection()
39
+ return _pool[tid]
40
+
41
+
42
+ def close_all_connections():
43
+ """Close all pooled connections. Call on shutdown."""
44
+ with _pool_lock:
45
+ for tid, conn in list(_pool.items()):
46
+ try:
47
+ conn.close()
48
+ except Exception:
49
+ pass
50
+ _pool[tid] = None
51
+ _pool.clear()
52
+
53
+
54
  def init_db():
55
+ """Initialize database schema with migration tracking."""
56
+ conn = _create_connection()
57
 
58
  conn.executescript("""
59
  CREATE TABLE IF NOT EXISTS entities (
 
179
  ('wealthtech', 'WealthTech', 'πŸ“ˆ', '#7C3AED', 'dpiit_category');
180
  """)
181
 
182
+ # ─── Schema versioning / migrations ───────────────────────────────────────
183
+ conn.execute("""
184
+ CREATE TABLE IF NOT EXISTS schema_version (
185
+ version INTEGER PRIMARY KEY,
186
+ applied_at TEXT DEFAULT (datetime('now'))
187
+ )
188
+ """)
189
+ conn.execute("INSERT OR IGNORE INTO schema_version (version) VALUES (0)")
190
  conn.commit()
191
+
192
+ # Run migrations
193
+ current = conn.execute("SELECT version FROM schema_version ORDER BY version DESC LIMIT 1").fetchone()[0]
194
+ if current < 1:
195
+ conn.execute("UPDATE schema_version SET version = 1 WHERE version = 0")
196
+ conn.commit()
197
+ if current < 2:
198
+ try:
199
+ conn.execute("ALTER TABLE entities ADD COLUMN github_stars INTEGER DEFAULT 0")
200
+ except sqlite3.OperationalError:
201
+ pass # Column already exists
202
+ conn.execute("UPDATE schema_version SET version = 2 WHERE version = 1")
203
+ conn.commit()
204
+
205
  conn.close()
206
 
207
 
208
+ def is_seeded() -> bool:
209
+ """Check if database already has seed data."""
210
+ try:
211
+ conn = get_db()
212
+ count = conn.execute("SELECT COUNT(*) FROM entities WHERE is_active = 1").fetchone()[0]
213
+ return count > 100
214
+ except Exception:
215
+ return False
216
+
217
+
218
  def haversine_distance(lat1, lon1, lat2, lon2):
219
  R = 6371
220
  dlat = math.radians(lat2 - lat1)