Skeleton for ResponseCache

This commit is contained in:
Tobe O 2018-04-01 21:05:35 -04:00
parent ad077502fc
commit d4226ab83f
5 changed files with 91 additions and 22 deletions

View file

@ -8,4 +8,8 @@ Support for server-side caching in [Angel](https://angel-dart.github.io).
*TODO: Documentation* *TODO: Documentation*
A `Service` class that caches data from one service, storing it in another. A `Service` class that caches data from one service, storing it in another.
An imaginable use case is storing results from MongoDB or another database in Redis. An imaginable use case is storing results from MongoDB or another database in
MemcacheD/Redis.
## `Cache`
*TODO: Documentation*

View file

@ -1,21 +1,2 @@
import 'package:angel_framework/angel_framework.dart'; export 'src/cache.dart';
import 'package:meta/meta.dart'; export 'src/cache_service.dart';
/// An Angel [Service] that caches data from another service.
///
/// This is useful for applications of scale, where network latency
/// can have real implications on application performance.
class CacheService extends Service {
/// The underlying [Service] that represents the original data store.
final Service database;
/// The [Service] used to interface with a caching layer.
///
/// If not provided, this defaults to a [MapService].
final Service cache;
CacheService({@required this.database, Service cache})
: this.cache = cache ?? new MapService() {
assert(database != null);
}
}

61
lib/src/cache.dart Normal file
View file

@ -0,0 +1,61 @@
import 'dart:async';
import 'package:angel_framework/angel_framework.dart';
import 'package:intl/intl.dart';
final DateFormat _fmt = new DateFormat('EEE, d MMM yyyy HH:mm:ss');
/// Formats a date (converted to UTC), ex: `Sun, 03 May 2015 23:02:37 GMT`.
String _formatDateForHttp(DateTime dt) => _fmt.format(dt.toUtc()) + ' GMT';
class ResponseCache {
final List<Pattern> patterns = [];
final Duration timeout;
final Map<String, _CachedResponse> _cache = {};
ResponseCache({this.timeout});
Future<bool> handleRequest(RequestContext req, ResponseContext res) async {
var now = new DateTime.now().toUtc();
// Check if there is a cache entry.
for (var pattern in patterns) {
if (pattern.allMatches(req.uri.path).isNotEmpty && _cache.containsKey(req.uri.path)) {
var response = _cache[req.uri.path];
// Only send a cached response if it is valid.
if (timeout == null || now.difference(response.timestamp) >= timeout) {
// TODO: If-Last-Modified
break;
}
}
}
return true;
}
Future<bool> responseFinalizer(RequestContext req, ResponseContext res) async {
var now = new DateTime.now().toUtc();
}
void setCachedHeaders(
DateTime modified, RequestContext req, ResponseContext res) {
var privacy = 'public';
res.headers
..['cache-control'] = '$privacy, max-age=${timeout?.inSeconds ?? 0}'
..['last-modified'] = _formatDateForHttp(modified);
if (timeout != null) {
var expiry = new DateTime.now().add(timeout);
res.headers['expires'] = _formatDateForHttp(expiry);
}
}
}
class _CachedResponse {
final Map<String, String> headers;
final List<int> body;
final DateTime timestamp;
_CachedResponse({this.headers, this.body, this.timestamp});
}

View file

@ -0,0 +1,21 @@
import 'package:angel_framework/angel_framework.dart';
import 'package:meta/meta.dart';
/// An Angel [Service] that caches data from another service.
///
/// This is useful for applications of scale, where network latency
/// can have real implications on application performance.
class CacheService extends Service {
/// The underlying [Service] that represents the original data store.
final Service database;
/// The [Service] used to interface with a caching layer.
///
/// If not provided, this defaults to a [MapService].
final Service cache;
CacheService({@required this.database, Service cache})
: this.cache = cache ?? new MapService() {
assert(database != null);
}
}

View file

@ -1,7 +1,9 @@
name: angel_cache name: angel_cache
dependencies: dependencies:
angel_framework: ">=1.0.0-dev <2.0.0" angel_framework: ">=1.0.0-dev <2.0.0"
intl: ^0.15.0
meta: ^1.0.0 meta: ^1.0.0
dev_dependencies: dev_dependencies:
angel_test: ^1.1.0 angel_test: ^1.1.0
glob: ^1.0.0
test: ^0.12.0 test: ^0.12.0