TF-123 Implement caching mailbox when get all mailbox

This commit is contained in:
dab246
2021-09-28 15:05:24 +07:00
committed by Dat H. Pham
parent b8b3cf0db0
commit 8f5171d581
21 changed files with 438 additions and 61 deletions
@@ -3,10 +3,16 @@ import 'dart:async';
import 'package:jmap_dart_client/http/http_client.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
import 'package:jmap_dart_client/jmap/core/request/reference_path.dart';
import 'package:jmap_dart_client/jmap/core/state.dart';
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:jmap_dart_client/jmap/jmap_request.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/changes/changes_mailbox_method.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/changes/changes_mailbox_response.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/get/get_mailbox_method.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/get/get_mailbox_response.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart';
class MailboxAPI {
@@ -14,7 +20,7 @@ class MailboxAPI {
MailboxAPI(this.httpClient);
Future<List<Mailbox>> getAllMailbox(AccountId accountId, {Properties? properties}) async {
Future<GetMailboxResponse?> getAllMailbox(AccountId accountId, {Properties? properties}) async {
final processingInvocation = ProcessingInvocation();
final jmapRequestBuilder = JmapRequestBuilder(httpClient, processingInvocation);
@@ -32,6 +38,66 @@ class MailboxAPI {
queryInvocation.methodCallId,
GetMailboxResponse.deserialize);
return resultCreated == null ? [] : resultCreated.list;
return resultCreated;
}
Future<MailboxChangeResponse> getChanges(AccountId accountId, State sinceState) async {
final processingInvocation = ProcessingInvocation();
final jmapRequestBuilder = JmapRequestBuilder(httpClient, processingInvocation);
final changesMailboxMethod = ChangesMailboxMethod(accountId, sinceState, maxChanges: UnsignedInt(128));
final changesMailboxInvocation = jmapRequestBuilder.invocation(changesMailboxMethod);
final getMailboxUpdated = GetMailboxMethod(accountId)
..addReferenceIds(processingInvocation.createResultReference(
changesMailboxInvocation.methodCallId,
ReferencePath.updatedPath))
..addReferenceProperties(processingInvocation.createResultReference(
changesMailboxInvocation.methodCallId,
ReferencePath.updatedPropertiesPath));
final getMailboxCreated = GetMailboxMethod(accountId)
..addReferenceIds(processingInvocation.createResultReference(
changesMailboxInvocation.methodCallId,
ReferencePath.createdPath));
final getMailboxUpdatedInvocation = jmapRequestBuilder.invocation(getMailboxUpdated);
final getMailboxCreatedInvocation = jmapRequestBuilder.invocation(getMailboxCreated);
final result = await (jmapRequestBuilder
..usings(getMailboxCreated.requiredCapabilities))
.build()
.execute();
final resultChanges = result.parse<ChangesMailboxResponse>(
changesMailboxInvocation.methodCallId,
ChangesMailboxResponse.deserialize);
final resultUpdated = result.parse<GetMailboxResponse>(
getMailboxUpdatedInvocation.methodCallId,
GetMailboxResponse.deserialize);
final resultCreated = result.parse<GetMailboxResponse>(
getMailboxCreatedInvocation.methodCallId,
GetMailboxResponse.deserialize);
final listMailboxIdDestroyed = resultChanges?.destroyed.map((id) => MailboxId(id)).toList() ?? <MailboxId>[];
final updatedProperties = resultChanges?.updatedProperties;
final listMailboxUpdated = resultUpdated?.list ?? <Mailbox>[];
final listMailboxCreated = resultCreated?.list ?? <Mailbox>[];
final newState = resultChanges?.newState;
return MailboxChangeResponse(
updated: listMailboxUpdated,
created: listMailboxCreated,
destroyed: listMailboxIdDestroyed,
newState: newState,
updatedProperties: updatedProperties);
}
}
@@ -0,0 +1,105 @@
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/caching/mailbox_cache_client.dart';
import 'package:tmail_ui_user/features/caching/state_cache_client.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_cache_response.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart';
class MailboxCacheManager {
final MailboxCacheClient _mailboxCacheClient;
final StateCacheClient _stateCacheClient;
MailboxCacheManager(this._mailboxCacheClient, this._stateCacheClient);
Future<MailboxCacheResponse> getAllMailbox() async {
return await Future.wait(
[
_stateCacheClient.getItem(StateType.mailbox.value),
_mailboxCacheClient.getListItem()
],
eagerError: true
).then((List responses) {
return MailboxCacheResponse(mailboxCaches: responses.last, oldState: responses.first);
});
}
Future<MailboxChangeResponse> combineMailboxCache(MailboxChangeResponse mailboxChangeResponse, List<Mailbox> mailboxList) async {
final mailboxUpdated = mailboxChangeResponse.updated;
final updatedProperties = mailboxChangeResponse.updatedProperties;
if (mailboxUpdated != null && mailboxUpdated.isNotEmpty) {
final newListMailboxUpdated = mailboxUpdated.map((mailboxUpdated) {
if (updatedProperties == null) {
return mailboxUpdated;
} else {
final mailboxOld = findMailbox(mailboxUpdated.id, mailboxList);
if (mailboxOld != null) {
return mailboxOld.combineMailbox(mailboxUpdated, updatedProperties);
} else {
return mailboxUpdated;
}
}
}).toList();
final newMailboxChangeResponse = MailboxChangeResponse(
created: mailboxChangeResponse.created,
destroyed: mailboxChangeResponse.destroyed,
updated: newListMailboxUpdated,
newState: mailboxChangeResponse.newState,
updatedProperties: mailboxChangeResponse.updatedProperties
);
return newMailboxChangeResponse;
}
return mailboxChangeResponse;
}
Mailbox? findMailbox(MailboxId mailboxId, List<Mailbox> mailboxList) {
try {
return mailboxList.firstWhere((element) => element.id == mailboxId);
} catch (e) {
return null;
}
}
Future<void> asyncUpdateCache(MailboxChangeResponse mailboxChangeResponse) async {
if (mailboxChangeResponse.newState != null) {
final stateCacheExist = await _stateCacheClient.isExistTable();
if (stateCacheExist) {
_stateCacheClient.updateItem(
StateType.mailbox.value,
mailboxChangeResponse.newState!.toStateDao(StateType.mailbox));
} else {
_stateCacheClient.insertItem(
StateType.mailbox.value,
mailboxChangeResponse.newState!.toStateDao(StateType.mailbox));
}
}
final mailboxCacheExist = await _mailboxCacheClient.isExistTable();
if (mailboxCacheExist) {
final updatedCacheMailboxes = mailboxChangeResponse.updated
?.map((mailbox) => mailbox.toMailboxCache())
.toList() ?? <MailboxCache>[];
final createdCacheMailboxes = mailboxChangeResponse.created
?.map((mailbox) => mailbox.toMailboxCache())
.toList() ?? <MailboxCache>[];
final destroyedCacheMailboxes = mailboxChangeResponse.destroyed
?.map((mailboxId) => mailboxId.id.value)
.toList() ?? <String>[];
await Future.wait([
_mailboxCacheClient.updateMultipleItem(updatedCacheMailboxes.toMap()),
_mailboxCacheClient.insertMultipleItem(createdCacheMailboxes.toMap()),
_mailboxCacheClient.deleteMultipleItem(destroyedCacheMailboxes)
]);
} else {
final createdCacheMailboxes = mailboxChangeResponse.created
?.map((mailbox) => mailbox.toMailboxCache())
.toList() ?? <MailboxCache>[];
await _mailboxCacheClient.insertMultipleItem(createdCacheMailboxes.toMap());
}
}
}