This commit is contained in:
Tobe O 2018-11-10 11:59:07 -05:00
parent 37abf01168
commit aea408b2f7
4 changed files with 30 additions and 17 deletions

View file

@ -1,2 +1,6 @@
# 2.0.1
* Add `ignoreQueryAndFragment` to `ResponseCache`.
* Rename `CacheService.ignoreQuery` to `ignoreParams`.
# 1.0.0 # 1.0.0
* First version * First version

View file

@ -19,7 +19,10 @@ class ResponseCache {
final Map<String, _CachedResponse> _cache = {}; final Map<String, _CachedResponse> _cache = {};
final Map<String, Pool> _writeLocks = {}; final Map<String, Pool> _writeLocks = {};
ResponseCache({this.timeout}); /// If `true` (default: `false`), then caching of results will discard URI query parameters and fragments.
final bool ignoreQueryAndFragment;
ResponseCache({this.timeout, this.ignoreQueryAndFragment: false});
/// Closes all internal write-locks, and closes the cache. /// Closes all internal write-locks, and closes the cache.
Future close() async { Future close() async {
@ -40,9 +43,9 @@ class ResponseCache {
// Check if there is a cache entry. // Check if there is a cache entry.
for (var pattern in patterns) { for (var pattern in patterns) {
if (pattern.allMatches(req.uri.path).isNotEmpty && if (pattern.allMatches(_getEffectivePath(req)).isNotEmpty &&
_cache.containsKey(req.uri.path)) { _cache.containsKey(_getEffectivePath(req))) {
var response = _cache[req.uri.path]; var response = _cache[_getEffectivePath(req)];
//print('timestamp ${response.timestamp} vs since ${modifiedSince}'); //print('timestamp ${response.timestamp} vs since ${modifiedSince}');
if (response.timestamp.compareTo(modifiedSince) <= 0) { if (response.timestamp.compareTo(modifiedSince) <= 0) {
@ -62,6 +65,9 @@ class ResponseCache {
return true; return true;
} }
String _getEffectivePath(RequestContext req) =>
ignoreQueryAndFragment == true ? req.uri.path : req.uri.toString();
/// Serves content from the cache, if applicable. /// Serves content from the cache, if applicable.
Future<bool> handleRequest(RequestContext req, ResponseContext res) async { Future<bool> handleRequest(RequestContext req, ResponseContext res) async {
if (!await ifModifiedSince(req, res)) return false; if (!await ifModifiedSince(req, res)) return false;
@ -73,11 +79,11 @@ class ResponseCache {
// If `if-modified-since` is present, this check has already been performed. // If `if-modified-since` is present, this check has already been performed.
if (req.headers.ifModifiedSince == null) { if (req.headers.ifModifiedSince == null) {
for (var pattern in patterns) { for (var pattern in patterns) {
if (pattern.allMatches(req.uri.path).isNotEmpty) { if (pattern.allMatches(_getEffectivePath(req)).isNotEmpty) {
var now = new DateTime.now().toUtc(); var now = new DateTime.now().toUtc();
if (_cache.containsKey(req.uri.path)) { if (_cache.containsKey(_getEffectivePath(req))) {
var response = _cache[req.uri.path]; var response = _cache[_getEffectivePath(req)];
if (timeout != null) { if (timeout != null) {
// If the cache timeout has been met, don't send the cached response. // If the cache timeout has been met, don't send the cached response.
@ -108,27 +114,27 @@ class ResponseCache {
// Check if there is a cache entry. // Check if there is a cache entry.
for (var pattern in patterns) { for (var pattern in patterns) {
if (pattern.allMatches(req.uri.path).isNotEmpty) { if (pattern.allMatches(_getEffectivePath(req)).isNotEmpty) {
var now = new DateTime.now().toUtc(); var now = new DateTime.now().toUtc();
// Invalidate the response, if need be. // Invalidate the response, if need be.
if (_cache.containsKey(req.uri.path)) { if (_cache.containsKey(_getEffectivePath(req))) {
// If there is no timeout, don't invalidate. // If there is no timeout, don't invalidate.
if (timeout == null) return true; if (timeout == null) return true;
// Otherwise, don't invalidate unless the timeout has been exceeded. // Otherwise, don't invalidate unless the timeout has been exceeded.
var response = _cache[req.uri.path]; var response = _cache[_getEffectivePath(req)];
if (now.difference(response.timestamp) < timeout) return true; if (now.difference(response.timestamp) < timeout) return true;
// If the cache entry should be invalidated, then invalidate it. // If the cache entry should be invalidated, then invalidate it.
purge(req.uri.path); purge(_getEffectivePath(req));
} }
// Save the response. // Save the response.
var writeLock = var writeLock =
_writeLocks.putIfAbsent(req.uri.path, () => new Pool(1)); _writeLocks.putIfAbsent(_getEffectivePath(req), () => new Pool(1));
await writeLock.withResource(() { await writeLock.withResource(() {
_cache[req.uri.path] = new _CachedResponse( _cache[_getEffectivePath(req)] = new _CachedResponse(
new Map.from(res.headers), res.buffer.toBytes(), now); new Map.from(res.headers), res.buffer.toBytes(), now);
}); });

View file

@ -16,7 +16,10 @@ class CacheService<Id, Data> extends Service<Id, Data> {
/// If not provided, this defaults to a [MapService]. /// If not provided, this defaults to a [MapService].
final Service<Id, Data> cache; final Service<Id, Data> cache;
final bool ignoreQuery; /// If `true` (default: `false`), then result caching will discard parameters passed to service methods.
///
/// If you want to return a cached result more-often-than-not, you may want to enable this.
final bool ignoreParams;
final Duration timeout; final Duration timeout;
@ -26,7 +29,7 @@ class CacheService<Id, Data> extends Service<Id, Data> {
CacheService( CacheService(
{@required this.database, {@required this.database,
@required this.cache, @required this.cache,
this.ignoreQuery: false, this.ignoreParams: false,
this.timeout}) { this.timeout}) {
assert(database != null); assert(database != null);
} }
@ -47,7 +50,7 @@ class CacheService<Id, Data> extends Service<Id, Data> {
if (timeout == null || !expired) { if (timeout == null || !expired) {
// Read from the cache if necessary // Read from the cache if necessary
var queryEqual = ignoreQuery == true || var queryEqual = ignoreParams == true ||
(params != null && (params != null &&
cached.params != null && cached.params != null &&
const MapEquality().equals( const MapEquality().equals(

View file

@ -1,5 +1,5 @@
name: angel_cache name: angel_cache
version: 2.0.0 version: 2.0.1
homepage: https://github.com/angel-dart/cache homepage: https://github.com/angel-dart/cache
description: Support for server-side caching in Angel. description: Support for server-side caching in Angel.
author: Tobe O <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>