Skip to content

Commit

Permalink
feat: cache snap ratings for 24 hours (#1843)
Browse files Browse the repository at this point in the history
UDENG-4934
  • Loading branch information
d-loose authored Oct 16, 2024
2 parents 6c80161 + 112e7ce commit bf32c5b
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 4 deletions.
7 changes: 7 additions & 0 deletions packages/app_center/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
targets:
$default:
builders:
json_serializable:
options:
any_map: true
explicit_to_json: true
4 changes: 4 additions & 0 deletions packages/app_center/lib/ratings/ratings_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:app_center_ratings_client/app_center_ratings_client.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

part 'ratings_data.freezed.dart';
part 'ratings_data.g.dart';

@freezed
class RatingsData with _$RatingsData {
Expand All @@ -12,4 +13,7 @@ class RatingsData with _$RatingsData {
required Rating? rating,
required VoteStatus? voteStatus,
}) = _RatingsData;

factory RatingsData.fromJson(Map<String, dynamic> json) =>
_$RatingsDataFromJson(json);
}
28 changes: 27 additions & 1 deletion packages/app_center/lib/ratings/ratings_model.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:app_center/providers/file_system_provider.dart';
import 'package:app_center/ratings/ratings_data.dart';
import 'package:app_center/ratings/ratings_service.dart';
import 'package:app_center/snapd/cache_file.dart';
import 'package:app_center/snapd/snap_model.dart';
import 'package:app_center_ratings_client/app_center_ratings_client.dart';
import 'package:clock/clock.dart';
Expand All @@ -17,6 +19,17 @@ class RatingsModel extends _$RatingsModel {
final snap = (await ref.watch(snapModelProvider(snapName).future)).snap;
final snapId = snap.id;

final cacheFile = _getCacheFile(snapId);

RatingsData? cachedRatingsData;
if (cacheFile.existsSync() && cacheFile.isValidSync()) {
cachedRatingsData = await cacheFile.readRatingsData();
}

if (cachedRatingsData != null) {
return cachedRatingsData;
}

final results = await Future.wait([
_ratings.getRating(snapId),
_ratings.getSnapVotes(snapId),
Expand All @@ -25,12 +38,15 @@ class RatingsModel extends _$RatingsModel {
final rating = results[0] as Rating;
final votes = results[1] as List<Vote>;

return RatingsData(
final ratingsData = RatingsData(
snapId: snapId,
snapRevision: snap.revision,
rating: rating,
voteStatus: _getUserVote(snap.revision, votes),
);

cacheFile.writeRatingsDataSync(ratingsData);
return ratingsData;
}

Future<void> castVote(VoteStatus voteStatus) async {
Expand All @@ -47,6 +63,8 @@ class RatingsModel extends _$RatingsModel {
);
await _ratings.vote(vote);
state = AsyncData(ratingsData.copyWith(voteStatus: voteStatus));
await _getCacheFile(ratingsData.snapId).deleteIfExists();
ref.invalidateSelf();
}
}

Expand All @@ -58,6 +76,14 @@ class RatingsModel extends _$RatingsModel {
}
return null;
}

CacheFile _getCacheFile(String snapId) {
return CacheFile.fromFileName(
'ratings-$snapId',
fileSystem: ref.read(fileSystemProvider),
expiry: const Duration(days: 1),
);
}
}

enum VoteStatus {
Expand Down
16 changes: 16 additions & 0 deletions packages/app_center/lib/snapd/cache_file.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:io';

import 'package:app_center/ratings/ratings_data.dart';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:flutter/services.dart';
Expand Down Expand Up @@ -92,13 +93,28 @@ class CacheFile {
.toList();
}

Future<void> deleteIfExists() async {
if (await _file.exists()) {
await _file.delete();
}
}

Future<void> writeSnap(Snap snap) => write(snap.toJson());

void writeSnapSync(Snap snap) => writeSync(snap.toJson());

void writeSnapListSync(List<Snap> snaps) {
return writeSync(snaps.map((snap) => snap.toJson()).toList());
}

Future<RatingsData?> readRatingsData() async {
final data = await read() as Map?;
return data != null ? RatingsData.fromJson(data.cast()) : null;
}

void writeRatingsDataSync(RatingsData ratingsData) {
return writeSync(ratingsData.toJson());
}
}

extension CacheObject on Object {
Expand Down
2 changes: 2 additions & 0 deletions packages/app_center/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ dependencies:
handy_window: ^0.4.0
http: ^1.2.2
intl: any
json_annotation: ^4.9.0
jwt_decode: ^0.3.1
meta: ^1.15.0
package_info_plus: ^8.0.2
Expand Down Expand Up @@ -64,6 +65,7 @@ dev_dependencies:
freezed: ^2.5.7
integration_test:
sdk: flutter
json_serializable: ^6.8.0
mockito: ^5.4.4
riverpod_generator: ^2.4.3
ubuntu_lints: ^0.4.0
Expand Down
7 changes: 7 additions & 0 deletions packages/app_center_ratings_client/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
targets:
$default:
builders:
json_serializable:
options:
any_map: true
explicit_to_json: true
4 changes: 3 additions & 1 deletion packages/app_center_ratings_client/lib/src/ratings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ import 'package:app_center_ratings_client/src/generated/ratings_features_common.
import 'package:freezed_annotation/freezed_annotation.dart';

part 'ratings.freezed.dart';
part 'ratings.g.dart';

@freezed
class Rating with _$Rating {
@JsonSerializable(explicitToJson: true)
const factory Rating({
required String snapId,
required int totalVotes,
required RatingsBand ratingsBand,
}) = _Rating;

factory Rating.fromJson(Map<String, dynamic> json) => _$RatingFromJson(json);
}

enum RatingsBand {
Expand Down
23 changes: 21 additions & 2 deletions packages/app_center_ratings_client/lib/src/ratings.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@ T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');

Rating _$RatingFromJson(Map<String, dynamic> json) {
return _Rating.fromJson(json);
}

/// @nodoc
mixin _$Rating {
String get snapId => throw _privateConstructorUsedError;
int get totalVotes => throw _privateConstructorUsedError;
RatingsBand get ratingsBand => throw _privateConstructorUsedError;

/// Serializes this Rating to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;

/// Create a copy of Rating
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
Expand Down Expand Up @@ -115,14 +122,16 @@ class __$$RatingImplCopyWithImpl<$Res>
}

/// @nodoc
@JsonSerializable(explicitToJson: true)
@JsonSerializable()
class _$RatingImpl implements _Rating {
const _$RatingImpl(
{required this.snapId,
required this.totalVotes,
required this.ratingsBand});

factory _$RatingImpl.fromJson(Map<String, dynamic> json) =>
_$$RatingImplFromJson(json);

@override
final String snapId;
@override
Expand All @@ -147,6 +156,7 @@ class _$RatingImpl implements _Rating {
other.ratingsBand == ratingsBand));
}

@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, snapId, totalVotes, ratingsBand);

Expand All @@ -157,6 +167,13 @@ class _$RatingImpl implements _Rating {
@pragma('vm:prefer-inline')
_$$RatingImplCopyWith<_$RatingImpl> get copyWith =>
__$$RatingImplCopyWithImpl<_$RatingImpl>(this, _$identity);

@override
Map<String, dynamic> toJson() {
return _$$RatingImplToJson(
this,
);
}
}

abstract class _Rating implements Rating {
Expand All @@ -165,6 +182,8 @@ abstract class _Rating implements Rating {
required final int totalVotes,
required final RatingsBand ratingsBand}) = _$RatingImpl;

factory _Rating.fromJson(Map<String, dynamic> json) = _$RatingImpl.fromJson;

@override
String get snapId;
@override
Expand Down
1 change: 1 addition & 0 deletions packages/app_center_ratings_client/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dependencies:

dev_dependencies:
build_runner: ^2.4.12
json_serializable: ^6.8.0
mockito: ^5.4.4
test: ^1.25.8
ubuntu_lints: ^0.4.0

0 comments on commit bf32c5b

Please sign in to comment.