Skip to content

Commit

Permalink
perf: use hive_ce for caching
Browse files Browse the repository at this point in the history
Better caching between cold starts, once again
  • Loading branch information
SlayerOrnstein committed Nov 16, 2024
1 parent e356385 commit c147175
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 24 deletions.
2 changes: 2 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ analyzer:
- lib/firebase_options.dart
- lib/router/routes.g.dart
- packages/navis_ui/lib/src/icons/warframe_symbols.dart
- packages/warframestat_repository/lib/hive_registrar.g.dart

This comment has been minimized.

Copy link
@Rexios80

Rexios80 Dec 3, 2024

Hello! I am the maintainer of Hive CE doing rounds to see how people are using my package.

Excluding files from analysis is dangerous. This disables all analysis, not just lint warnings, which means you can end up with broken code, and the analyzer won't tell you about it.

It is better to add lint ignores to the build.yaml config as specified in this documentation: https://pub.dev/packages/source_gen#configuring-combining_builder

This comment has been minimized.

Copy link
@SlayerOrnstein

SlayerOrnstein Dec 3, 2024

Author Member

Oh thanks for that

- packages/warframestat_repository/lib/src/cache_client.g.dart

linter:
rules:
Expand Down
1 change: 0 additions & 1 deletion packages/warframestat_repository/analysis_options.yaml

This file was deleted.

8 changes: 8 additions & 0 deletions packages/warframestat_repository/lib/hive_registrar.g.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import 'package:hive_ce/hive.dart';
import 'package:warframestat_repository/src/cache_client.dart';

extension HiveRegistrar on HiveInterface {
void registerAdapters() {
registerAdapter(HiveCacheItemAdapter());
}
}
32 changes: 25 additions & 7 deletions packages/warframestat_repository/lib/src/cache_client.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import 'dart:async';
import 'dart:typed_data';

import 'package:hive_ce/hive.dart';
import 'package:http/http.dart';

part 'cache_client.g.dart';

///
typedef CachedItem = ({DateTime timestamp, Uint8List data});

Expand All @@ -11,32 +14,34 @@ typedef CachedItem = ({DateTime timestamp, Uint8List data});
/// {@endtemplate}
class CacheClient extends BaseClient {
/// {@macro cache_client}
CacheClient({required this.cacheTime, Client? client})
CacheClient({required this.cacheTime, required this.cacheBox, Client? client})
: _inner = client ?? Client();

/// When the response should be considered invalid
final Duration cacheTime;

final Client _inner;
final Box<HiveCacheItem> cacheBox;

final Map<String, CachedItem> _cache = {};
final Client _inner;

@override
Future<StreamedResponse> send(BaseRequest request) async {
if (request.method != 'GET') return _inner.send(request);

final now = DateTime.timestamp();
final cached = _cache[request.url.toString()];
final cached = cacheBox.get(request.url.toString());

if (cached != null && now.isBefore(cached.timestamp)) {
if (cached != null && cached.isExpired) {
return StreamedResponse(Stream.value(cached.data), 200);
}

final response = await _inner.send(request);
final body = await response.stream.toBytes();

_cache[request.url.toString()] =
(timestamp: now.add(cacheTime), data: body);
await cacheBox.put(
request.url.toString(),
HiveCacheItem(body, now.add(cacheTime)),
);

return response.copy(Stream.value(body));
}
Expand All @@ -56,3 +61,16 @@ extension on StreamedResponse {
);
}
}

@HiveType(typeId: 0)
class HiveCacheItem extends HiveObject {
HiveCacheItem(this.data, this.expiry);

@HiveField(0)
final Uint8List data;

@HiveField(1)
final DateTime expiry;

bool get isExpired => expiry.isAfter(DateTime.timestamp());
}
44 changes: 44 additions & 0 deletions packages/warframestat_repository/lib/src/cache_client.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 24 additions & 11 deletions packages/warframestat_repository/lib/src/repository.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import 'dart:io';

import 'package:collection/collection.dart';
import 'package:hive_ce/hive.dart';
import 'package:http/http.dart';
import 'package:warframestat_client/warframestat_client.dart';
import 'package:warframestat_repository/hive_registrar.g.dart';
import 'package:warframestat_repository/src/cache_client.dart';

