LCOV - code coverage report
Current view: top level - async-2.5.0/lib/src - async_cache.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 24 0.0 %
Date: 2021-11-28 14:37:50 Functions: 0 0 -

          Line data    Source code
       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             : 
       7             : import 'package:async/async.dart';
       8             : 
       9             : /// Runs asynchronous functions and caches the result for a period of time.
      10             : ///
      11             : /// This class exists to cover the pattern of having potentially expensive code
      12             : /// such as file I/O, network access, or isolate computation that's unlikely to
      13             : /// change quickly run fewer times. For example:
      14             : ///
      15             : /// ```dart
      16             : /// final _usersCache = new AsyncCache<List<String>>(const Duration(hours: 1));
      17             : ///
      18             : /// /// Uses the cache if it exists, otherwise calls the closure:
      19             : /// Future<List<String>> get onlineUsers => _usersCache.fetch(() {
      20             : ///   // Actually fetch online users here.
      21             : /// });
      22             : /// ```
      23             : ///
      24             : /// This class's timing can be mocked using [`fake_async`][fake_async].
      25             : ///
      26             : /// [fake_async]: https://pub.dev/packages/fake_async
      27             : class AsyncCache<T> {
      28             :   /// How long cached values stay fresh.
      29             :   final Duration _duration;
      30             : 
      31             :   /// Cached results of a previous [fetchStream] call.
      32             :   StreamSplitter<T>? _cachedStreamSplitter;
      33             : 
      34             :   /// Cached results of a previous [fetch] call.
      35             :   Future<T>? _cachedValueFuture;
      36             : 
      37             :   /// Fires when the cache should be considered stale.
      38             :   Timer? _stale;
      39             : 
      40             :   /// Creates a cache that invalidates its contents after [duration] has passed.
      41             :   ///
      42             :   /// The [duration] starts counting after the Future returned by [fetch]
      43             :   /// completes, or after the Stream returned by [fetchStream] emits a done
      44             :   /// event.
      45           0 :   AsyncCache(this._duration);
      46             : 
      47             :   /// Creates a cache that invalidates after an in-flight request is complete.
      48             :   ///
      49             :   /// An ephemeral cache guarantees that a callback function will only be
      50             :   /// executed at most once concurrently. This is useful for requests for which
      51             :   /// data is updated frequently but stale data is acceptable.
      52           0 :   factory AsyncCache.ephemeral() => AsyncCache(Duration.zero);
      53             : 
      54             :   /// Returns a cached value from a previous call to [fetch], or runs [callback]
      55             :   /// to compute a new one.
      56             :   ///
      57             :   /// If [fetch] has been called recently enough, returns its previous return
      58             :   /// value. Otherwise, runs [callback] and returns its new return value.
      59           0 :   Future<T> fetch(Future<T> Function() callback) async {
      60           0 :     if (_cachedStreamSplitter != null) {
      61           0 :       throw StateError('Previously used to cache via `fetchStream`');
      62             :     }
      63           0 :     final result = _cachedValueFuture ??= callback();
      64             :     try {
      65           0 :       return await result;
      66             :     } finally {
      67           0 :       _startStaleTimer();
      68             :     }
      69             :   }
      70             : 
      71             :   /// Returns a cached stream from a previous call to [fetchStream], or runs
      72             :   /// [callback] to compute a new stream.
      73             :   ///
      74             :   /// If [fetchStream] has been called recently enough, returns a copy of its
      75             :   /// previous return value. Otherwise, runs [callback] and returns its new
      76             :   /// return value.
      77           0 :   Stream<T> fetchStream(Stream<T> Function() callback) {
      78           0 :     if (_cachedValueFuture != null) {
      79           0 :       throw StateError('Previously used to cache via `fetch`');
      80             :     }
      81           0 :     var splitter = _cachedStreamSplitter ??= StreamSplitter(
      82           0 :         callback().transform(StreamTransformer.fromHandlers(handleDone: (sink) {
      83           0 :       _startStaleTimer();
      84           0 :       sink.close();
      85             :     })));
      86           0 :     return splitter.split();
      87             :   }
      88             : 
      89             :   /// Removes any cached value.
      90           0 :   void invalidate() {
      91             :     // TODO: This does not return a future, but probably should.
      92           0 :     _cachedValueFuture = null;
      93             :     // TODO: This does not await, but probably should.
      94           0 :     _cachedStreamSplitter?.close();
      95           0 :     _cachedStreamSplitter = null;
      96           0 :     _stale?.cancel();
      97           0 :     _stale = null;
      98             :   }
      99             : 
     100           0 :   void _startStaleTimer() {
     101           0 :     _stale = Timer(_duration, invalidate);
     102             :   }
     103             : }

Generated by: LCOV version 1.14