FreshPixels commited on
Commit
a3ef05a
·
verified ·
1 Parent(s): 943a612

Delete database.py

Browse files
Files changed (1) hide show
  1. database.py +0 -188
database.py DELETED
@@ -1,188 +0,0 @@
1
- import asyncpg
2
- import logging
3
- from typing import Optional, List, Dict, Any
4
- from config import config
5
-
6
- logger = logging.getLogger(__name__)
7
-
8
-
9
- class Database:
10
- def __init__(self) -> None:
11
- self.pool: Optional[asyncpg.Pool] = None
12
-
13
- async def connect(self) -> None:
14
- self.pool = await asyncpg.create_pool(
15
- dsn=config.DATABASE_URL,
16
- min_size=1,
17
- max_size=3,
18
- command_timeout=60,
19
- )
20
- logger.info("Database pool created (max_size=3)")
21
- await self._create_tables()
22
-
23
- async def disconnect(self) -> None:
24
- if self.pool:
25
- await self.pool.close()
26
- logger.info("Database pool closed")
27
-
28
- def _acquire(self):
29
- if self.pool is None:
30
- raise RuntimeError("Database not connected. Call connect() first.")
31
- return self.pool.acquire()
32
-
33
- async def _create_tables(self) -> None:
34
- async with self._acquire() as conn:
35
- await conn.execute("""
36
- CREATE TABLE IF NOT EXISTS users (
37
- id BIGINT PRIMARY KEY,
38
- username VARCHAR(255),
39
- first_name VARCHAR(255),
40
- last_name VARCHAR(255),
41
- created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
42
- updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
43
- )
44
- """)
45
- await conn.execute("""
46
- CREATE TABLE IF NOT EXISTS messages (
47
- id SERIAL PRIMARY KEY,
48
- user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
49
- role VARCHAR(20) NOT NULL CHECK (role IN ('user', 'assistant', 'system')),
50
- content TEXT NOT NULL,
51
- is_summarized BOOLEAN DEFAULT FALSE,
52
- created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
53
- )
54
- """)
55
- await conn.execute("""
56
- CREATE INDEX IF NOT EXISTS idx_messages_user_id_created_at
57
- ON messages(user_id, created_at DESC)
58
- """)
59
- await conn.execute("""
60
- CREATE INDEX IF NOT EXISTS idx_messages_user_id_summarized
61
- ON messages(user_id, is_summarized, created_at DESC)
62
- """)
63
- await conn.execute("""
64
- CREATE TABLE IF NOT EXISTS summaries (
65
- id SERIAL PRIMARY KEY,
66
- user_id BIGINT NOT NULL UNIQUE REFERENCES users(id) ON DELETE CASCADE,
67
- summary TEXT NOT NULL,
68
- message_count INTEGER NOT NULL DEFAULT 0,
69
- created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
70
- updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
71
- )
72
- """)
73
- logger.info("Database tables created/verified")
74
-
75
- async def upsert_user(
76
- self,
77
- user_id: int,
78
- username: Optional[str],
79
- first_name: Optional[str],
80
- last_name: Optional[str],
81
- ) -> None:
82
- async with self._acquire() as conn:
83
- await conn.execute("""
84
- INSERT INTO users (id, username, first_name, last_name)
85
- VALUES ($1, $2, $3, $4)
86
- ON CONFLICT (id) DO UPDATE SET
87
- username = EXCLUDED.username,
88
- first_name = EXCLUDED.first_name,
89
- last_name = EXCLUDED.last_name,
90
- updated_at = NOW()
91
- """, user_id, username, first_name, last_name)
92
-
93
- async def save_message(self, user_id: int, role: str, content: str) -> None:
94
- async with self._acquire() as conn:
95
- await conn.execute("""
96
- INSERT INTO messages (user_id, role, content)
97
- VALUES ($1, $2, $3)
98
- """, user_id, role, content)
99
-
100
- async def get_messages(self, user_id: int, limit: int = 30) -> List[Dict[str, Any]]:
101
- async with self._acquire() as conn:
102
- rows = await conn.fetch("""
103
- SELECT role, content, created_at
104
- FROM messages
105
- WHERE user_id = $1 AND is_summarized = FALSE
106
- ORDER BY created_at DESC
107
- LIMIT $2
108
- """, user_id, limit)
109
- return [
110
- {"role": r["role"], "content": r["content"], "created_at": r["created_at"]}
111
- for r in reversed(rows)
112
- ]
113
-
114
- async def get_summary(self, user_id: int) -> Optional[str]:
115
- async with self._acquire() as conn:
116
- row = await conn.fetchrow("""
117
- SELECT summary FROM summaries WHERE user_id = $1
118
- """, user_id)
119
- return row["summary"] if row else None
120
-
121
- async def save_summary(self, user_id: int, summary: str, message_count: int) -> None:
122
- async with self._acquire() as conn:
123
- await conn.execute("""
124
- INSERT INTO summaries (user_id, summary, message_count, updated_at)
125
- VALUES ($1, $2, $3, NOW())
126
- ON CONFLICT (user_id) DO UPDATE SET
127
- summary = EXCLUDED.summary,
128
- message_count = summaries.message_count + EXCLUDED.message_count,
129
- updated_at = NOW()
130
- """, user_id, summary, message_count)
131
-
132
- async def mark_summarized(self, user_id: int, cutoff_id: int) -> None:
133
- async with self._acquire() as conn:
134
- await conn.execute("""
135
- UPDATE messages
136
- SET is_summarized = TRUE
137
- WHERE user_id = $1 AND id <= $2
138
- """, user_id, cutoff_id)
139
-
140
- async def get_oldest_unsummarized(self, user_id: int, limit: int) -> List[Dict[str, Any]]:
141
- async with self._acquire() as conn:
142
- rows = await conn.fetch("""
143
- SELECT id, role, content
144
- FROM messages
145
- WHERE user_id = $1 AND is_summarized = FALSE
146
- ORDER BY created_at ASC
147
- LIMIT $2
148
- """, user_id, limit)
149
- return [{"id": r["id"], "role": r["role"], "content": r["content"]} for r in rows]
150
-
151
- async def count_unsummarized(self, user_id: int) -> int:
152
- async with self._acquire() as conn:
153
- val = await conn.fetchval("""
154
- SELECT COUNT(*) FROM messages
155
- WHERE user_id = $1 AND is_summarized = FALSE
156
- """, user_id)
157
- return val or 0
158
-
159
- async def clear_history(self, user_id: int) -> int:
160
- async with self._acquire() as conn:
161
- result = await conn.execute("""
162
- DELETE FROM messages WHERE user_id = $1
163
- """, user_id)
164
- await conn.execute("""
165
- DELETE FROM summaries WHERE user_id = $1
166
- """, user_id)
167
- try:
168
- count = int(result.split()[-1])
169
- except (ValueError, IndexError):
170
- count = 0
171
- logger.info("Cleared %d messages and summary for user %s", count, user_id)
172
- return count
173
-
174
- async def get_stats(self, user_id: int) -> Dict[str, Any]:
175
- async with self._acquire() as conn:
176
- user_count = await conn.fetchval("SELECT COUNT(*) FROM users")
177
- msg_count = await conn.fetchval(
178
- "SELECT COUNT(*) FROM messages WHERE user_id = $1", user_id
179
- )
180
- total_msg_count = await conn.fetchval("SELECT COUNT(*) FROM messages")
181
- return {
182
- "total_users": user_count,
183
- "user_messages": msg_count,
184
- "total_messages": total_msg_count,
185
- }
186
-
187
-
188
- db = Database()