-
-
Save bubnenkoff/65fa684a3de218bab6102453df3f79fe to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'package:parser_monitor_server/Services/Database.dart'; | |
import 'package:parser_monitor_server/Services/Globals.dart'; | |
import 'package:postgres/postgres.dart'; | |
enum CacheLevel { | |
oneMinute, | |
tenMinutes, | |
oneHour, | |
oneDay | |
} | |
class RequestCacheStruct { | |
int requestHash; | |
DateTime requestDate; | |
PostgreSQLResult requestResult; | |
bool? markedAsOutDate; | |
RequestCacheStruct(this.requestHash, this.requestDate, this.requestResult); | |
} | |
class QueryResultCache { | |
List<RequestCacheStruct> requestsCacheList = []; | |
// Если один и тот же запрос отправлен два раза подряд, то второй точно такой же выполнять нет смысла | |
Map<int, Future<PostgreSQLResult>> pendingFutures = {}; | |
Future<void> addResultToCache(sqlQuery) async { | |
try { | |
if(pendingFutures.containsKey(sqlQuery.hashCode)) { | |
print('This query is already running'); | |
await pendingFutures[sqlQuery.hashCode]; | |
// await pendingFutures.remove(sqlQuery.hashCode); // удаляем обработанную Future из списка | |
} | |
else { | |
pendingFutures.addAll({sqlQuery.hashCode: connection.query(sqlQuery, timeoutInSeconds: 3600)}); | |
var queryResult = await pendingFutures[sqlQuery.hashCode]; // выполняем отложенную Future | |
var queryObj = RequestCacheStruct(sqlQuery.hashCode, DateTime.now(), queryResult! ); | |
requestsCacheList.add(queryObj); | |
await pendingFutures.remove(sqlQuery.hashCode); // удаляем обработанную Future из списка | |
// pendingFutures.addAll({ | |
// sqlQuery.hashCode: connection.query(sqlQuery, timeoutInSeconds: 3600) | |
// .then((queryResult) { | |
// var queryResult = pendingFutures[sqlQuery.hashCode]; // выполняем отложенную Future | |
// }) | |
// } | |
// ); | |
print('Query was added to сache'); | |
} | |
} | |
on TimeoutException catch(e) { | |
print('!!!TimeoutException: ${e.message}' ); | |
// rethrow делать пока не нужно -- мы не знаем как обрабатывать ошибку уровнем выше | |
// rethrow; | |
} | |
on PostgreSQLException catch(e) { | |
print('PostgreSQLException: ${e.message}' ); | |
rethrow; | |
} | |
on Exception catch(e) { | |
print('Base Exception: ${e}' ); | |
} | |
} | |
// результат есть где-то в кэше | |
PostgreSQLResult getResultFromCache(sqlQuery) { | |
return requestsCacheList.firstWhere((element) => element.requestHash == sqlQuery.hashCode).requestResult; | |
// for (var req in requestsCacheList) { | |
// if(req.requestHash == sqlQuery.hashCode) { | |
// return req.requestResult; | |
// } | |
// } | |
} | |
bool isQueryInCache(sqlQuery, cacheLevel) { | |
// requestsList.any((element) => element.requestHash == el.requestHash); | |
// if(requestsList.isEmpty) return false; | |
for(var req in requestsCacheList) { | |
if(req.requestHash == sqlQuery.hashCode) { | |
// теперь нужно проверить на сколько устарел запрос по сравнению с временем кэширования | |
if(cacheLevel == CacheLevel.oneMinute) { | |
if( req.requestDate.isBefore( DateTime.now().subtract(Duration(minutes: 1)) )) { | |
req.markedAsOutDate = true; | |
} | |
} | |
if(cacheLevel == CacheLevel.tenMinutes) { | |
if( req.requestDate.isBefore( DateTime.now().subtract(Duration(minutes: 10)) )) { | |
req.markedAsOutDate = true; | |
} | |
} | |
if(cacheLevel == CacheLevel.oneHour) { | |
if( req.requestDate.isBefore( DateTime.now().subtract(Duration(minutes: 60)) )) { | |
req.markedAsOutDate = true; | |
} | |
} | |
if(cacheLevel == CacheLevel.oneDay) { | |
if( req.requestDate.isBefore( DateTime.now().subtract(Duration(hours: 24)) )) { | |
req.markedAsOutDate = true; | |
} | |
} | |
} | |
} | |
requestsCacheList.removeWhere((element) => element.markedAsOutDate == true); | |
// print("requestsList: $requestsList"); | |
var result = requestsCacheList.any((element) => element.requestHash == sqlQuery.hashCode); | |
if(result) {print('Request is in cache');} | |
else {print('Request is NOT in cache');} | |
return result; | |
} | |
Future<PostgreSQLResult?> executeQuery(sql, cacheLevel) async { | |
// если в кэше нет ничего то возвращается null | |
// можно без null но тогда нужно придумать как реализовать пустой PostgreSQLResult | |
PostgreSQLResult? result; | |
// if (queryResultCache.isQueryInCache(sql, cacheLevel)) { | |
// result = await queryResultCache.getResultFromCache(sql); | |
// } | |
// else { | |
// await queryResultCache.addResultToCache(sql); | |
// result = await queryResultCache.getResultFromCache(sql); | |
// print("here potential null: $result"); | |
// } | |
if (!queryResultCache.isQueryInCache(sql, cacheLevel)) { | |
await queryResultCache.addResultToCache(sql); | |
} | |
result = await queryResultCache.getResultFromCache(sql); | |
print("here potential null. Don't know why: $result"); | |
return result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment