From fac57fc93f28bd179ea079f74768e282de530753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Tue, 8 Mar 2022 16:40:03 +0800 Subject: [PATCH 1/2] fix: bundle cache contextId and cache object deleted --- kraken/lib/src/devtools/module.dart | 2 +- kraken/lib/src/foundation/http_cache.dart | 13 +++++++++++-- kraken/lib/src/foundation/http_cache_object.dart | 16 ++++++++++++---- .../lib/src/foundation/http_client_request.dart | 2 +- kraken/lib/src/launcher/bundle.dart | 2 +- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/kraken/lib/src/devtools/module.dart b/kraken/lib/src/devtools/module.dart index e908161138..0c0a392387 100644 --- a/kraken/lib/src/devtools/module.dart +++ b/kraken/lib/src/devtools/module.dart @@ -45,7 +45,7 @@ abstract class UIInspectorModule extends _InspectorModule { @override void sendEventToFrontend(InspectorEvent event) { - devtoolsService.isolateServerPort!.send(event); + devtoolsService.isolateServerPort?.send(event); } } diff --git a/kraken/lib/src/foundation/http_cache.dart b/kraken/lib/src/foundation/http_cache.dart index 6e96259ba6..5ab102a38e 100644 --- a/kraken/lib/src/foundation/http_cache.dart +++ b/kraken/lib/src/foundation/http_cache.dart @@ -102,12 +102,17 @@ class HttpCacheController { // Add or update the httpCacheObject to memory cache. void putObject(Uri uri, HttpCacheObject cacheObject) { if (_caches.length == _maxCachedObjects) { - _caches.remove(_caches.lastKey()); + _caches.remove(_caches.lastKey()); } final String key = _getCacheKey(uri); _caches.update(key, (value) => cacheObject, ifAbsent: () => cacheObject); } + void removeObject(Uri uri) { + final String key = _getCacheKey(uri); + _caches.remove(key); + } + Future interceptResponse( HttpClientRequest request, HttpClientResponse response, @@ -132,7 +137,11 @@ class HttpCacheController { ); // Cache the object. - putObject(request.uri, cacheObject); + if (cacheObject.valid) { + putObject(request.uri, cacheObject); + } else { + removeObject(request.uri); + } return HttpClientCachedResponse(response, cacheObject); } diff --git a/kraken/lib/src/foundation/http_cache_object.dart b/kraken/lib/src/foundation/http_cache_object.dart index 557ceaf7b0..890f6662a2 100644 --- a/kraken/lib/src/foundation/http_cache_object.dart +++ b/kraken/lib/src/foundation/http_cache_object.dart @@ -146,13 +146,17 @@ class HttpCacheObject { /// Read the index file. Future read() async { - if (_valid) return; - final bool isIndexFileExist = await _file.exists(); - if (!isIndexFileExist) { - // Index file not exist, dispose. + // Make sure file exists, or causing io exception. + if (!await _file.exists() || !await _blob.exists()) { + _valid = false; return; } + // If index read before, ignoring to read again. + // Note: if index or blob file were being changed, this will make chaos, + // usually this is an abnormal operation. + if (_valid) return; + try { Uint8List bytes = await _file.readAsBytes(); ByteData byteData = bytes.buffer.asByteData(); @@ -286,6 +290,10 @@ class HttpCacheObject { // Store shorted response headers, 4B. writeString(bytesBuilder, headers ?? '', 4); + // In case of cache object file is deleted by accident. + if (!await _file.exists()) { + await _file.create(recursive: true); + } // The index file will not be TOO LARGE, // so take bytes at one time. await _file.writeAsBytes(bytesBuilder.takeBytes(), flush: true); diff --git a/kraken/lib/src/foundation/http_client_request.dart b/kraken/lib/src/foundation/http_client_request.dart index 75545d474a..8d1a1b6101 100644 --- a/kraken/lib/src/foundation/http_client_request.dart +++ b/kraken/lib/src/foundation/http_client_request.dart @@ -158,7 +158,7 @@ class ProxyHttpClientRequest extends HttpClientRequest { } // Step 3: Handle negotiate cache request header. - if (headers.ifModifiedSince == null && headers.value(HttpHeaders.ifNoneMatchHeader) == null) { + if (cacheObject.valid && headers.ifModifiedSince == null && headers.value(HttpHeaders.ifNoneMatchHeader) == null) { // ETag has higher priority of lastModified. if (cacheObject.eTag != null) { headers.set(HttpHeaders.ifNoneMatchHeader, cacheObject.eTag!); diff --git a/kraken/lib/src/launcher/bundle.dart b/kraken/lib/src/launcher/bundle.dart index 41a135b170..53775d16c9 100644 --- a/kraken/lib/src/launcher/bundle.dart +++ b/kraken/lib/src/launcher/bundle.dart @@ -196,7 +196,7 @@ String _resolveStringFromData(ByteData data) { class NetworkAssetBundle extends AssetBundle { /// Creates an network asset bundle that resolves asset keys as URLs relative /// to the given base URL. - NetworkAssetBundle(Uri baseUrl, {int? contextId, Map? additionalHttpHeaders }) + NetworkAssetBundle(Uri baseUrl, {this.contextId, Map? additionalHttpHeaders }) : _baseUrl = baseUrl, _additionalHttpHeaders = additionalHttpHeaders, httpClient = HttpClient(); From d5885820396a55f71d6e4a491f046e5793c3fa1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Tue, 8 Mar 2022 16:55:04 +0800 Subject: [PATCH 2/2] test: add test for cache. --- kraken/lib/src/launcher/bundle.dart | 2 +- kraken/test/kraken_test.dart | 6 ++++++ kraken/test/src/launcher/bundle.dart | 23 +++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 kraken/test/src/launcher/bundle.dart diff --git a/kraken/lib/src/launcher/bundle.dart b/kraken/lib/src/launcher/bundle.dart index 53775d16c9..128b115d4b 100644 --- a/kraken/lib/src/launcher/bundle.dart +++ b/kraken/lib/src/launcher/bundle.dart @@ -201,7 +201,7 @@ class NetworkAssetBundle extends AssetBundle { _additionalHttpHeaders = additionalHttpHeaders, httpClient = HttpClient(); - int? contextId; + final int? contextId; final Uri _baseUrl; final HttpClient httpClient; final Map? _additionalHttpHeaders; diff --git a/kraken/test/kraken_test.dart b/kraken/test/kraken_test.dart index edffcde954..5f9157d8cd 100644 --- a/kraken/test/kraken_test.dart +++ b/kraken/test/kraken_test.dart @@ -21,6 +21,8 @@ import 'src/css/values.dart' as css_values; import 'src/gesture/scroll_physics.dart' as scroll_physics; +import 'src/launcher/bundle.dart' as bundle; + // The main entry for kraken unit test. // Setup all common logic. void main() { @@ -64,6 +66,10 @@ void main() { scroll_physics.main(); }); + group('launcher', () { + bundle.main(); + }); + tearDownAll(() { if (tempDirectory.existsSync()) { tempDirectory.deleteSync(recursive: true); diff --git a/kraken/test/src/launcher/bundle.dart b/kraken/test/src/launcher/bundle.dart new file mode 100644 index 0000000000..dbef939925 --- /dev/null +++ b/kraken/test/src/launcher/bundle.dart @@ -0,0 +1,23 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:kraken/launcher.dart'; +import 'package:test/test.dart'; + +import '../../local_http_server.dart'; + +void main() { + var server = LocalHttpServer.getInstance(); + + group('Bundle', () { + test('NetworkAssetsBundle basic', () async { + Uri uri = server.getUri('js_over_128k'); + // Using contextId to active cache. + var bundle = NetworkAssetBundle(uri, contextId: 1); + ByteData data = await bundle.load(uri.toString()); + var code = utf8.decode(data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes)); + + expect(code.length > 128 * 1024, true); + }); + }); +}