///
Expand All @@ -11,30 +15,39 @@ const userAgent = 'navis';
/// {@endtemplate}
class WarframestatRepository {
/// {@macro warframestat_repository}
WarframestatRepository({Client? client}) : _client = client ?? Client();
WarframestatRepository({Client? client}) : _client = client ?? Client() {
Hive.registerAdapters();
}

final Client _client;

/// The locale request will be made for
Language language = Language.en;

final _cacheClients = <Duration, CacheClient>{};
CacheClient _cacheClient(Duration cacheTime) {
Future<CacheClient> _cacheClient(Duration cacheTime) async {
Hive.init(Directory.systemTemp.absolute.path);

// Hive will return the same box if it's already opened
final cache =
await Hive.openBox<HiveCacheItem>('warframestat_repository_cache');

if (_cacheClients.containsKey(cacheTime)) return _cacheClients[cacheTime]!;

_cacheClients[cacheTime] = CacheClient(
cacheTime: cacheTime,
client: _client,
cacheBox: cache,
);

return _cacheClients[cacheTime]!;
}

/// Get the current worldstate
Future<Worldstate> fetchWorldstate() {
Future<Worldstate> fetchWorldstate() async {
const cacheTime = Duration(seconds: 60);
final client = WorldstateClient(
client: _cacheClient(cacheTime),
client: await _cacheClient(cacheTime),
ua: userAgent,
language: language,
);
Expand All @@ -46,10 +59,10 @@ class WarframestatRepository {
///
/// I doubt the list will be updated since DE doesn't really add much on their
/// end so caching for even a year is perfectly fine
Future<List<SynthTarget>> fetchTargets() {
Future<List<SynthTarget>> fetchTargets() async {
const cacheTime = Duration(days: 30);
final client = SynthTaretClient(
client: _cacheClient(cacheTime),
client: await _cacheClient(cacheTime),
ua: userAgent,
language: language,
);
Expand All @@ -62,7 +75,7 @@ class WarframestatRepository {
Future<MinimalItem?> fetchDealInfo(String uniqueName, String name) async {
const cacheTime = Duration(minutes: 30);
final client = WarframeItemsClient(
client: _cacheClient(cacheTime),
client: await _cacheClient(cacheTime),
ua: userAgent,
language: language,
);
Expand All @@ -81,10 +94,10 @@ class WarframestatRepository {
}

/// Search warframe-items
Future<List<MinimalItem>> searchItems(String query) {
Future<List<MinimalItem>> searchItems(String query) async {
const cacheTime = Duration(minutes: 5);
final client = WarframeItemsClient(
client: _cacheClient(cacheTime),
client: await _cacheClient(cacheTime),
ua: userAgent,
language: language,
);
Expand All @@ -93,10 +106,10 @@ class WarframestatRepository {
}

/// Get one item based on unique name
Future<Item> fetchItem(String uniqueName) {
Future<Item> fetchItem(String uniqueName) async {
const cacheTime = Duration(minutes: 5);
final client = WarframeItemsClient(
client: _cacheClient(cacheTime),
client: await _cacheClient(cacheTime),
ua: userAgent,
language: language,
);
Expand Down
5 changes: 3 additions & 2 deletions packages/warframestat_repository/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ environment:

dependencies:
collection: ^1.18.0
hive: ^2.2.3
hive_ce: ^2.7.0+1
http: ^1.2.1
warframestat_client: ^3.8.11

dev_dependencies:
build_runner: ^2.4.13
hive_ce_generator: ^1.7.0
mocktail: ^1.0.3
path: ^1.9.0
test: ^1.25.2
very_good_analysis: ^5.1.0
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'dart:convert' hide json;
import 'dart:io';

import 'package:hive/hive.dart';
import 'package:hive_ce/hive.dart';
import 'package:http/http.dart';
import 'package:mocktail/mocktail.dart';
import 'package:test/test.dart';
Expand Down
12 changes: 10 additions & 2 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.3"
hive_ce:
dependency: transitive
description:
name: hive_ce
sha256: ab1b79ce8d479cd3a8f9b90fe70219f368ca846f86eb4a1e84f4f11483cef65f
url: "https://pub.dev"
source: hosted
version: "2.7.0+1"
hive_flutter:
dependency: "direct main"
description:
Expand All @@ -717,10 +725,10 @@ packages:
dependency: transitive
description:
name: html
sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"
sha256: "1fc58edeaec4307368c60d59b7e15b9d658b57d7f3125098b6294153c75337ec"
url: "https://pub.dev"
source: hosted
version: "0.15.4"
version: "0.15.5"
http:
dependency: transitive
description:
Expand Down

0 comments on commit c147175

Please sign in to comment.