Chromium Code Reviews| Index: tools/gardening_tools/base_lib/lib/src/cache.dart |
| diff --git a/tools/gardening_tools/base_lib/lib/src/cache.dart b/tools/gardening_tools/base_lib/lib/src/cache.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8a4b28affc2628c26289e8baee8b0201d51be2e4 |
| --- /dev/null |
| +++ b/tools/gardening_tools/base_lib/lib/src/cache.dart |
| @@ -0,0 +1,156 @@ |
| +// 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> Call(); |
|
Johnni Winther
2017/08/23 12:40:46
Rename to [ReadResultFunction] and variables of th
|
| +typedef Future<String> WithCache(Call call, [String key]); |
| +typedef WithCache PerformWithCache({String overrideKey, Duration duration}); |
|
Johnni Winther
2017/08/23 12:40:47
Rename to [CreateCacheFunction] and variables of t
|
| + |
| +PerformWithCache initCache(Uri baseUri, [Logger logger]) { |
| + if (logger == null) { |
| + logger = new StdOutLogger(Level.warning); |
|
Johnni Winther
2017/08/23 12:40:47
Just write this as:
logger ??= new StdOutLogger(L
|
| + } |
| + |
| + final cache = new Cache(baseUri, logger); |
| + |
| + return ({String overrideKey, Duration duration}) { |
| + if (duration == null) { |
| + duration = new Duration(hours: 24); |
| + } |
| + |
| + return (Call 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<ReadFromCacheResult> readResult = |
|
Johnni Winther
2017/08/23 12:40:46
Rename to [cacheResult].
|
| + await cache.tryRead(key, duration); |
| + if (!readResult.isError() && readResult.get().hasResult) { |
| + logger.debug("Found key $key in cache"); |
| + return readResult.get().res; |
| + } |
| + if (readResult.isError()) { |
| + logger.error("Error when reading from cache", readResult.getError(), |
| + readResult.getStackTrace()); |
| + } |
| + } |
| + |
| + 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; |
| + }; |
| + }; |
| +} |
| + |
| +PerformWithCache noCache() { |
| + return ({String overrideKey, Duration duration}) { |
| + return (Call call, [String key]) { |
| + return call(); |
| + }; |
| + }; |
| +} |
| + |
| +/// Simple cache for caching data. |
| +class Cache { |
|
Johnni Winther
2017/08/23 12:40:46
Add a TODO (for me?) to use this instead of the Ca
|
| + 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<ReadFromCacheResult>> tryRead(String path, |
|
Johnni Winther
2017/08/23 12:40:46
Rename to [read] (since we always just try)
|
| + [Duration duration]) async { |
| + if (memoryCache.containsKey(path)) { |
| + logger.debug('Found $path in memory cache'); |
| + return new Try.from(new ReadFromCacheResult.result(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 ReadFromCacheResult.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'); |
|
Johnni Winther
2017/08/23 12:40:47
Split long strings manual:
logger.debug(
'Fil
|
| + return new Try.from(new ReadFromCacheResult.noResult()); |
| + } |
| + |
| + return tryStartAsync(() async { |
| + logger.debug('Found $path in file cache'); |
| + var text = await file.readAsString(); |
| + memoryCache[path] = text; |
| + return new ReadFromCacheResult.result(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 cache |
| + Future clearCache(Uri baseUri) async { |
| + // needs to be done |
|
Johnni Winther
2017/08/23 12:40:47
Write this as
// TODO(mkroghj): Implement this.
|
| + } |
| +} |
| + |
| +class ReadFromCacheResult { |
|
Johnni Winther
2017/08/23 12:40:46
Rename to [CacheResult] (the correctly name reads
|
| + bool hasResult; |
|
Johnni Winther
2017/08/23 12:40:47
Make the fields final.
|
| + String res; |
|
Johnni Winther
2017/08/23 12:40:47
Rename to [result]. We generally use unabbreviated
Bill Hesse
2017/08/23 15:41:25
I agree - alway use full, correctly-spelled words
|
| + |
| + ReadFromCacheResult.noResult() { |
| + hasResult = false; |
| + res = null; |
| + } |
| + |
| + ReadFromCacheResult.result(String result) { |
|
Johnni Winther
2017/08/23 12:40:47
Rename to the no-name constructor and use initiali
|
| + hasResult = true; |
| + this.res = result; |
| + } |
| +} |