mirror of
https://gitlab.com/mysocialportal/relatica
synced 2024-10-18 12:23:31 +00:00
Add very short term (2 second) HTTP GET request cache for when multiple calls to same endpoint from redraws
This commit is contained in:
parent
782d3ba14d
commit
4ff673e6fd
1 changed files with 135 additions and 10 deletions
|
@ -12,6 +12,133 @@ final _logger = Logger('NetworkUtils');
|
|||
|
||||
http.Response requestTimeout() => http.Response('Client side timeout', 408);
|
||||
|
||||
enum _RequestType {
|
||||
get,
|
||||
}
|
||||
|
||||
const _expireDuration = Duration(seconds: 2);
|
||||
|
||||
class _CachedResponse {
|
||||
final _RequestType requestType;
|
||||
final Uri requestUri;
|
||||
final Map<String, dynamic> requestBody;
|
||||
final Map<String, String> headers;
|
||||
final http.Response response;
|
||||
final DateTime requestTime;
|
||||
|
||||
_CachedResponse(
|
||||
{required this.requestType,
|
||||
required this.requestUri,
|
||||
required this.requestBody,
|
||||
required this.headers,
|
||||
required this.response,
|
||||
required this.requestTime});
|
||||
|
||||
factory _CachedResponse.requestStub(_RequestType type, Uri uri,
|
||||
Map<String, String>? headers, Map<String, dynamic>? body) =>
|
||||
_CachedResponse(
|
||||
requestType: type,
|
||||
requestUri: uri,
|
||||
requestBody: body ?? {},
|
||||
headers: headers ?? {},
|
||||
response: http.Response('', 555),
|
||||
requestTime: DateTime(0),
|
||||
);
|
||||
|
||||
factory _CachedResponse.response(
|
||||
_RequestType type,
|
||||
Uri uri,
|
||||
Map<String, String>? headers,
|
||||
Map<String, dynamic>? body,
|
||||
http.Response response,
|
||||
) =>
|
||||
_CachedResponse(
|
||||
requestType: type,
|
||||
requestUri: uri,
|
||||
requestBody: body ?? {},
|
||||
headers: headers ?? {},
|
||||
response: response,
|
||||
requestTime: DateTime.now(),
|
||||
);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is _CachedResponse &&
|
||||
runtimeType == other.runtimeType &&
|
||||
requestType == other.requestType &&
|
||||
requestUri == other.requestUri;
|
||||
|
||||
@override
|
||||
int get hashCode => requestType.hashCode ^ requestUri.hashCode;
|
||||
}
|
||||
|
||||
class _ExpiringRequestCache {
|
||||
final _responses = <_CachedResponse, _CachedResponse>{};
|
||||
|
||||
void _cleanupCache() {
|
||||
final expireTime = DateTime.now().subtract(_expireDuration);
|
||||
_logger
|
||||
.finest('Cleaning up request cache with ${_responses.length} entries');
|
||||
_responses.removeWhere((key, value) {
|
||||
final expired = key.requestTime.isBefore(expireTime);
|
||||
if (expired) {
|
||||
_logger.finest(
|
||||
'Expiring request: ${value.requestType} => ${value.requestUri}');
|
||||
}
|
||||
return expired;
|
||||
});
|
||||
_logger.finest('Cleaned up request cache has ${_responses.length} entries');
|
||||
}
|
||||
|
||||
Future<http.Response> getRequestOrExecute({
|
||||
required Uri url,
|
||||
Map<String, String>? headers,
|
||||
Map<String, dynamic>? body,
|
||||
Duration? timeout,
|
||||
}) async {
|
||||
_cleanupCache();
|
||||
const type = _RequestType.get;
|
||||
final requestStub = _CachedResponse.requestStub(
|
||||
type,
|
||||
url,
|
||||
headers,
|
||||
null,
|
||||
);
|
||||
|
||||
late final http.Response response;
|
||||
if (_responses.containsKey(requestStub)) {
|
||||
print('Returning cached response for $type => $url');
|
||||
response = _responses[requestStub]?.response ?? http.Response('', 555);
|
||||
} else {
|
||||
final request = http.get(
|
||||
url,
|
||||
headers: headers,
|
||||
);
|
||||
|
||||
response = await request.timeout(
|
||||
timeout ?? apiCallTimeout,
|
||||
onTimeout: requestTimeout,
|
||||
);
|
||||
|
||||
final cacheEntry = _CachedResponse.response(
|
||||
type,
|
||||
url,
|
||||
headers ?? {},
|
||||
body ?? {},
|
||||
response,
|
||||
);
|
||||
|
||||
print('Adding cached response for $type => $url');
|
||||
_responses[cacheEntry] = cacheEntry;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
final _cache = _ExpiringRequestCache();
|
||||
|
||||
FutureResult<PagedResponse<String>, ExecError> getUrl(
|
||||
Uri url, {
|
||||
Map<String, String>? headers,
|
||||
|
@ -23,14 +150,10 @@ FutureResult<PagedResponse<String>, ExecError> getUrl(
|
|||
requestHeaders['Cookie'] = 'XDEBUG_SESSION=PHPSTORM;path=/';
|
||||
}
|
||||
try {
|
||||
final request = http.get(
|
||||
url,
|
||||
headers: requestHeaders,
|
||||
);
|
||||
|
||||
final response = await request.timeout(
|
||||
timeout ?? apiCallTimeout,
|
||||
onTimeout: requestTimeout,
|
||||
final response = await _cache.getRequestOrExecute(
|
||||
url: url,
|
||||
headers: headers,
|
||||
timeout: timeout ?? apiCallTimeout,
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
|
@ -87,6 +210,7 @@ FutureResult<String, ExecError> putUrl(
|
|||
Uri url,
|
||||
Map<String, dynamic> body, {
|
||||
Map<String, String>? headers,
|
||||
Duration? timeout,
|
||||
}) async {
|
||||
_logger.fine('PUT: $url \n Body: $body');
|
||||
try {
|
||||
|
@ -97,7 +221,7 @@ FutureResult<String, ExecError> putUrl(
|
|||
);
|
||||
|
||||
final response = await request.timeout(
|
||||
apiCallTimeout,
|
||||
timeout ?? apiCallTimeout,
|
||||
onTimeout: requestTimeout,
|
||||
);
|
||||
|
||||
|
@ -117,6 +241,7 @@ FutureResult<String, ExecError> deleteUrl(
|
|||
Uri url,
|
||||
Map<String, dynamic> body, {
|
||||
Map<String, String>? headers,
|
||||
Duration? timeout,
|
||||
}) async {
|
||||
_logger.fine('DELETE: $url');
|
||||
try {
|
||||
|
@ -127,7 +252,7 @@ FutureResult<String, ExecError> deleteUrl(
|
|||
);
|
||||
|
||||
final response = await request.timeout(
|
||||
apiCallTimeout,
|
||||
timeout ?? apiCallTimeout,
|
||||
onTimeout: requestTimeout,
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue