fix #360
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run

This commit is contained in:
otsmr 2025-12-29 21:22:32 +01:00
parent ebf53a5ab4
commit 87187843fa
10 changed files with 6971 additions and 6 deletions

View file

@ -80,10 +80,18 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
}
}
Future<List<Receipt>> getReceiptsNotAckByServer() async {
Future<List<Receipt>> getReceiptsForRetransmission() async {
final markedRetriesTime = DateTime.now().subtract(
const Duration(
// give the server time to transmit all messages to the client
seconds: 20,
),
);
return (select(receipts)
..where(
(t) => t.ackByServerAt.isNull(),
(t) =>
t.ackByServerAt.isNull() |
t.markForRetry.isSmallerThanValue(markedRetriesTime),
))
.get();
}
@ -100,6 +108,14 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
.write(updates);
}
Future<void> markMessagesForRetry(int contactId) async {
await (update(receipts)..where((c) => c.contactId.equals(contactId))).write(
ReceiptsCompanion(
markForRetry: Value(DateTime.now()),
),
);
}
Future<bool> isDuplicated(String receiptId) async {
return await (select(receivedReceipts)
..where((t) => t.receiptId.equals(receiptId)))

File diff suppressed because one or more lines are too long

View file

@ -20,6 +20,8 @@ class Receipts extends Table {
BoolColumn get contactWillSendsReceipt =>
boolean().withDefault(const Constant(true))();
DateTimeColumn get markForRetry => dateTime().nullable()();
DateTimeColumn get ackByServerAt => dateTime().nullable()();
IntColumn get retryCount => integer().withDefault(const Constant(0))();

View file

@ -67,7 +67,7 @@ class TwonlyDB extends _$TwonlyDB {
TwonlyDB.forTesting(DatabaseConnection super.connection);
@override
int get schemaVersion => 4;
int get schemaVersion => 5;
static QueryExecutor _openConnection() {
return driftDatabase(
@ -103,6 +103,9 @@ class TwonlyDB extends _$TwonlyDB {
),
);
},
from4To5: (m, schema) async {
await m.addColumn(schema.receipts, schema.receipts.markForRetry);
},
),
);
}

View file

