| Index: tools/gardening/lib/src/cache_new.dart
|
| diff --git a/tools/gardening/lib/src/cache_new.dart b/tools/gardening/lib/src/cache_new.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cafd893e1758355fffe94dcbacad121cc5928045
|
| --- /dev/null
|
| +++ b/tools/gardening/lib/src/cache_new.dart
|
| @@ -0,0 +1,150 @@
|
| +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +import 'dart:async';
|
| +import 'dart:io';
|
| +import 'logger.dart';
|
| +import 'try.dart';
|
| +
|
| +typedef Future<String> FetchDataFunction();
|
| +typedef Future<String> WithCacheFunction(FetchDataFunction fetchData,
|
| + [String key]);
|
| +typedef WithCacheFunction CreateCacheFunction(
|
| + {String overrideKey, Duration duration});
|
| +
|
| +CreateCacheFunction initCache(Uri baseUri, [Logger logger]) {
|
| + final cache = new Cache(baseUri, logger);
|
| + logger ??= new StdOutLogger(Level.warning);
|
| +
|
| + return ({String overrideKey, Duration duration}) {
|
| + if (duration == null) {
|
| + duration = new Duration(hours: 24);
|
| + }
|
| +
|
| + return (FetchDataFunction call, [String key]) async {
|
| + if (overrideKey != null) {
|
| + key = overrideKey;
|
| + }
|
| +
|
| + if (key == null || key.isEmpty) {
|
| + logger.warning("Key is null or empty - cannot cache result");
|
| + } else {
|
| + // format key
|
| + key = key.replaceAll("/", "_").replaceAll(".", "_");
|
| +
|
| + Try<CacheResult> readResult = await cache.read(key, duration);
|
| + if (!readResult.isError && readResult.value.hasResult) {
|
| + logger.debug("Found key $key in cache");
|
| + return readResult.value.result;
|
| + }
|
| + if (readResult.isError) {
|
| + logger.error("Error when reading from cache", readResult.error,
|
| + readResult.stackTrace);
|
| + }
|
| + }
|
| +
|
| + logger.debug("Could not find key $key in cache");
|
| +
|
| + // we have to make a call
|
| + String result = await call();
|
| +
|
| + // insert/update the cache
|
| + if (key != null && !key.isEmpty) {
|
| + await cache.write(key, result);
|
| + }
|
| +
|
| + return result;
|
| + };
|
| + };
|
| +}
|
| +
|
| +CreateCacheFunction noCache() {
|
| + return ({String overrideKey, Duration duration}) {
|
| + return (FetchDataFunction fetchData, [String key]) {
|
| + return fetchData();
|
| + };
|
| + };
|
| +}
|
| +
|
| +/// Simple cache for caching data.
|
| +class Cache {
|
| + // TODO(mkroghj) use this instead of cache.dart
|
| + Uri base;
|
| + Logger logger;
|
| +
|
| + Cache(this.base, this.logger);
|
| +
|
| + Map<String, String> memoryCache = <String, String>{};
|
| +
|
| + /// Checks if key [path] is in cache
|
| + Future<bool> containsKey(String path, [Duration duration]) async {
|
| + if (memoryCache.containsKey(path)) return true;
|
| +
|
| + File file = new File.fromUri(base.resolve(path));
|
| + if (await file.exists()) {
|
| + return duration == null
|
| + ? true
|
| + : new DateTime.now().difference(await file.lastModified()) <=
|
| + duration;
|
| + }
|
| +
|
| + return false;
|
| + }
|
| +
|
| + /// Try reading [path] from cache
|
| + Future<Try<CacheResult>> read(String path, [Duration duration]) async {
|
| + if (memoryCache.containsKey(path)) {
|
| + logger.debug('Found $path in memory cache');
|
| + return new Try.from(new CacheResult(memoryCache[path]));
|
| + }
|
| +
|
| + File file = new File.fromUri(base.resolve(path));
|
| +
|
| + if (!(await file.exists())) {
|
| + logger.debug('Could not find file $path in file cache');
|
| + return new Try.from(new CacheResult.noResult());
|
| + }
|
| +
|
| + if (duration != null &&
|
| + new DateTime.now().difference(await file.lastModified()) > duration) {
|
| + logger.debug('File $path was found but the information is too stale,'
|
| + 'for the duration: $duration');
|
| + return new Try.from(new CacheResult.noResult());
|
| + }
|
| +
|
| + return tryStartAsync(() async {
|
| + logger.debug('Found $path in file cache');
|
| + var text = await file.readAsString();
|
| + memoryCache[path] = text;
|
| + return new CacheResult(text);
|
| + });
|
| + }
|
| +
|
| + /// Store [text] as the cache data for [path].
|
| + Future write(String path, String text) async {
|
| + logger.debug('Creating $path in file cache');
|
| + File file = new File.fromUri(base.resolve(path));
|
| + if (!await file.exists()) {
|
| + await file.create(recursive: true);
|
| + }
|
| + await file.writeAsString(text);
|
| + memoryCache[path] = text;
|
| + }
|
| +
|
| + /// Clears the cache at [baseUri]
|
| + Future clearCache(Uri baseUri) async {
|
| + await new Directory(baseUri.toFilePath()).delete(recursive: true);
|
| + }
|
| +}
|
| +
|
| +class CacheResult {
|
| + final bool hasResult;
|
| + final String result;
|
| +
|
| + CacheResult.noResult()
|
| + : hasResult = false,
|
| + result = null {}
|
| +
|
| + CacheResult(this.result) : hasResult = true {}
|
| +}
|
|
|