[IMP] mail: reduce number of lookups in channels dict

Instead of using the channel's ids to communicate between the client action and
the chat manager, directly use the channel itself. This prevents many lookups
in the channels dict to retrieve the channel from its id.
This commit is contained in:
Aaron Bohy
2015-10-02 15:49:36 +02:00
parent 986f449909
commit 8908d5ccab
2 changed files with 64 additions and 65 deletions
+20 -22
View File
@@ -196,9 +196,8 @@ function make_channel (data, options) {
return channel;
}
function get_channel_cache (channel_id, domain) {
function get_channel_cache (channel, domain) {
var stringified_domain = JSON.stringify(domain || []);
var channel = _.findWhere(channels, {id: channel_id});
if (!channel.cache[stringified_domain]) {
channel.cache[stringified_domain] = {
all_history_loaded: false,
@@ -218,11 +217,11 @@ function remove_message_from_channel (channel_id, message) {
}
// options: domain, load_more
function fetch_from_channel (channel_id, options) {
function fetch_from_channel (channel, options) {
var domain =
(channel_id === "channel_inbox") ? [['needaction', '=', true]] :
(channel_id === "channel_starred") ? [['starred', '=', true]] :
[['channel_ids', 'in', channel_id]];
(channel.id === "channel_inbox") ? [['needaction', '=', true]] :
(channel.id === "channel_starred") ? [['starred', '=', true]] :
[['channel_ids', 'in', channel.id]];
options = options || {};
if (options.domain) {
@@ -230,7 +229,7 @@ function fetch_from_channel (channel_id, options) {
}
if (options.load_more) {
var min_message_id = _.chain(messages)
.filter(function (msg) { return _.contains(msg.channel_ids, channel_id); })
.filter(function (msg) { return _.contains(msg.channel_ids, channel.id); })
.pluck("id")
.min()
.value();
@@ -239,7 +238,7 @@ function fetch_from_channel (channel_id, options) {
}
return MessageModel.call('message_fetch', [domain], {limit: LIMIT}).then(function (msgs) {
var cache = get_channel_cache(channel_id, options.domain);
var cache = get_channel_cache(channel, options.domain);
cache.message_ids = _.uniq(cache.message_ids.concat(_.pluck(msgs, 'id')));
if (!cache.all_history_loaded) {
@@ -248,7 +247,7 @@ function fetch_from_channel (channel_id, options) {
cache.loaded = true;
_.each(msgs, function (msg) {
add_message(msg, {channel_id: channel_id, silent: true});
add_message(msg, {channel_id: channel.id, silent: true});
});
return _.filter(messages, function (m) {
return _.contains(cache.message_ids, m.id);
@@ -290,22 +289,23 @@ var chat_manager = {
get_messages: function (options) {
if ('channel_id' in options) { // channel message
var channel_cache = get_channel_cache(options.channel_id, options.domain);
var channel = this.get_channel(options.channel_id);
var channel_cache = get_channel_cache(channel, options.domain);
if (channel_cache.loaded) {
return $.when(_.filter(messages, function (message) {
return _.contains(message.channel_ids, options.channel_id);
}));
} else {
return fetch_from_channel(options.channel_id);
return fetch_from_channel(channel);
}
} else { // chatter message
}
},
fetch: function (channel_id, domain) {
return fetch_from_channel(channel_id, {domain: domain});
fetch: function (channel, domain) {
return fetch_from_channel(channel, {domain: domain});
},
fetch_more: function (channel_id, domain) {
return fetch_from_channel(channel_id, {domain: domain, load_more: true});
fetch_more: function (channel, domain) {
return fetch_from_channel(channel, {domain: domain, load_more: true});
},
/**
* Fetches chatter messages from their ids
@@ -342,8 +342,8 @@ var chat_manager = {
return _.findWhere(channels, {id: id}) || channels[0];
},
all_history_loaded: function (channel_id, domain) {
return get_channel_cache(channel_id, domain).all_history_loaded;
all_history_loaded: function (channel, domain) {
return get_channel_cache(channel, domain).all_history_loaded;
},
get_emojis: function() {
@@ -354,8 +354,7 @@ var chat_manager = {
return needaction_counter;
},
detach_channel: function (channel_id) {
var channel = this.get_channel(channel_id);
detach_channel: function (channel) {
return ChannelModel.call("channel_minimize", [channel.uuid, true]);
},
remove_chatter_messages: function (model) {
@@ -384,13 +383,12 @@ var chat_manager = {
});
},
unsubscribe: function (channel_id) {
unsubscribe: function (channel) {
var def;
var channel = chat_manager.get_channel(channel_id);
if (channel.type === "dm") {
def = ChannelModel.call('channel_pin', [channel.uuid, false]);
} else {
def = ChannelModel.call('action_unfollow', [[channel_id]]);
def = ChannelModel.call('action_unfollow', [[channel.id]]);
}
return def.then(function () {
channels = _.without(channels, channel);
+44 -43
View File
@@ -91,7 +91,7 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
"click .o_mail_chat_channel_item": function (event) {
event.preventDefault();
var channel_id = this.$(event.currentTarget).data('channel-id');
this.set_channel(channel_id);
this.set_channel(chat_manager.get_channel(channel_id));
},
"click .o_mail_sidebar_title .o_add": function (event) {
event.preventDefault();
@@ -108,18 +108,20 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
event.stopPropagation();
var self = this;
var channel_id = $(event.target).data("channel-id");
chat_manager.unsubscribe(channel_id).then(function () {
self.render_sidebar();
self.set_channel("channel_inbox");
});
chat_manager
.unsubscribe(chat_manager.get_channel(channel_id))
.then(function () {
self.render_sidebar();
self.set_channel(chat_manager.get_channel("channel_inbox"));
});
},
},
on_attach_callback: function () {
this.thread.scroll_to({offset: this.channels_scrolltop[this.channel_id]});
this.thread.scroll_to({offset: this.channels_scrolltop[this.channel.id]});
},
on_detach_callback: function () {
this.channels_scrolltop[this.channel_id] = this.thread.get_scrolltop();
this.channels_scrolltop[this.channel.id] = this.thread.get_scrolltop();
},
init: function(parent, action) {
@@ -141,7 +143,9 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
};
var dataset = new data.DataSetSearch(this, 'mail.message');
var view_id = (this.action && this.action.search_view_id && this.action.search_view_id[0]) || false;
var default_channel = this.action.context.active_id || this.action.params.default_active_id || 'channel_inbox';
var default_channel_id = this.action.context.active_id ||
this.action.params.default_active_id ||
'channel_inbox';
this.searchview = new SearchView(this, dataset, view_id, {}, options);
this.searchview.on('search_data', this, this.on_search);
@@ -185,13 +189,13 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
this.render_sidebar();
return $.when(def1, def2, def3, def4)
.then(this.set_channel.bind(this, default_channel))
.then(this.set_channel.bind(this, chat_manager.get_channel(default_channel_id)))
.then(function () {
chat_manager.bus.on('new_message', self, self.on_new_message);
chat_manager.bus.on('update_message', self, self.on_update_message);
chat_manager.bus.on('new_channel', self, self.on_new_channel);
chat_manager.bus.on('anyone_listening', self, function (channel, query) {
query.is_displayed = query.is_displayed || channel.id === self.channel_id;
query.is_displayed = query.is_displayed || channel.id === self.channel.id;
});
chat_manager.bus.on('update_needaction', self, self.on_update_needaction);
});
@@ -284,16 +288,14 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
});
},
set_channel: function (channel_id) {
set_channel: function (channel) {
var self = this;
// Store scroll position of previous channel
if (this.channel_id) {
this.channels_scrolltop[this.channel_id] = this.thread.get_scrolltop();
if (this.channel) {
this.channels_scrolltop[this.channel.id] = this.thread.get_scrolltop();
}
var new_channel_scrolltop = this.channels_scrolltop[channel_id];
var channel = chat_manager.get_channel(channel_id);
channel_id = channel.id;
this.channel_id = channel_id;
var new_channel_scrolltop = this.channels_scrolltop[channel.id];
this.channel = channel;
this.set("title", channel.name);
this.$buttons.toggle(channel.type !== "static");
this.$buttons
@@ -301,12 +303,12 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
.toggle(channel.type !== "dm");
this.update_cp();
this.action.context.active_id = channel_id;
this.action.context.active_ids = [channel_id];
this.action.context.active_id = channel.id;
this.action.context.active_ids = [channel.id];
this.$('.o_mail_chat_channel_item')
.removeClass('o_active')
.filter('[data-channel-id=' + channel_id + ']')
.filter('[data-channel-id=' + channel.id + ']')
.removeClass('o_unread_message')
.addClass('o_active');
@@ -320,15 +322,15 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
}
self.action_manager.do_push_state({
action: self.action.id,
active_id: self.channel_id,
active_id: self.channel.id,
});
});
},
fetch_and_render_thread: function () {
var self = this;
return chat_manager.fetch(this.channel_id, this.domain).then(function(result) {
var history_loaded = chat_manager.all_history_loaded(self.channel_id, self.domain);
return chat_manager.fetch(this.channel, this.domain).then(function(result) {
var history_loaded = chat_manager.all_history_loaded(self.channel, self.domain);
self.thread.render(result, {display_load_more: !history_loaded});
});
},
@@ -339,9 +341,9 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
var oldest_msg_selector = '.o_thread_message[data-message-id="' + oldest_msg_id + '"]';
var offset = -framework.getPosition(document.querySelector(oldest_msg_selector)).top;
return chat_manager
.fetch_more(this.channel_id, this.domain)
.fetch_more(this.channel, this.domain)
.then(function(result) {
var history_loaded = chat_manager.all_history_loaded(self.channel_id, self.domain);
var history_loaded = chat_manager.all_history_loaded(self.channel, self.domain);
self.thread.render(result, {display_load_more: !history_loaded});
offset += framework.getPosition(document.querySelector(oldest_msg_selector)).top;
self.thread.scroll_to({offset: offset});
@@ -390,11 +392,11 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
this.update_cp(); // do not reload the client action, just display it, but a refresh of the control panel is needed.
this.action_manager.do_push_state({
action: this.action.id,
active_id: this.channel_id,
active_id: this.channel.id,
});
},
on_post_message: function (message) {
message.channel_id = this.channel_id;
message.channel_id = this.channel.id;
chat_manager
.post_message(message)
.fail(function () {
@@ -403,13 +405,13 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
},
on_new_message: function (message) {
var self = this;
if (_.contains(message.channel_ids, this.channel_id)) {
if (_.contains(message.channel_ids, this.channel.id)) {
this.fetch_and_render_thread().then(function () {
self.thread.scroll_to({id: message.id});
});
}
// Indicate in the sidebar that there is a new message in the corresponding channels
_.each(_.without(message.channel_ids, this.channel_id), function (channel_id) {
_.each(_.without(message.channel_ids, this.channel.id), function (channel_id) {
self.$('.o_mail_chat_channel_item')
.filter('[data-channel-id=' + channel_id + ']')
.addClass('o_unread_message');
@@ -419,20 +421,21 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
},
on_update_message: function (message) {
var self = this;
if ((this.channel_id === "channel_starred" && !message.is_starred) ||
(this.channel_id === "channel_inbox" && !message.is_needaction)) {
chat_manager.fetch(this.channel_id, this.domain).then(function (messages) {
var history_loaded = chat_manager.all_history_loaded(self.channel_id, self.domain);
var current_channel_id = this.channel.id;
if ((current_channel_id === "channel_starred" && !message.is_starred) ||
(current_channel_id === "channel_inbox" && !message.is_needaction)) {
chat_manager.fetch(this.channel, this.domain).then(function (messages) {
var history_loaded = chat_manager.all_history_loaded(self.channel, self.domain);
self.thread.remove_message_and_render(message.id, messages, {display_load_more: !history_loaded});
});
} else if (_.contains(message.channel_ids, this.channel_id)) {
} else if (_.contains(message.channel_ids, current_channel_id)) {
this.fetch_and_render_thread();
}
},
on_new_channel: function (channel) {
this.render_sidebar();
if (channel.autoswitch) {
this.set_channel(channel.id);
this.set_channel(channel);
}
},
on_update_needaction: function () {
@@ -443,23 +446,21 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
},
on_click_button_invite: function () {
var channel = chat_manager.get_channel(this.channel_id);
var title = _.str.sprintf(_t('Invite people to %s'), channel.name);
new PartnerInviteDialog(this, title, this.channel_id).open();
var title = _.str.sprintf(_t('Invite people to %s'), this.channel.name);
new PartnerInviteDialog(this, title, this.channel.id).open();
},
on_click_button_detach: function () {
chat_manager.detach_channel(this.channel_id);
chat_manager.detach_channel(this.channel);
},
on_click_button_unsubscribe: function () {
var self = this;
var channel = chat_manager.get_channel(this.channel_id);
chat_manager
.unsubscribe(channel.id)
.unsubscribe(this.channel)
.then(this.set_channel.bind(this, "channel_inbox"))
.then(this.render_sidebar.bind(this))
.then(function () {
var msg = _.str.sprintf(_t('You unsubscribed from <b>%s</b>.'), channel.name);
var msg = _.str.sprintf(_t('You unsubscribed from <b>%s</b>.'), self.channel.name);
self.do_notify(_t("Unsubscribed"), msg);
});
},
@@ -467,7 +468,7 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
this.do_action({
type: 'ir.actions.act_window',
res_model: "mail.channel",
res_id: this.channel_id,
res_id: this.channel.id,
views: [[false, 'form']],
target: 'current'
}, {