@ -4546,6 +4546,12 @@ class $ReceiptsTable extends Receipts with TableInfo<$ReceiptsTable, Receipt> {
defaultConstraints: GeneratedColumn.constraintIsAlways(
'CHECK ("contact_will_sends_receipt" IN (0, 1))'),
defaultValue: const Constant(true));
static const VerificationMeta _markForRetryMeta =
const VerificationMeta('markForRetry');
@override
late final GeneratedColumn<DateTime> markForRetry = GeneratedColumn<DateTime>(
'mark_for_retry', aliasedName, true,
type: DriftSqlType.dateTime, requiredDuringInsert: false);
static const VerificationMeta _ackByServerAtMeta =
const VerificationMeta('ackByServerAt');
@override
@ -4581,6 +4587,7 @@ class $ReceiptsTable extends Receipts with TableInfo<$ReceiptsTable, Receipt> {
messageId,
message,
contactWillSendsReceipt,
markForRetry,
ackByServerAt,
retryCount,
lastRetry,
@ -4625,6 +4632,12 @@ class $ReceiptsTable extends Receipts with TableInfo<$ReceiptsTable, Receipt> {
data['contact_will_sends_receipt']!,
_contactWillSendsReceiptMeta));
}
if (data.containsKey('mark_for_retry')) {
context.handle(
_markForRetryMeta,
markForRetry.isAcceptableOrUnknown(
data['mark_for_retry']!, _markForRetryMeta));
}
if (data.containsKey('ack_by_server_at')) {
context.handle(
_ackByServerAtMeta,
@ -4665,6 +4678,8 @@ class $ReceiptsTable extends Receipts with TableInfo<$ReceiptsTable, Receipt> {
contactWillSendsReceipt: attachedDatabase.typeMapping.read(
DriftSqlType.bool,
data['${effectivePrefix}contact_will_sends_receipt'])!,
markForRetry: attachedDatabase.typeMapping.read(
DriftSqlType.dateTime, data['${effectivePrefix}mark_for_retry']),
ackByServerAt: attachedDatabase.typeMapping.read(
DriftSqlType.dateTime, data['${effectivePrefix}ack_by_server_at']),
retryCount: attachedDatabase.typeMapping
@ -4690,6 +4705,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
/// This is the protobuf 'Message'
final Uint8List message;
final bool contactWillSendsReceipt;
final DateTime? markForRetry;
final DateTime? ackByServerAt;
final int retryCount;
final DateTime? lastRetry;
@ -4700,6 +4716,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
this.messageId,
required this.message,
required this.contactWillSendsReceipt,
this.markForRetry,
this.ackByServerAt,
required this.retryCount,
this.lastRetry,
@ -4714,6 +4731,9 @@ class Receipt extends DataClass implements Insertable<Receipt> {
}
map['message'] = Variable<Uint8List>(message);
map['contact_will_sends_receipt'] = Variable<bool>(contactWillSendsReceipt);
if (!nullToAbsent || markForRetry != null) {
map['mark_for_retry'] = Variable<DateTime>(markForRetry);
}
if (!nullToAbsent || ackByServerAt != null) {
map['ack_by_server_at'] = Variable<DateTime>(ackByServerAt);
}
@ -4734,6 +4754,9 @@ class Receipt extends DataClass implements Insertable<Receipt> {
: Value(messageId),
message: Value(message),
contactWillSendsReceipt: Value(contactWillSendsReceipt),
markForRetry: markForRetry == null && nullToAbsent
? const Value.absent()
: Value(markForRetry),
ackByServerAt: ackByServerAt == null && nullToAbsent
? const Value.absent()
: Value(ackByServerAt),
@ -4755,6 +4778,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
message: serializer.fromJson<Uint8List>(json['message']),
contactWillSendsReceipt:
serializer.fromJson<bool>(json['contactWillSendsReceipt']),
markForRetry: serializer.fromJson<DateTime?>(json['markForRetry']),
ackByServerAt: serializer.fromJson<DateTime?>(json['ackByServerAt']),
retryCount: serializer.fromJson<int>(json['retryCount']),
lastRetry: serializer.fromJson<DateTime?>(json['lastRetry']),
@ -4771,6 +4795,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
'message': serializer.toJson<Uint8List>(message),
'contactWillSendsReceipt':
serializer.toJson<bool>(contactWillSendsReceipt),
'markForRetry': serializer.toJson<DateTime?>(markForRetry),
'ackByServerAt': serializer.toJson<DateTime?>(ackByServerAt),
'retryCount': serializer.toJson<int>(retryCount),
'lastRetry': serializer.toJson<DateTime?>(lastRetry),
@ -4784,6 +4809,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
Value<String?> messageId = const Value.absent(),
Uint8List? message,
bool? contactWillSendsReceipt,
Value<DateTime?> markForRetry = const Value.absent(),
Value<DateTime?> ackByServerAt = const Value.absent(),
int? retryCount,
Value<DateTime?> lastRetry = const Value.absent(),
@ -4795,6 +4821,8 @@ class Receipt extends DataClass implements Insertable<Receipt> {
message: message ?? this.message,
contactWillSendsReceipt:
contactWillSendsReceipt ?? this.contactWillSendsReceipt,
markForRetry:
markForRetry.present ? markForRetry.value : this.markForRetry,
ackByServerAt:
ackByServerAt.present ? ackByServerAt.value : this.ackByServerAt,
retryCount: retryCount ?? this.retryCount,
@ -4810,6 +4838,9 @@ class Receipt extends DataClass implements Insertable<Receipt> {
contactWillSendsReceipt: data.contactWillSendsReceipt.present
? data.contactWillSendsReceipt.value
: this.contactWillSendsReceipt,
markForRetry: data.markForRetry.present
? data.markForRetry.value
: this.markForRetry,
ackByServerAt: data.ackByServerAt.present
? data.ackByServerAt.value
: this.ackByServerAt,
@ -4828,6 +4859,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
..write('messageId: $messageId, ')
..write('message: $message, ')
..write('contactWillSendsReceipt: $contactWillSendsReceipt, ')
..write('markForRetry: $markForRetry, ')
..write('ackByServerAt: $ackByServerAt, ')
..write('retryCount: $retryCount, ')
..write('lastRetry: $lastRetry, ')
@ -4843,6 +4875,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
messageId,
$driftBlobEquality.hash(message),
contactWillSendsReceipt,
markForRetry,
ackByServerAt,
retryCount,
lastRetry,
@ -4856,6 +4889,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
other.messageId == this.messageId &&
$driftBlobEquality.equals(other.message, this.message) &&
other.contactWillSendsReceipt == this.contactWillSendsReceipt &&
other.markForRetry == this.markForRetry &&
other.ackByServerAt == this.ackByServerAt &&
other.retryCount == this.retryCount &&
other.lastRetry == this.lastRetry &&
@ -4868,6 +4902,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
final Value<String?> messageId;
final Value<Uint8List> message;
final Value<bool> contactWillSendsReceipt;
final Value<DateTime?> markForRetry;
final Value<DateTime?> ackByServerAt;
final Value<int> retryCount;
final Value<DateTime?> lastRetry;
@ -4879,6 +4914,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
this.messageId = const Value.absent(),
this.message = const Value.absent(),
this.contactWillSendsReceipt = const Value.absent(),
this.markForRetry = const Value.absent(),
this.ackByServerAt = const Value.absent(),
this.retryCount = const Value.absent(),
this.lastRetry = const Value.absent(),
@ -4891,6 +4927,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
this.messageId = const Value.absent(),
required Uint8List message,
this.contactWillSendsReceipt = const Value.absent(),
this.markForRetry = const Value.absent(),
this.ackByServerAt = const Value.absent(),
this.retryCount = const Value.absent(),
this.lastRetry = const Value.absent(),
@ -4905,6 +4942,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
Expression<String>? messageId,
Expression<Uint8List>? message,
Expression<bool>? contactWillSendsReceipt,
Expression<DateTime>? markForRetry,
Expression<DateTime>? ackByServerAt,
Expression<int>? retryCount,
Expression<DateTime>? lastRetry,
@ -4918,6 +4956,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
if (message != null) 'message': message,
if (contactWillSendsReceipt != null)
'contact_will_sends_receipt': contactWillSendsReceipt,
if (markForRetry != null) 'mark_for_retry': markForRetry,
if (ackByServerAt != null) 'ack_by_server_at': ackByServerAt,
if (retryCount != null) 'retry_count': retryCount,
if (lastRetry != null) 'last_retry': lastRetry,
@ -4932,6 +4971,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
Value<String?>? messageId,
Value<Uint8List>? message,
Value<bool>? contactWillSendsReceipt,
Value<DateTime?>? markForRetry,
Value<DateTime?>? ackByServerAt,
Value<int>? retryCount,
Value<DateTime?>? lastRetry,
@ -4944,6 +4984,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
message: message ?? this.message,
contactWillSendsReceipt:
contactWillSendsReceipt ?? this.contactWillSendsReceipt,
markForRetry: markForRetry ?? this.markForRetry,
ackByServerAt: ackByServerAt ?? this.ackByServerAt,
retryCount: retryCount ?? this.retryCount,
lastRetry: lastRetry ?? this.lastRetry,
@ -4971,6 +5012,9 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
map['contact_will_sends_receipt'] =
Variable<bool>(contactWillSendsReceipt.value);
}
if (markForRetry.present) {
map['mark_for_retry'] = Variable<DateTime>(markForRetry.value);
}
if (ackByServerAt.present) {
map['ack_by_server_at'] = Variable<DateTime>(ackByServerAt.value);
}
@ -4997,6 +5041,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
..write('messageId: $messageId, ')
..write('message: $message, ')
..write('contactWillSendsReceipt: $contactWillSendsReceipt, ')
..write('markForRetry: $markForRetry, ')
..write('ackByServerAt: $ackByServerAt, ')
..write('retryCount: $retryCount, ')
..write('lastRetry: $lastRetry, ')
@ -11662,6 +11707,7 @@ typedef $$ReceiptsTableCreateCompanionBuilder = ReceiptsCompanion Function({
Value<String?> messageId,
required Uint8List message,
Value<bool> contactWillSendsReceipt,
Value<DateTime?> markForRetry,
Value<DateTime?> ackByServerAt,
Value<int> retryCount,
Value<DateTime?> lastRetry,
@ -11674,6 +11720,7 @@ typedef $$ReceiptsTableUpdateCompanionBuilder = ReceiptsCompanion Function({
Value<String?> messageId,
Value<Uint8List> message,
Value<bool> contactWillSendsReceipt,
Value<DateTime?> markForRetry,
Value<DateTime?> ackByServerAt,
Value<int> retryCount,
Value<DateTime?> lastRetry,
@ -11735,6 +11782,9 @@ class $$ReceiptsTableFilterComposer
column: $table.contactWillSendsReceipt,
builder: (column) => ColumnFilters(column));
ColumnFilters<DateTime> get markForRetry => $composableBuilder(
column: $table.markForRetry, builder: (column) => ColumnFilters(column));
ColumnFilters<DateTime> get ackByServerAt => $composableBuilder(
column: $table.ackByServerAt, builder: (column) => ColumnFilters(column));
@ -11807,6 +11857,10 @@ class $$ReceiptsTableOrderingComposer
column: $table.contactWillSendsReceipt,
builder: (column) => ColumnOrderings(column));
ColumnOrderings<DateTime> get markForRetry => $composableBuilder(
column: $table.markForRetry,
builder: (column) => ColumnOrderings(column));
ColumnOrderings<DateTime> get ackByServerAt => $composableBuilder(
column: $table.ackByServerAt,
builder: (column) => ColumnOrderings(column));
@ -11879,6 +11933,9 @@ class $$ReceiptsTableAnnotationComposer
GeneratedColumn<bool> get contactWillSendsReceipt => $composableBuilder(
column: $table.contactWillSendsReceipt, builder: (column) => column);
GeneratedColumn<DateTime> get markForRetry => $composableBuilder(
column: $table.markForRetry, builder: (column) => column);
GeneratedColumn<DateTime> get ackByServerAt => $composableBuilder(
column: $table.ackByServerAt, builder: (column) => column);
@ -11960,6 +12017,7 @@ class $$ReceiptsTableTableManager extends RootTableManager<
Value<String?> messageId = const Value.absent(),
Value<Uint8List> message = const Value.absent(),
Value<bool> contactWillSendsReceipt = const Value.absent(),
Value<DateTime?> markForRetry = const Value.absent(),
Value<DateTime?> ackByServerAt = const Value.absent(),
Value<int> retryCount = const Value.absent(),
Value<DateTime?> lastRetry = const Value.absent(),
@ -11972,6 +12030,7 @@ class $$ReceiptsTableTableManager extends RootTableManager<
messageId: messageId,
message: message,
contactWillSendsReceipt: contactWillSendsReceipt,
markForRetry: markForRetry,
ackByServerAt: ackByServerAt,
retryCount: retryCount,
lastRetry: lastRetry,
@ -11984,6 +12043,7 @@ class $$ReceiptsTableTableManager extends RootTableManager<
Value<String?> messageId = const Value.absent(),
required Uint8List message,
Value<bool> contactWillSendsReceipt = const Value.absent(),
Value<DateTime?> markForRetry = const Value.absent(),
Value<DateTime?> ackByServerAt = const Value.absent(),
Value<int> retryCount = const Value.absent(),
Value<DateTime?> lastRetry = const Value.absent(),
@ -11996,6 +12056,7 @@ class $$ReceiptsTableTableManager extends RootTableManager<
messageId: messageId,
message: message,
contactWillSendsReceipt: contactWillSendsReceipt,
markForRetry: markForRetry,
ackByServerAt: ackByServerAt,
retryCount: retryCount,
lastRetry: lastRetry,

View file

@ -1946,10 +1946,416 @@ final class Schema4 extends i0.VersionedSchema {
i1.GeneratedColumn<int> _column_101(String aliasedName) =>
i1.GeneratedColumn<int>('affected_contact_id', aliasedName, true,
type: i1.DriftSqlType.int);
final class Schema5 extends i0.VersionedSchema {
Schema5({required super.database}) : super(version: 5);
@override
late final List<i1.DatabaseSchemaEntity> entities = [
contacts,
groups,
mediaFiles,
messages,
messageHistories,
reactions,
groupMembers,
receipts,
receivedReceipts,
signalIdentityKeyStores,
signalPreKeyStores,
signalSenderKeyStores,
signalSessionStores,
signalContactPreKeys,
signalContactSignedPreKeys,
messageActions,
groupHistories,
];
late final Shape0 contacts = Shape0(
source: i0.VersionedTable(
entityName: 'contacts',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(user_id)',
],
columns: [
_column_0,
_column_1,
_column_2,
_column_3,
_column_4,
_column_5,
_column_6,
_column_7,
_column_8,
_column_9,
_column_10,
_column_11,
_column_12,
],
attachedDatabase: database,
),
alias: null);
late final Shape17 groups = Shape17(
source: i0.VersionedTable(
entityName: 'groups',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(group_id)',
],
columns: [
_column_13,
_column_14,
_column_15,
_column_16,
_column_17,
_column_18,
_column_19,
_column_20,
_column_21,
_column_22,
_column_23,
_column_24,
_column_100,
_column_25,
_column_26,
_column_27,
_column_12,
_column_28,
_column_29,
_column_30,
_column_31,
_column_32,
_column_33,
_column_34,
_column_35,
],
attachedDatabase: database,
),
alias: null);
late final Shape2 mediaFiles = Shape2(
source: i0.VersionedTable(
entityName: 'media_files',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(media_id)',
],
columns: [
_column_36,
_column_37,
_column_38,
_column_39,
_column_40,
_column_41,
_column_42,
_column_43,
_column_44,
_column_45,
_column_46,
_column_47,
_column_48,
_column_49,
_column_12,
],
attachedDatabase: database,
),
alias: null);
late final Shape3 messages = Shape3(
source: i0.VersionedTable(
entityName: 'messages',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(message_id)',
],
columns: [
_column_50,
_column_51,
_column_52,
_column_37,
_column_53,
_column_54,
_column_55,
_column_56,
_column_46,
_column_57,
_column_58,
_column_59,
_column_60,
_column_12,
_column_61,
_column_62,
_column_63,
],
attachedDatabase: database,
),
alias: null);
late final Shape4 messageHistories = Shape4(
source: i0.VersionedTable(
entityName: 'message_histories',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(id)',
],
columns: [
_column_64,
_column_65,
_column_66,
_column_53,
_column_12,
],
attachedDatabase: database,
),
alias: null);
late final Shape5 reactions = Shape5(
source: i0.VersionedTable(
entityName: 'reactions',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(message_id, sender_id, emoji)',
],
columns: [
_column_65,
_column_67,
_column_68,
_column_12,
],
attachedDatabase: database,
),
alias: null);
late final Shape6 groupMembers = Shape6(
source: i0.VersionedTable(
entityName: 'group_members',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(group_id, contact_id)',
],
columns: [
_column_50,
_column_69,
_column_70,
_column_71,
_column_72,
_column_12,
],
attachedDatabase: database,
),
alias: null);
late final Shape18 receipts = Shape18(
source: i0.VersionedTable(
entityName: 'receipts',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(receipt_id)',
],
columns: [
_column_73,
_column_74,
_column_75,
_column_76,
_column_77,
_column_102,
_column_78,
_column_79,
_column_80,
_column_12,
],
attachedDatabase: database,
),
alias: null);
late final Shape8 receivedReceipts = Shape8(
source: i0.VersionedTable(
entityName: 'received_receipts',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(receipt_id)',
],
columns: [
_column_73,
_column_12,
],
attachedDatabase: database,
),
alias: null);
late final Shape9 signalIdentityKeyStores = Shape9(
source: i0.VersionedTable(
entityName: 'signal_identity_key_stores',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(device_id, name)',
],
columns: [
_column_81,
_column_82,
_column_83,
_column_12,
],
attachedDatabase: database,
),
alias: null);
late final Shape10 signalPreKeyStores = Shape10(
source: i0.VersionedTable(
entityName: 'signal_pre_key_stores',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(pre_key_id)',
],
columns: [
_column_84,
_column_85,
_column_12,
],
attachedDatabase: database,
),
alias: null);
late final Shape11 signalSenderKeyStores = Shape11(
source: i0.VersionedTable(
entityName: 'signal_sender_key_stores',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(sender_key_name)',
],
columns: [
_column_86,
_column_87,
],
attachedDatabase: database,
),
alias: null);
late final Shape12 signalSessionStores = Shape12(
source: i0.VersionedTable(
entityName: 'signal_session_stores',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(device_id, name)',
],
columns: [
_column_81,
_column_82,
_column_88,
_column_12,
],
attachedDatabase: database,
),
alias: null);
late final Shape13 signalContactPreKeys = Shape13(
source: i0.VersionedTable(
entityName: 'signal_contact_pre_keys',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(contact_id, pre_key_id)',
],
columns: [
_column_74,
_column_84,
_column_85,
_column_12,
],
attachedDatabase: database,
),
alias: null);
late final Shape14 signalContactSignedPreKeys = Shape14(
source: i0.VersionedTable(
entityName: 'signal_contact_signed_pre_keys',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(contact_id)',
],
columns: [
_column_74,
_column_89,
_column_90,
_column_91,
_column_12,
],
attachedDatabase: database,
),
alias: null);
late final Shape15 messageActions = Shape15(
source: i0.VersionedTable(
entityName: 'message_actions',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(message_id, contact_id, type)',
],
columns: [
_column_65,
_column_92,
_column_37,
_column_93,
],
attachedDatabase: database,
),
alias: null);
late final Shape16 groupHistories = Shape16(
source: i0.VersionedTable(
entityName: 'group_histories',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(group_history_id)',
],
columns: [
_column_94,
_column_50,
_column_95,
_column_101,
_column_97,
_column_98,
_column_99,
_column_37,
_column_93,
],
attachedDatabase: database,
),
alias: null);
}
class Shape18 extends i0.VersionedTable {
Shape18({required super.source, required super.alias}) : super.aliased();
i1.GeneratedColumn<String> get receiptId =>
columnsByName['receipt_id']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<int> get contactId =>
columnsByName['contact_id']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<String> get messageId =>
columnsByName['message_id']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<i2.Uint8List> get message =>
columnsByName['message']! as i1.GeneratedColumn<i2.Uint8List>;
i1.GeneratedColumn<bool> get contactWillSendsReceipt =>
columnsByName['contact_will_sends_receipt']! as i1.GeneratedColumn<bool>;
i1.GeneratedColumn<DateTime> get markForRetry =>
columnsByName['mark_for_retry']! as i1.GeneratedColumn<DateTime>;
i1.GeneratedColumn<DateTime> get ackByServerAt =>
columnsByName['ack_by_server_at']! as i1.GeneratedColumn<DateTime>;
i1.GeneratedColumn<int> get retryCount =>
columnsByName['retry_count']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<DateTime> get lastRetry =>
columnsByName['last_retry']! as i1.GeneratedColumn<DateTime>;
i1.GeneratedColumn<DateTime> get createdAt =>
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
}
i1.GeneratedColumn<DateTime> _column_102(String aliasedName) =>
i1.GeneratedColumn<DateTime>('mark_for_retry', aliasedName, true,
type: i1.DriftSqlType.dateTime);
i0.MigrationStepWithVersion migrationSteps({
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
required Future<void> Function(i1.Migrator m, Schema5 schema) from4To5,
}) {
return (currentVersion, database) async {
switch (currentVersion) {
@ -1968,6 +2374,11 @@ i0.MigrationStepWithVersion migrationSteps({
final migrator = i1.Migrator(database, schema);
await from3To4(migrator, schema);
return 4;
case 4:
final schema = Schema5(database: database);
final migrator = i1.Migrator(database, schema);
await from4To5(migrator, schema);
return 5;
default:
throw ArgumentError.value('Unknown migration from $currentVersion');
}
@ -1978,10 +2389,12 @@ i1.OnUpgrade stepByStep({
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
required Future<void> Function(i1.Migrator m, Schema5 schema) from4To5,
}) =>
i0.VersionedSchema.stepByStepHelper(
step: migrationSteps(
from1To2: from1To2,
from2To3: from2To3,
from3To4: from3To4,
from4To5: from4To5,
));

View file

@ -21,7 +21,7 @@ final lockRetransmission = Mutex();
Future<void> tryTransmitMessages() async {
return lockRetransmission.protect(() async {
final receipts = await twonlyDB.receiptsDao.getReceiptsNotAckByServer();
final receipts = await twonlyDB.receiptsDao.getReceiptsForRetransmission();
if (receipts.isEmpty) return;

View file

@ -40,7 +40,11 @@ Future<void> handleServerMessage(server.ServerToClient msg) async {
await handleClient2ClientMessage(msg.v0.newMessage);
} else if (msg.v0.hasNewMessages()) {
for (final newMessage in msg.v0.newMessages.newMessages) {
try {
await handleClient2ClientMessage(newMessage);
} catch (e) {
Log.error(e);
}
}
} else {
Log.error('Unknown server message: $msg');
@ -185,6 +189,15 @@ Future<PlaintextContent?> handleEncryptedMessage(
..type = decryptionErrorType!);
}
// We got a valid message fromUserId, so mark all messages which where
// send to the user but not yet ACK for retransmission. All marked messages
// will be either transmitted again after a new server connection (minimum 20 seconds).
// In case the server sends the ACK before they will be deleted.
// This ensures that 1. all messages will be received by the other person and
// that they will be retransmitted in case the server deleted them as they
// where not downloaded within the 40 days
await twonlyDB.receiptsDao.markMessagesForRetry(fromUserId);
final senderProfileCounter = await checkForProfileUpdate(fromUserId, content);
if (content.hasContactRequest()) {

View file

@ -7,6 +7,7 @@ import 'schema_v1.dart' as v1;
import 'schema_v2.dart' as v2;
import 'schema_v3.dart' as v3;
import 'schema_v4.dart' as v4;
import 'schema_v5.dart' as v5;
class GeneratedHelper implements SchemaInstantiationHelper {
@override
@ -20,10 +21,12 @@ class GeneratedHelper implements SchemaInstantiationHelper {
return v3.DatabaseAtV3(db);
case 4:
return v4.DatabaseAtV4(db);
case 5:
return v5.DatabaseAtV5(db);
default:
throw MissingSchemaException(version, versions);
}
}
static const versions = const [1, 2, 3, 4];
static const versions = const [1, 2, 3, 4, 5];
}

File diff suppressed because it is too large Load diff