Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 import 'dart:async'; | |
| 6 import 'dart:io'; | |
| 7 import 'logger.dart'; | |
| 8 import 'try.dart'; | |
| 9 | |
| 10 typedef Future<String> Call(); | |
|
Johnni Winther
2017/08/23 12:40:46
Rename to [ReadResultFunction] and variables of th
| |
| 11 typedef Future<String> WithCache(Call call, [String key]); | |
| 12 typedef WithCache PerformWithCache({String overrideKey, Duration duration}); | |
|
Johnni Winther
2017/08/23 12:40:47
Rename to [CreateCacheFunction] and variables of t
| |
| 13 | |
| 14 PerformWithCache initCache(Uri baseUri, [Logger logger]) { | |
| 15 if (logger == null) { | |
| 16 logger = new StdOutLogger(Level.warning); | |
|
Johnni Winther
2017/08/23 12:40:47
Just write this as:
logger ??= new StdOutLogger(L
| |
| 17 } | |
| 18 | |
| 19 final cache = new Cache(baseUri, logger); | |
| 20 | |
| 21 return ({String overrideKey, Duration duration}) { | |
| 22 if (duration == null) { | |
| 23 duration = new Duration(hours: 24); | |
| 24 } | |
| 25 | |
| 26 return (Call call, [String key]) async { | |
| 27 if (overrideKey != null) { | |
| 28 key = overrideKey; | |
| 29 } | |
| 30 | |
| 31 if (key == null || key.isEmpty) { | |
| 32 logger.warning("Key is null or empty - cannot cache result"); | |
| 33 } else { | |
| 34 // format key | |
| 35 key = key.replaceAll("/", "_").replaceAll(".", "_"); | |
| 36 | |
| 37 Try<ReadFromCacheResult> readResult = | |
|
Johnni Winther
2017/08/23 12:40:46
Rename to [cacheResult].
| |
| 38 await cache.tryRead(key, duration); | |
| 39 if (!readResult.isError() && readResult.get().hasResult) { | |
| 40 logger.debug("Found key $key in cache"); | |
| 41 return readResult.get().res; | |
| 42 } | |
| 43 if (readResult.isError()) { | |
| 44 logger.error("Error when reading from cache", readResult.getError(), | |
| 45 readResult.getStackTrace()); | |
| 46 } | |
| 47 } | |
| 48 | |
| 49 logger.debug("Could not find key $key in cache"); | |
| 50 | |
| 51 // we have to make a call | |
| 52 String result = await call(); | |
| 53 | |
| 54 // insert/update the cache | |
| 55 if (key != null && !key.isEmpty) { | |
| 56 await cache.write(key, result); | |
| 57 } | |
| 58 | |
| 59 return result; | |
| 60 }; | |
| 61 }; | |
| 62 } | |
| 63 | |
| 64 PerformWithCache noCache() { | |
| 65 return ({String overrideKey, Duration duration}) { | |
| 66 return (Call call, [String key]) { | |
| 67 return call(); | |
| 68 }; | |
| 69 }; | |
| 70 } | |
| 71 | |
| 72 /// Simple cache for caching data. | |
| 73 class Cache { | |
|
Johnni Winther
2017/08/23 12:40:46
Add a TODO (for me?) to use this instead of the Ca
| |
| 74 Uri base; | |
| 75 Logger logger; | |
| 76 | |
| 77 Cache(this.base, this.logger); | |
| 78 | |
| 79 Map<String, String> memoryCache = <String, String>{}; | |
| 80 | |
| 81 /// Checks if key [path] is in cache | |
| 82 Future<bool> containsKey(String path, [Duration duration]) async { | |
| 83 if (memoryCache.containsKey(path)) return true; | |
| 84 | |
| 85 File file = new File.fromUri(base.resolve(path)); | |
| 86 if (await file.exists()) { | |
| 87 return duration == null | |
| 88 ? true | |
| 89 : new DateTime.now().difference(await file.lastModified()) <= | |
| 90 duration; | |
| 91 } | |
| 92 | |
| 93 return false; | |
| 94 } | |
| 95 | |
| 96 /// Try reading [path] from cache | |
| 97 Future<Try<ReadFromCacheResult>> tryRead(String path, | |
|
Johnni Winther
2017/08/23 12:40:46
Rename to [read] (since we always just try)
| |
| 98 [Duration duration]) async { | |
| 99 if (memoryCache.containsKey(path)) { | |
| 100 logger.debug('Found $path in memory cache'); | |
| 101 return new Try.from(new ReadFromCacheResult.result(memoryCache[path])); | |
| 102 } | |
| 103 | |
| 104 File file = new File.fromUri(base.resolve(path)); | |
| 105 | |
| 106 if (!await file.exists()) { | |
| 107 logger.debug('Could not find file $path in file cache'); | |
| 108 return new Try.from(new ReadFromCacheResult.noResult()); | |
| 109 } | |
| 110 | |
| 111 if (duration != null && | |
| 112 new DateTime.now().difference(await file.lastModified()) > duration) { | |
| 113 logger.debug( | |
| 114 'File $path was found but the information is too stale, for the durati on: $duration'); | |
|
Johnni Winther
2017/08/23 12:40:47
Split long strings manual:
logger.debug(
'Fil
| |
| 115 return new Try.from(new ReadFromCacheResult.noResult()); | |
| 116 } | |
| 117 | |
| 118 return tryStartAsync(() async { | |
| 119 logger.debug('Found $path in file cache'); | |
| 120 var text = await file.readAsString(); | |
| 121 memoryCache[path] = text; | |
| 122 return new ReadFromCacheResult.result(text); | |
| 123 }); | |
| 124 } | |
| 125 | |
| 126 /// Store [text] as the cache data for [path]. | |
| 127 Future write(String path, String text) async { | |
| 128 logger.debug('Creating $path in file cache'); | |
| 129 File file = new File.fromUri(base.resolve(path)); | |
| 130 if (!await file.exists()) { | |
| 131 await file.create(recursive: true); | |
| 132 } | |
| 133 await file.writeAsString(text); | |
| 134 memoryCache[path] = text; | |
| 135 } | |
| 136 | |
| 137 /// Clears cache | |
| 138 Future clearCache(Uri baseUri) async { | |
| 139 // needs to be done | |
|
Johnni Winther
2017/08/23 12:40:47
Write this as
// TODO(mkroghj): Implement this.
| |
| 140 } | |
| 141 } | |
| 142 | |
| 143 class ReadFromCacheResult { | |
|
Johnni Winther
2017/08/23 12:40:46
Rename to [CacheResult] (the correctly name reads
| |
| 144 bool hasResult; | |
|
Johnni Winther
2017/08/23 12:40:47
Make the fields final.
| |
| 145 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
| |
| 146 | |
| 147 ReadFromCacheResult.noResult() { | |
| 148 hasResult = false; | |
| 149 res = null; | |
| 150 } | |
| 151 | |
| 152 ReadFromCacheResult.result(String result) { | |
|
Johnni Winther
2017/08/23 12:40:47
Rename to the no-name constructor and use initiali
| |
| 153 hasResult = true; | |
| 154 this.res = result; | |
| 155 } | |
| 156 } | |
| OLD | NEW |