diff --git a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart index 48e563dc..9d2cb955 100644 --- a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart +++ b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart @@ -1,7 +1,5 @@ import 'package:flutter/foundation.dart'; -import 'package:mutex/mutex.dart'; import 'package:stream_chat/stream_chat.dart'; - import 'package:stream_chat_persistence/src/db/drift_chat_database.dart'; /// Various connection modes on which [StreamChatPersistenceClient] can work @@ -48,7 +46,6 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { final Logger _logger; final ConnectionMode _connectionMode; final bool _webUseIndexedDbIfSupported; - final _mutex = ReadWriteMutex(); void _defaultLogHandler(LogRecord record) { print( @@ -59,9 +56,6 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { if (record.stackTrace != null) print(record.stackTrace); } - Future _readProtected(AsyncValueGetter func) => - _mutex.protectRead(func); - bool get _debugIsConnected { assert(() { if (db == null) { @@ -104,90 +98,84 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { Future getConnectionInfo() { assert(_debugIsConnected, ''); _logger.info('getConnectionInfo'); - return _readProtected(() => db!.connectionEventDao.connectionEvent); + return db!.connectionEventDao.connectionEvent; } @override Future updateConnectionInfo(Event event) { assert(_debugIsConnected, ''); _logger.info('updateConnectionInfo'); - return _readProtected( - () => db!.connectionEventDao.updateConnectionEvent(event), - ); + return db!.connectionEventDao.updateConnectionEvent(event); } @override Future updateLastSyncAt(DateTime lastSyncAt) { assert(_debugIsConnected, ''); _logger.info('updateLastSyncAt'); - return _readProtected( - () => db!.connectionEventDao.updateLastSyncAt(lastSyncAt), - ); + return db!.connectionEventDao.updateLastSyncAt(lastSyncAt); } @override Future getLastSyncAt() { assert(_debugIsConnected, ''); _logger.info('getLastSyncAt'); - return _readProtected(() => db!.connectionEventDao.lastSyncAt); + return db!.connectionEventDao.lastSyncAt; } @override Future deleteChannels(List cids) { assert(_debugIsConnected, ''); _logger.info('deleteChannels'); - return _readProtected(() => db!.channelDao.deleteChannelByCids(cids)); + return db!.channelDao.deleteChannelByCids(cids); } @override Future> getChannelCids() { assert(_debugIsConnected, ''); _logger.info('getChannelCids'); - return _readProtected(() => db!.channelDao.cids); + return db!.channelDao.cids; } @override Future deleteMessageByIds(List messageIds) { assert(_debugIsConnected, ''); _logger.info('deleteMessageByIds'); - return _readProtected(() => db!.messageDao.deleteMessageByIds(messageIds)); + return db!.messageDao.deleteMessageByIds(messageIds); } @override Future deletePinnedMessageByIds(List messageIds) { assert(_debugIsConnected, ''); _logger.info('deletePinnedMessageByIds'); - return _readProtected( - () => db!.pinnedMessageDao.deleteMessageByIds(messageIds), - ); + return db!.pinnedMessageDao.deleteMessageByIds(messageIds); } @override Future deleteMessageByCids(List cids) { assert(_debugIsConnected, ''); _logger.info('deleteMessageByCids'); - return _readProtected(() => db!.messageDao.deleteMessageByCids(cids)); + return db!.messageDao.deleteMessageByCids(cids); } @override Future deletePinnedMessageByCids(List cids) { assert(_debugIsConnected, ''); _logger.info('deletePinnedMessageByCids'); - return _readProtected(() => db!.pinnedMessageDao.deleteMessageByCids(cids)); + return db!.pinnedMessageDao.deleteMessageByCids(cids); } @override Future> getMembersByCid(String cid) { assert(_debugIsConnected, ''); _logger.info('getMembersByCid'); - return _readProtected(() => db!.memberDao.getMembersByCid(cid)); + return db!.memberDao.getMembersByCid(cid); } @override Future getChannelByCid(String cid) { assert(_debugIsConnected, ''); _logger.info('getChannelByCid'); - return _readProtected(() => db!.channelDao.getChannelByCid(cid)); + return db!.channelDao.getChannelByCid(cid); } @override @@ -197,11 +185,9 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { }) { assert(_debugIsConnected, ''); _logger.info('getMessagesByCid'); - return _readProtected( - () => db!.messageDao.getMessagesByCid( - cid, - messagePagination: messagePagination, - ), + return db!.messageDao.getMessagesByCid( + cid, + messagePagination: messagePagination, ); } @@ -212,37 +198,34 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { }) { assert(_debugIsConnected, ''); _logger.info('getPinnedMessagesByCid'); - return _readProtected( - () => db!.pinnedMessageDao.getMessagesByCid( - cid, - messagePagination: messagePagination, - ), + return db!.pinnedMessageDao.getMessagesByCid( + cid, + messagePagination: messagePagination, ); } @override - Future> getReadsByCid(String cid) { + Future> getReadsByCid(String cid) async { assert(_debugIsConnected, ''); _logger.info('getReadsByCid'); - return _readProtected(() => db!.readDao.getReadsByCid(cid)); + return db!.readDao.getReadsByCid(cid); } @override - Future>> getChannelThreads(String cid) { + Future>> getChannelThreads(String cid) async { assert(_debugIsConnected, ''); _logger.info('getChannelThreads'); - return _readProtected(() async { - final messages = await db!.messageDao.getThreadMessages(cid); - final messageByParentIdDictionary = >{}; - for (final message in messages) { - final parentId = message.parentId!; - messageByParentIdDictionary[parentId] = [ - ...messageByParentIdDictionary[parentId] ?? [], - message, - ]; - } - return messageByParentIdDictionary; - }); + final messages = await db!.messageDao.getThreadMessages(cid); + final messageByParentIdDictionary = >{}; + for (final message in messages) { + final parentId = message.parentId!; + messageByParentIdDictionary[parentId] = [ + ...messageByParentIdDictionary[parentId] ?? [], + message, + ]; + } + + return messageByParentIdDictionary; } @override @@ -252,11 +235,9 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { }) { assert(_debugIsConnected, ''); _logger.info('getReplies'); - return _readProtected( - () => db!.messageDao.getThreadMessagesByParentId( - parentId, - options: options, - ), + return db!.messageDao.getThreadMessagesByParentId( + parentId, + options: options, ); } @@ -268,73 +249,69 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { Please use channelStateSort instead.''') List>? sort, List>? channelStateSort, PaginationParams? paginationParams, - }) { + }) async { assert(_debugIsConnected, ''); assert( sort == null || channelStateSort == null, 'sort and channelStateSort cannot be used together', ); _logger.info('getChannelStates'); - return _readProtected( - () async { - final channels = await db!.channelQueryDao.getChannels( - filter: filter, - sort: sort, - ); - final channelStates = await Future.wait( - channels.map((e) => getChannelStateByCid(e.cid)), - ); - - // Only sort the channel states if the channels are not already sorted. - if (sort == null) { - var chainedComparator = (ChannelState a, ChannelState b) { - final dateA = a.channel?.lastMessageAt ?? a.channel?.createdAt; - final dateB = b.channel?.lastMessageAt ?? b.channel?.createdAt; - - if (dateA == null && dateB == null) { - return 0; - } else if (dateA == null) { - return 1; - } else if (dateB == null) { - return -1; - } else { - return dateB.compareTo(dateA); - } - }; - - if (channelStateSort != null && channelStateSort.isNotEmpty) { - chainedComparator = (a, b) { - int result; - for (final comparator in channelStateSort - .map((it) => it.comparator) - .withNullifyer) { - try { - result = comparator(a, b); - } catch (e) { - result = 0; - } - if (result != 0) return result; - } - return 0; - }; - } - - channelStates.sort(chainedComparator); - } - - final offset = paginationParams?.offset; - if (offset != null && offset > 0 && channelStates.isNotEmpty) { - channelStates.removeRange(0, offset); - } - - if (paginationParams?.limit != null) { - return channelStates.take(paginationParams!.limit).toList(); - } - - return channelStates; - }, + final channels = await db!.channelQueryDao.getChannels( + filter: filter, + sort: sort, ); + + final channelStates = await Future.wait( + channels.map((e) => getChannelStateByCid(e.cid)), + ); + + // Only sort the channel states if the channels are not already sorted. + if (sort == null) { + var chainedComparator = (ChannelState a, ChannelState b) { + final dateA = a.channel?.lastMessageAt ?? a.channel?.createdAt; + final dateB = b.channel?.lastMessageAt ?? b.channel?.createdAt; + + if (dateA == null && dateB == null) { + return 0; + } else if (dateA == null) { + return 1; + } else if (dateB == null) { + return -1; + } else { + return dateB.compareTo(dateA); + } + }; + + if (channelStateSort != null && channelStateSort.isNotEmpty) { + chainedComparator = (a, b) { + int result; + for (final comparator + in channelStateSort.map((it) => it.comparator).withNullifyer) { + try { + result = comparator(a, b); + } catch (e) { + result = 0; + } + if (result != 0) return result; + } + return 0; + }; + } + + channelStates.sort(chainedComparator); + } + + final offset = paginationParams?.offset; + if (offset != null && offset > 0 && channelStates.isNotEmpty) { + channelStates.removeRange(0, offset); + } + + if (paginationParams?.limit != null) { + return channelStates.take(paginationParams!.limit).toList(); + } + + return channelStates; } @override @@ -345,12 +322,10 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { }) { assert(_debugIsConnected, ''); _logger.info('updateChannelQueries'); - return _readProtected( - () => db!.channelQueryDao.updateChannelQueries( - filter, - cids, - clearQueryCache: clearQueryCache, - ), + return db!.channelQueryDao.updateChannelQueries( + filter, + cids, + clearQueryCache: clearQueryCache, ); } @@ -358,60 +333,56 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { Future updateChannels(List channels) { assert(_debugIsConnected, ''); _logger.info('updateChannels'); - return _readProtected(() => db!.channelDao.updateChannels(channels)); + return db!.channelDao.updateChannels(channels); } @override Future bulkUpdateMembers(Map?> members) { assert(_debugIsConnected, ''); _logger.info('bulkUpdateMembers'); - return _readProtected(() => db!.memberDao.bulkUpdateMembers(members)); + return db!.memberDao.bulkUpdateMembers(members); } @override Future bulkUpdateMessages(Map?> messages) { assert(_debugIsConnected, ''); _logger.info('bulkUpdateMessages'); - return _readProtected(() => db!.messageDao.bulkUpdateMessages(messages)); + return db!.messageDao.bulkUpdateMessages(messages); } @override Future bulkUpdatePinnedMessages(Map?> messages) { assert(_debugIsConnected, ''); _logger.info('bulkUpdatePinnedMessages'); - return _readProtected( - () => db!.pinnedMessageDao.bulkUpdateMessages(messages), - ); + return db!.pinnedMessageDao.bulkUpdateMessages(messages); } @override Future updatePinnedMessageReactions(List reactions) { assert(_debugIsConnected, ''); _logger.info('updatePinnedMessageReactions'); - return _readProtected( - () => db!.pinnedMessageReactionDao.updateReactions(reactions), - ); + return db!.pinnedMessageReactionDao.updateReactions(reactions); } @override Future updateReactions(List reactions) { assert(_debugIsConnected, ''); _logger.info('updateReactions'); - return _readProtected(() => db!.reactionDao.updateReactions(reactions)); + return db!.reactionDao.updateReactions(reactions); } @override Future bulkUpdateReads(Map?> reads) { assert(_debugIsConnected, ''); _logger.info('bulkUpdateReads'); - return _readProtected(() => db!.readDao.bulkUpdateReads(reads)); + return db!.readDao.bulkUpdateReads(reads); } @override Future updateUsers(List users) { assert(_debugIsConnected, ''); _logger.info('updateUsers'); - return _readProtected(() => db!.userDao.updateUsers(users)); + return db!.userDao.updateUsers(users); } @override @@ -420,53 +391,51 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { ) { assert(_debugIsConnected, ''); _logger.info('deletePinnedMessageReactionsByMessageId'); - return _readProtected( - () => - db!.pinnedMessageReactionDao.deleteReactionsByMessageIds(messageIds), - ); + return db!.pinnedMessageReactionDao.deleteReactionsByMessageIds(messageIds); } @override Future deleteReactionsByMessageId(List messageIds) { assert(_debugIsConnected, ''); _logger.info('deleteReactionsByMessageId'); - return _readProtected( - () => db!.reactionDao.deleteReactionsByMessageIds(messageIds), - ); + return db!.reactionDao.deleteReactionsByMessageIds(messageIds); } @override Future deleteMembersByCids(List cids) { assert(_debugIsConnected, ''); _logger.info('deleteMembersByCids'); - return _readProtected(() => db!.memberDao.deleteMemberByCids(cids)); + return db!.memberDao.deleteMemberByCids(cids); + } + + @override + Future updateChannelThreads( + String cid, + Map> threads, + ) { + assert(_debugIsConnected, ''); + _logger.info('updateChannelThreads'); + return db!.transaction(() => super.updateChannelThreads(cid, threads)); } @override Future updateChannelStates(List channelStates) { assert(_debugIsConnected, ''); _logger.info('updateChannelStates'); - return _readProtected( - () async => db!.transaction( - () async { - await super.updateChannelStates(channelStates); - }, - ), - ); + return db!.transaction(() => super.updateChannelStates(channelStates)); } @override - Future disconnect({bool flush = false}) async => - _mutex.protectWrite(() async { - _logger.info('disconnect'); - if (db != null) { - _logger.info('Disconnecting'); - if (flush) { - _logger.info('Flushing'); - await db!.flush(); - } - await db!.disconnect(); - db = null; - } - }); + Future disconnect({bool flush = false}) async { + _logger.info('disconnect'); + if (db != null) { + _logger.info('Disconnecting'); + if (flush) { + _logger.info('Flushing'); + await db!.flush(); + } + await db!.disconnect(); + db = null; + } + } } diff --git a/packages/stream_chat_persistence/pubspec.yaml b/packages/stream_chat_persistence/pubspec.yaml index 23275396..83fa7a11 100644 --- a/packages/stream_chat_persistence/pubspec.yaml +++ b/packages/stream_chat_persistence/pubspec.yaml @@ -15,7 +15,6 @@ dependencies: sdk: flutter logging: ^1.0.1 meta: ^1.8.0 - mutex: ^3.0.0 path: ^1.8.2 path_provider: ^2.0.1 sqlite3_flutter_libs: ^0.5.0