|
1 | 1 | import { AppDataSource } from '../datasources/PostgresDS.js'; |
| 2 | +import { DRADataSource } from '../models/DRADataSource.js'; |
2 | 3 | import { getRedisClient } from '../config/redis.config.js'; |
3 | 4 | import { ScheduledBackupProcessor } from './ScheduledBackupProcessor.js'; |
4 | 5 | import { ScheduledBackupService } from '../services/ScheduledBackupService.js'; |
@@ -151,8 +152,9 @@ export class AdminStatsProcessor { |
151 | 152 | let activeRedisSessions = 0; |
152 | 153 | try { |
153 | 154 | const redis = getRedisClient(); |
154 | | - const keys = await redis.keys('dra:ai:*session*'); |
155 | | - activeRedisSessions = keys.length; |
| 155 | + for await (const _key of redis.scanIterator({ MATCH: 'dra:ai:*session*' })) { |
| 156 | + activeRedisSessions++; |
| 157 | + } |
156 | 158 | } catch { |
157 | 159 | activeRedisSessions = 0; |
158 | 160 | } |
@@ -183,63 +185,63 @@ export class AdminStatsProcessor { |
183 | 185 | }; |
184 | 186 | } |
185 | 187 |
|
186 | | - private async querySyncHealthSummary(manager: any) { |
187 | | - const rows = await manager.query(` |
188 | | - SELECT |
189 | | - COUNT(*)::int AS total, |
190 | | - COUNT(*) FILTER ( |
191 | | - WHERE data_type NOT IN ('postgresql','mysql','mariadb','mongodb','csv','excel','pdf') |
192 | | - AND ( |
193 | | - connection_details->'api_connection_details'->'api_config'->>'last_sync' IS NULL |
194 | | - OR connection_details->'api_connection_details'->'api_config'->>'last_sync' = 'null' |
195 | | - ) |
196 | | - )::int AS never_synced, |
197 | | - 0::int AS failed |
198 | | - FROM dra_data_sources |
199 | | - `); |
200 | | - const r = rows[0] || {}; |
| 188 | + private async querySyncHealthSummary(_manager: any) { |
| 189 | + const FILE_DB_TYPES = ['postgresql', 'mysql', 'mariadb', 'mongodb', 'csv', 'excel', 'pdf']; |
| 190 | + const dataSources = await AppDataSource.manager.find(DRADataSource); |
| 191 | + |
| 192 | + const total = dataSources.length; |
| 193 | + let neverSynced = 0; |
| 194 | + let failedSources = 0; |
| 195 | + |
| 196 | + for (const ds of dataSources) { |
| 197 | + if (FILE_DB_TYPES.includes(ds.data_type)) continue; |
| 198 | + const lastSync = ds.connection_details?.api_connection_details?.api_config?.last_sync; |
| 199 | + if (!lastSync) { |
| 200 | + neverSynced++; |
| 201 | + } else { |
| 202 | + const hoursSinceSync = (Date.now() - new Date(lastSync as any).getTime()) / 3600000; |
| 203 | + if (hoursSinceSync > 72) failedSources++; |
| 204 | + } |
| 205 | + } |
| 206 | + |
201 | 207 | return { |
202 | | - totalSources: r.total || 0, |
203 | | - failedSources: r.failed || 0, |
204 | | - neverSynced: r.never_synced || 0, |
| 208 | + totalSources: total, |
| 209 | + failedSources, |
| 210 | + neverSynced, |
205 | 211 | }; |
206 | 212 | } |
207 | 213 |
|
208 | 214 | async getSyncHealthData(): Promise<IDataSourceSyncRow[]> { |
209 | | - const manager = AppDataSource.manager; |
210 | | - const rows = await manager.query(` |
211 | | - SELECT |
212 | | - ds.id, |
213 | | - ds.name, |
214 | | - ds.data_type, |
215 | | - ds.created_at, |
216 | | - u.email AS owner_email, |
217 | | - ds.connection_details->'api_connection_details'->'api_config'->>'last_sync' AS last_sync |
218 | | - FROM dra_data_sources ds |
219 | | - LEFT JOIN dra_users_platform u ON ds.users_platform_id = u.id |
220 | | - ORDER BY ds.id DESC |
221 | | - LIMIT 200 |
222 | | - `); |
| 215 | + const FILE_DB_TYPES = ['postgresql', 'mysql', 'mariadb', 'mongodb', 'csv', 'excel', 'pdf']; |
| 216 | + |
| 217 | + const dataSources = await AppDataSource.manager.find(DRADataSource, { |
| 218 | + relations: ['users_platform'], |
| 219 | + order: { id: 'DESC' }, |
| 220 | + take: 200, |
| 221 | + }); |
| 222 | + |
| 223 | + return dataSources.map((ds) => { |
| 224 | + const isFileOrDb = FILE_DB_TYPES.includes(ds.data_type); |
| 225 | + const lastSyncRaw = ds.connection_details?.api_connection_details?.api_config?.last_sync; |
| 226 | + const lastSync = lastSyncRaw ? String(lastSyncRaw) : null; |
223 | 227 |
|
224 | | - return rows.map((r: any) => { |
225 | | - const isFileOrDb = ['postgresql', 'mysql', 'mariadb', 'mongodb', 'csv', 'excel', 'pdf'].includes(r.data_type); |
226 | 228 | let status: 'synced' | 'failed' | 'never' = 'synced'; |
227 | 229 | if (!isFileOrDb) { |
228 | | - if (!r.last_sync || r.last_sync === 'null') { |
| 230 | + if (!lastSync || lastSync === 'null') { |
229 | 231 | status = 'never'; |
230 | 232 | } else { |
231 | | - const lastSyncDate = new Date(r.last_sync); |
232 | | - const hoursSinceSync = (Date.now() - lastSyncDate.getTime()) / 3600000; |
| 233 | + const hoursSinceSync = (Date.now() - new Date(lastSync).getTime()) / 3600000; |
233 | 234 | status = hoursSinceSync > 72 ? 'failed' : 'synced'; |
234 | 235 | } |
235 | 236 | } |
| 237 | + |
236 | 238 | return { |
237 | | - id: r.id, |
238 | | - name: r.name, |
239 | | - data_type: r.data_type, |
240 | | - owner_email: r.owner_email || 'Unknown', |
241 | | - last_sync: r.last_sync || null, |
242 | | - created_at: r.created_at || null, |
| 239 | + id: ds.id, |
| 240 | + name: ds.name, |
| 241 | + data_type: ds.data_type, |
| 242 | + owner_email: (ds as any).users_platform?.email || 'Unknown', |
| 243 | + last_sync: lastSync, |
| 244 | + created_at: ds.created_at ? String(ds.created_at) : null, |
243 | 245 | status, |
244 | 246 | }; |
245 | 247 | }); |
|
0 commit comments