Skip to content

Commit

Permalink
feat: retry sending file up to 10x
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiasn committed Jun 1, 2024
1 parent d596a0b commit 437114a
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 140 deletions.
1 change: 1 addition & 0 deletions integration_test/matrix_service_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import 'package:lotti/database/settings_db.dart';
import 'package:lotti/get_it.dart';
import 'package:lotti/services/db_notification.dart';
import 'package:lotti/sync/matrix/matrix_service.dart';
import 'package:lotti/sync/matrix/send_message.dart';
import 'package:lotti/sync/secure_storage.dart';
import 'package:lotti/sync/vector_clock.dart';
import 'package:lotti/utils/file_utils.dart';
Expand Down
12 changes: 0 additions & 12 deletions lib/sync/matrix/matrix_service.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import 'dart:async';

import 'package:lotti/classes/config.dart';
import 'package:lotti/classes/sync_message.dart';
import 'package:lotti/database/database.dart';
import 'package:lotti/sync/client_runner.dart';
import 'package:lotti/sync/matrix/client.dart';
import 'package:lotti/sync/matrix/config.dart';
import 'package:lotti/sync/matrix/key_verification_runner.dart';
import 'package:lotti/sync/matrix/last_read.dart';
import 'package:lotti/sync/matrix/room.dart';
import 'package:lotti/sync/matrix/send_message.dart';
import 'package:lotti/sync/matrix/stats.dart';
import 'package:lotti/sync/matrix/timeline.dart';
import 'package:matrix/encryption/utils/key_verification.dart';
Expand Down Expand Up @@ -178,16 +176,6 @@ class MatrixService {
Future<void> startKeyVerificationListener() =>
listenForKeyVerificationRequests(service: this);

Future<bool> sendMatrixMsg(
SyncMessage syncMessage, {
String? myRoomId,
}) async {
return sendMessage(
syncMessage,
myRoomId: myRoomId,
);
}

Future<void> logout() async {
if (_client.isLogged()) {
timeline?.cancelSubscriptions();
Expand Down
185 changes: 79 additions & 106 deletions lib/sync/matrix/send_message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:lotti/classes/journal_entities.dart';
import 'package:lotti/classes/sync_message.dart';
import 'package:lotti/database/database.dart';
Expand Down Expand Up @@ -35,103 +34,89 @@ extension SendExtension on MatrixService {
/// Also updates some stats on sent message counts on the [MatrixService].
/// The send function will terminate early (and thus refuse to send anything)
/// when there are users with unverified device in the room.
Future<bool> sendMessage(
Future<void> sendMatrixMsg(
SyncMessage syncMessage, {
required String? myRoomId,
String? myRoomId,
}) async {
final loggingDb = getIt<LoggingDb>();

try {
final msg = json.encode(syncMessage);
final roomId = myRoomId ?? syncRoomId;

if (getUnverifiedDevices().isNotEmpty) {
loggingDb.captureException(
'Unverified devices found',
domain: 'MATRIX_SERVICE',
subDomain: 'sendMatrixMsg',
);
return false;
}

if (roomId == null) {
loggingDb.captureEvent(
configNotFound,
domain: 'MATRIX_SERVICE',
subDomain: 'sendMatrixMsg',
);
return false;
}
final msg = json.encode(syncMessage);
final roomId = myRoomId ?? syncRoomId;

loggingDb.captureEvent(
'trying to send text message to $syncRoom',
if (getUnverifiedDevices().isNotEmpty) {
loggingDb.captureException(
'Unverified devices found',
domain: 'MATRIX_SERVICE',
subDomain: 'sendMatrixMsg',
);
}

final eventId = await syncRoom?.sendTextEvent(
base64.encode(utf8.encode(msg)),
msgtype: syncMessageType,
parseCommands: false,
parseMarkdown: false,
);

incrementSentCount();

if (roomId == null) {
loggingDb.captureEvent(
'sent text message to $syncRoom with event ID $eventId',
configNotFound,
domain: 'MATRIX_SERVICE',
subDomain: 'sendMatrixMsg',
);
}

final docDir = getDocumentsDirectory();

if (syncMessage is SyncJournalEntity) {
final journalEntity = syncMessage.journalEntity;

final shouldResendAttachments =
await getIt<JournalDb>().getConfigFlag(resendAttachments);

await journalEntity.maybeMap(
journalAudio: (JournalAudio journalAudio) async {
if (shouldResendAttachments ||
syncMessage.status == SyncEntryStatus.initial) {
unawaited(
sendFile(
fullPath: AudioUtils.getAudioPath(
journalAudio,
docDir,
),
relativePath: AudioUtils.getRelativeAudioPath(journalAudio),
),
);
}
},
journalImage: (JournalImage journalImage) async {
if (shouldResendAttachments ||
syncMessage.status == SyncEntryStatus.initial) {
unawaited(
sendFile(
fullPath: getFullImagePath(journalImage),
relativePath: getRelativeImagePath(journalImage),
loggingDb.captureEvent(
'trying to send text message to $syncRoom',
domain: 'MATRIX_SERVICE',
subDomain: 'sendMatrixMsg',
);

final eventId = await syncRoom?.sendTextEvent(
base64.encode(utf8.encode(msg)),
msgtype: syncMessageType,
parseCommands: false,
parseMarkdown: false,
);

incrementSentCount();

loggingDb.captureEvent(
'sent text message to $syncRoom with event ID $eventId',
domain: 'MATRIX_SERVICE',
subDomain: 'sendMatrixMsg',
);

final docDir = getDocumentsDirectory();

if (syncMessage is SyncJournalEntity) {
final journalEntity = syncMessage.journalEntity;

final shouldResendAttachments =
await getIt<JournalDb>().getConfigFlag(resendAttachments);

await journalEntity.maybeMap(
journalAudio: (JournalAudio journalAudio) async {
if (shouldResendAttachments ||
syncMessage.status == SyncEntryStatus.initial) {
unawaited(
sendFile(
fullPath: AudioUtils.getAudioPath(
journalAudio,
docDir,
),
);
}
},
orElse: () {},
);
}
return true;
} catch (e, stackTrace) {
debugPrint('MATRIX: Error sending message: $e');
loggingDb.captureException(
e,
domain: 'MATRIX_SERVICE',
subDomain: 'sendMatrixMsg',
stackTrace: stackTrace,
relativePath: AudioUtils.getRelativeAudioPath(journalAudio),
),
);
}
},
journalImage: (JournalImage journalImage) async {
if (shouldResendAttachments ||
syncMessage.status == SyncEntryStatus.initial) {
unawaited(
sendFile(
fullPath: getFullImagePath(journalImage),
relativePath: getRelativeImagePath(journalImage),
),
);
}
},
orElse: () {},
);
}
return false;
}

/// Sends a file attachment to the sync room.
Expand All @@ -146,32 +131,20 @@ extension SendExtension on MatrixService {
subDomain: 'sendMatrixMsg',
);

try {
final eventId = await syncRoom?.sendFileEvent(
MatrixFile(
bytes: await File(fullPath).readAsBytes(),
name: fullPath,
),
extraContent: {
'relativePath': relativePath,
},
);
final eventId = await syncRoom?.sendFileEvent(
MatrixFile(
bytes: await File(fullPath).readAsBytes(),
name: fullPath,
),
extraContent: {'relativePath': relativePath},
);

incrementSentCount();
incrementSentCount();

loggingDb.captureEvent(
'sent $relativePath file message to $syncRoom, event ID $eventId',
domain: 'MATRIX_SERVICE',
subDomain: 'sendMatrixMsg',
);
} catch (e, stackTrace) {
debugPrint('MATRIX: Error sending file: $e');
loggingDb.captureException(
e,
domain: 'MATRIX_SERVICE',
subDomain: 'sendFile',
stackTrace: stackTrace,
);
}
loggingDb.captureEvent(
'sent $relativePath file message to $syncRoom, event ID $eventId',
domain: 'MATRIX_SERVICE',
subDomain: 'sendMatrixMsg',
);
}
}
43 changes: 22 additions & 21 deletions lib/sync/outbox/outbox_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'package:lotti/get_it.dart';
import 'package:lotti/services/vector_clock_service.dart';
import 'package:lotti/sync/client_runner.dart';
import 'package:lotti/sync/matrix/matrix_service.dart';
import 'package:lotti/sync/matrix/send_message.dart';
import 'package:lotti/utils/audio_utils.dart';
import 'package:lotti/utils/consts.dart';
import 'package:lotti/utils/file_utils.dart';
Expand Down Expand Up @@ -140,36 +141,36 @@ class OutboxService {
);

try {
final syncMessage = SyncMessage.fromJson(
json.decode(nextPending.message) as Map<String, dynamic>,
await getIt<MatrixService>().sendMatrixMsg(
SyncMessage.fromJson(
json.decode(nextPending.message) as Map<String, dynamic>,
),
);

final success =
await getIt<MatrixService>().sendMatrixMsg(syncMessage);

if (success) {
await _syncDatabase.updateOutboxItem(
OutboxCompanion(
id: Value(nextPending.id),
status: Value(OutboxStatus.sent.index),
updatedAt: Value(DateTime.now()),
),
);
if (unprocessed.length > 1) {
await enqueueNextSendRequest();
}
} else {
await enqueueNextSendRequest(
delay: const Duration(seconds: 15),
);
await _syncDatabase.updateOutboxItem(
OutboxCompanion(
id: Value(nextPending.id),
status: Value(OutboxStatus.sent.index),
updatedAt: Value(DateTime.now()),
),
);
if (unprocessed.length > 1) {
await enqueueNextSendRequest();
}

_loggingDb.captureEvent(
'${nextPending.subject} done',
domain: 'OUTBOX',
subDomain: 'sendNext()',
);
} catch (e) {
} catch (e, stackTrace) {
getIt<LoggingDb>().captureException(
e,
domain: 'MATRIX_SERVICE',
subDomain: 'sendMatrixMsg',
stackTrace: stackTrace,
);

await _syncDatabase.updateOutboxItem(
OutboxCompanion(
id: Value(nextPending.id),
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: lotti
description: Achieve your goals and keep your data private with Lotti.
publish_to: 'none'
version: 0.9.472+2542
version: 0.9.473+2543

msix_config:
display_name: LottiApp
Expand Down

0 comments on commit 437114a

Please sign in to comment.