Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: cache snap ratings for 24 hours #1843

Merged
merged 2 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading