Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Unified Diff: tools/gardening_tools/base_lib/lib/src/cache.dart

Issue 3005443002: Additional tools for gardening. (Closed)
Patch Set: Removed accidental commit Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698