Fix some MAM issues
- Messages from MUCs weren't added to their respective MUC MAM ranges, thus re-fetched on rejoin - The earliest ('first') message of a mam page was used to update the to_id, but it should have been 'last'; also the other way around. - Duplicates weren't detected properly
This commit is contained in:
parent
d1fb22ebed
commit
4d50c51a75
|
@ -46,7 +46,7 @@ public class Dino.HistorySync {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update_latest_db_range(Account account, Xmpp.MessageStanza message_stanza) {
|
public void update_latest_db_range(Account account, Xmpp.MessageStanza message_stanza) {
|
||||||
Jid mam_server = stream_interactor.get_module(MucManager.IDENTITY).might_be_groupchat(message_stanza.from, account) ? message_stanza.from.bare_jid : account.bare_jid;
|
Jid mam_server = stream_interactor.get_module(MucManager.IDENTITY).might_be_groupchat(message_stanza.from.bare_jid, account) ? message_stanza.from.bare_jid : account.bare_jid;
|
||||||
|
|
||||||
if (!current_catchup_id.has_key(account) || !current_catchup_id[account].has_key(mam_server)) return;
|
if (!current_catchup_id.has_key(account) || !current_catchup_id[account].has_key(mam_server)) return;
|
||||||
|
|
||||||
|
@ -205,7 +205,12 @@ public class Dino.HistorySync {
|
||||||
|
|
||||||
PageRequestResult page_result = yield get_mam_page(account, query_params, null);
|
PageRequestResult page_result = yield get_mam_page(account, query_params, null);
|
||||||
|
|
||||||
if (page_result.page_result == PageResult.Error || page_result.page_result == PageResult.Duplicate) {
|
if (page_result.page_result == PageResult.Duplicate) {
|
||||||
|
// No new messages
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page_result.page_result == PageResult.Error) {
|
||||||
debug("[%s | %s] Failed fetching latest page %s", mam_server.to_string(), mam_server.to_string(), page_result.page_result.to_string());
|
debug("[%s | %s] Failed fetching latest page %s", mam_server.to_string(), mam_server.to_string(), page_result.page_result.to_string());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -214,13 +219,13 @@ public class Dino.HistorySync {
|
||||||
if (page_result.page_result in new PageResult[] { PageResult.TargetReached, PageResult.NoMoreMessages } && latest_row_id != -1) {
|
if (page_result.page_result in new PageResult[] { PageResult.TargetReached, PageResult.NoMoreMessages } && latest_row_id != -1) {
|
||||||
if (page_result.stanzas == null || page_result.stanzas.is_empty) return null;
|
if (page_result.stanzas == null || page_result.stanzas.is_empty) return null;
|
||||||
|
|
||||||
string first_mam_id = page_result.query_result.first;
|
string latest_mam_id = page_result.query_result.last;
|
||||||
long first_mam_time = (long) mam_times[account][first_mam_id].to_unix();
|
long latest_mam_time = (long) mam_times[account][latest_mam_id].to_unix();
|
||||||
|
|
||||||
var query = db.mam_catchup.update()
|
var query = db.mam_catchup.update()
|
||||||
.with(db.mam_catchup.id, "=", latest_row_id)
|
.with(db.mam_catchup.id, "=", latest_row_id)
|
||||||
.set(db.mam_catchup.to_time, first_mam_time)
|
.set(db.mam_catchup.to_time, latest_mam_time)
|
||||||
.set(db.mam_catchup.to_id, first_mam_id);
|
.set(db.mam_catchup.to_id, latest_mam_id);
|
||||||
|
|
||||||
if (page_result.page_result == PageResult.NoMoreMessages) {
|
if (page_result.page_result == PageResult.NoMoreMessages) {
|
||||||
// If the server doesn't have more messages, store that this range is at its end.
|
// If the server doesn't have more messages, store that this range is at its end.
|
||||||
|
@ -326,14 +331,14 @@ public class Dino.HistorySync {
|
||||||
|
|
||||||
if (page_result.page_result == PageResult.Error || page_result.stanzas == null) return page_result;
|
if (page_result.page_result == PageResult.Error || page_result.stanzas == null) return page_result;
|
||||||
|
|
||||||
string last_mam_id = page_result.query_result.last;
|
string earliest_mam_id = page_result.query_result.first;
|
||||||
long last_mam_time = (long)mam_times[account][last_mam_id].to_unix();
|
long earliest_mam_time = (long)mam_times[account][earliest_mam_id].to_unix();
|
||||||
|
|
||||||
debug("Updating %s to %s, %s", query_params.mam_server.to_string(), last_mam_time.to_string(), last_mam_id);
|
debug("Updating %s to %s, %s", query_params.mam_server.to_string(), earliest_mam_time.to_string(), earliest_mam_id);
|
||||||
var query = db.mam_catchup.update()
|
var query = db.mam_catchup.update()
|
||||||
.with(db.mam_catchup.id, "=", db_id)
|
.with(db.mam_catchup.id, "=", db_id)
|
||||||
.set(db.mam_catchup.from_time, last_mam_time)
|
.set(db.mam_catchup.from_time, earliest_mam_time)
|
||||||
.set(db.mam_catchup.from_id, last_mam_id);
|
.set(db.mam_catchup.from_id, earliest_mam_id);
|
||||||
|
|
||||||
if (page_result.page_result == PageResult.NoMoreMessages) {
|
if (page_result.page_result == PageResult.NoMoreMessages) {
|
||||||
// If the server doesn't have more messages, store that this range is at its end.
|
// If the server doesn't have more messages, store that this range is at its end.
|
||||||
|
@ -349,7 +354,7 @@ public class Dino.HistorySync {
|
||||||
MorePagesAvailable,
|
MorePagesAvailable,
|
||||||
TargetReached,
|
TargetReached,
|
||||||
NoMoreMessages,
|
NoMoreMessages,
|
||||||
Duplicate, // TODO additional boolean
|
Duplicate,
|
||||||
Error
|
Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,10 +369,10 @@ public class Dino.HistorySync {
|
||||||
} else {
|
} else {
|
||||||
query_result = yield Xmpp.MessageArchiveManagement.V2.page_through_results(stream, query_params, prev_page_result.query_result);
|
query_result = yield Xmpp.MessageArchiveManagement.V2.page_through_results(stream, query_params, prev_page_result.query_result);
|
||||||
}
|
}
|
||||||
return yield process_query_result(account, query_result, query_params.query_id, query_params.start_id);
|
return yield process_query_result(account, query_params, query_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async PageRequestResult process_query_result(Account account, Xmpp.MessageArchiveManagement.QueryResult query_result, string query_id, string? after_id) {
|
private async PageRequestResult process_query_result(Account account, Xmpp.MessageArchiveManagement.V2.MamQueryParams query_params, Xmpp.MessageArchiveManagement.QueryResult query_result) {
|
||||||
PageResult page_result = PageResult.MorePagesAvailable;
|
PageResult page_result = PageResult.MorePagesAvailable;
|
||||||
|
|
||||||
if (query_result.malformed || query_result.error) {
|
if (query_result.malformed || query_result.error) {
|
||||||
|
@ -387,6 +392,9 @@ public class Dino.HistorySync {
|
||||||
string selection = null;
|
string selection = null;
|
||||||
string[] selection_args = {};
|
string[] selection_args = {};
|
||||||
|
|
||||||
|
string query_id = query_params.query_id;
|
||||||
|
string? after_id = query_params.start_id;
|
||||||
|
|
||||||
// Check the server id of all returned messages. Check if we've hit our target (from_id) or got a duplicate.
|
// Check the server id of all returned messages. Check if we've hit our target (from_id) or got a duplicate.
|
||||||
if (stanzas.has_key(query_id) && !stanzas[query_id].is_empty) {
|
if (stanzas.has_key(query_id) && !stanzas[query_id].is_empty) {
|
||||||
foreach (Xmpp.MessageStanza message in stanzas[query_id]) {
|
foreach (Xmpp.MessageStanza message in stanzas[query_id]) {
|
||||||
|
@ -397,8 +405,12 @@ public class Dino.HistorySync {
|
||||||
page_result = PageResult.TargetReached;
|
page_result = PageResult.TargetReached;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selection != null) selection += " OR ";
|
if (selection == null) {
|
||||||
selection = @"$(db.message.server_id) = ?";
|
selection = @"$(db.message.server_id) = ?";
|
||||||
|
} else {
|
||||||
|
selection += @" OR $(db.message.server_id) = ?";
|
||||||
|
}
|
||||||
|
selection_args += mam_message_flag.mam_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,8 +419,18 @@ public class Dino.HistorySync {
|
||||||
page_result = PageResult.TargetReached;
|
page_result = PageResult.TargetReached;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 duplicates_found = db.message.select().where(selection, selection_args).count();
|
// Check for duplicates among the messages of the page.
|
||||||
if (duplicates_found > 0) {
|
var duplicates_qry = db.message.select()
|
||||||
|
.with(db.message.account_id, "=", account.id)
|
||||||
|
.where(selection, selection_args);
|
||||||
|
// We don't want messages from different MAM servers to interfere with each other.
|
||||||
|
if (!query_params.mam_server.equals_bare(account.bare_jid)) {
|
||||||
|
duplicates_qry.with(db.message.counterpart_id, "=", db.get_jid_id(query_params.mam_server));
|
||||||
|
} else {
|
||||||
|
duplicates_qry.with(db.message.type_, "=", Message.Type.CHAT);
|
||||||
|
}
|
||||||
|
var duplicates_count = duplicates_qry.count();
|
||||||
|
if (duplicates_count > 0) {
|
||||||
// We got a duplicate although we thought we have to catch up.
|
// We got a duplicate although we thought we have to catch up.
|
||||||
// There was a server bug where prosody would send all messages if it didn't know the after ID that was given
|
// There was a server bug where prosody would send all messages if it didn't know the after ID that was given
|
||||||
page_result = PageResult.Duplicate;
|
page_result = PageResult.Duplicate;
|
||||||
|
|
Loading…
Reference in a new issue