Compare commits

..

No commits in common. "main" and "v0.5.2" have entirely different histories.
main ... v0.5.2

5 changed files with 7 additions and 62 deletions

View file

@ -1,9 +1,5 @@
# Changelog # Changelog
## 0.5.2
- Hotfix: Fixed an infinite loop involving delivery receipts
## 0.5.1 ## 0.5.1
- Improve: Show delivery and read receipt indicators for text messages - Improve: Show delivery and read receipt indicators for text messages

View file

@ -250,25 +250,6 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
null; null;
} }
/// Claims a new delivery-receipt attempt after [cooldown] has elapsed.
///
/// Updating the timestamp before sending prevents repeated server batches from
/// starting multiple delivery-receipt attempts during the same cooldown.
Future<bool> claimDuplicateReceiptResend(
String receiptId,
Duration cooldown,
) async {
final now = clock.now();
final updated =
await (update(receivedReceipts)..where(
(t) =>
t.receiptId.equals(receiptId) &
t.createdAt.isSmallerOrEqualValue(now.subtract(cooldown)),
))
.write(ReceivedReceiptsCompanion(createdAt: Value(now)));
return updated > 0;
}
Future<void> gotReceipt(String receiptId) async { Future<void> gotReceipt(String receiptId) async {
await into( await into(
receivedReceipts, receivedReceipts,

View file

@ -299,17 +299,9 @@ class ApiService {
return result; return result;
} }
Future<bool> sendResponse(ClientToServer response) async { Future<void> sendResponse(ClientToServer response) async {
final channel = _channel; if (_channel != null) {
if (channel == null || channel.closeCode != null) { _channel!.sink.add(response.writeToBuffer());
return false;
}
try {
channel.sink.add(response.writeToBuffer());
return true;
} catch (e) {
Log.warn('Could not send response to server: $e');
return false;
} }
} }

View file

@ -80,16 +80,9 @@ Future<void> handleServerMessage(server.ServerToClient msg) async {
..seq = msg.v0.seq ..seq = msg.v0.seq
..response = response; ..response = response;
final responseSent = await apiService.sendResponse(ClientToServer()..v0 = v0); await apiService.sendResponse(ClientToServer()..v0 = v0);
if (responseSent) {
Log.info(
'Successfully queued response for server message ${msg.v0.seq}.',
);
} else {
Log.warn('Could not send response for server message ${msg.v0.seq}.');
}
AppState.gotMessageFromServer = true; AppState.gotMessageFromServer = true;
Log.info('All messages from the server processed.'); Log.info('All messages from the server proccessed.');
} }
DateTime lastPushKeyRequest = clock.now().subtract(const Duration(hours: 1)); DateTime lastPushKeyRequest = clock.now().subtract(const Duration(hours: 1));
@ -148,25 +141,8 @@ Future<void> _handleClient2ClientMessage(
} }
if (await twonlyDB.receiptsDao.isDuplicated(receiptId)) { if (await twonlyDB.receiptsDao.isDuplicated(receiptId)) {
if (message.type == Message_Type.SENDER_DELIVERY_RECEIPT) {
Log.info( Log.info(
'[$receiptId] Delivery receipt is a duplicate. Skipping receipt response.', '[$receiptId] Message is a duplicate. Sending delivery receipt again.',
);
return;
}
const duplicateReceiptCooldown = Duration(days: 10);
final shouldResend = await twonlyDB.receiptsDao.claimDuplicateReceiptResend(
receiptId,
duplicateReceiptCooldown,
);
if (!shouldResend) {
Log.info(
'[$receiptId] Message is a duplicate. Skipping delivery receipt during cooldown.',
);
return;
}
Log.info(
'[$receiptId] Message is a duplicate and cooldown elapsed. Sending delivery receipt again.',
); );
try { try {
final response = Message(type: Message_Type.SENDER_DELIVERY_RECEIPT); final response = Message(type: Message_Type.SENDER_DELIVERY_RECEIPT);

View file

@ -3,7 +3,7 @@ description: "twonly, a privacy-friendly way to connect with friends through sec
publish_to: 'none' publish_to: 'none'
version: 0.5.2+172 version: 0.5.1+171
environment: environment:
sdk: ^3.11.0 sdk: ^3.11.0