-
-
Notifications
You must be signed in to change notification settings - Fork 588
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MIG] mail_tracking: Migration to 11.0 #244
Conversation
thanks @chienandalu ! please could you review travis? is in red |
@rafaelbn I'm on it. I had an old v11 instance in wich test worked. So I have to debug what change in |
So travis won't pass due to this issue: odoo/odoo#23808 Wich affects to Without that module installed tests pass with no problem at all in my local... |
@simahawk maybe you can find a workaround for making green again the branch |
@pedrobaeza branch 11.0 is green AFAIS. For the issue here I've no clue ATM. @chienandalu can you report here which domain do you get and which is the offending leaf here? Then you could improve the test cases or add a new one here so that we are sure that this case too is covered w/ tests. BTW I'll have to work on mail_digest for some improvements in the next 2 weeks. I will have a look at this if not solved yet. |
Hi @simahawk You can test it like this:
def test_notify_domains_only_recipients(self):
# we don't set recipients
# because we call `_get_notify_by_email_domain` directly
self.partner1.real_user_id.notification_type = 'email'
self.partner2.real_user_id.notification_type = 'email'
partners = self.partner1 + self.partner2
# followers
self.partner3.message_subscribe(self.partner2.ids)
# partner1 is the only recipient
message = self.message_model.create({
'body': 'My Body',
'res_id': self.partner3.id,
'model': 'res.partner',
'partner_ids': [(4, self.partner1.id), (4, self.partner_alt.id)]
})
domain = partners._get_notify_by_email_domain(message)
# we find both of them since partner2 is a follower
self._assert_found(self.partner1, domain)
self._assert_found(self.partner2, domain)
self._assert_found(self.partner_alt, domain)
# no one here in digest mode
domain = partners._get_notify_by_email_domain(message, digest=True)
self._assert_found(self.partner1, domain, not_found=True)
self._assert_found(self.partner2, domain, not_found=True) |
@chienandalu if w/ "normal partner" you mean a partner w/ no user... then you are right. It does not pass. I'm checking. |
@simahawk Sure, that's what I meant 😅 |
@chienandalu review wlcm :) #253 |
Please rebase |
de57fec
to
74f5229
Compare
Rebased and a little commit squash |
@yajo please review |
mail_tracking/__manifest__.py
Outdated
@@ -0,0 +1,34 @@ | |||
# -*- coding: utf-8 -*- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
drop coding headers
mail_tracking/controllers/main.py
Outdated
reg = registry(db) | ||
except OperationalError: | ||
_logger.warning("Selected BD '%s' not found", db) | ||
except: # pragma: no cover |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
except Exception:
and remove the comment
if match: | ||
try: | ||
tracking_email_id = int(match.group(1)) | ||
except: # pragma: no cover |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
except Exception
or ValueError
if is related to int
call
mail_server = mail_server_ids[0] if mail_server_ids else None | ||
if mail_server: | ||
smtp_server_used = mail_server.smtp_host | ||
else: # pragma: no cover |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment needed for?
if tracking.partner_id: | ||
partners_already |= tracking.partner_id | ||
# Search all recipients for this message | ||
if message.partner_ids: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
recordsets operation can be slow compared to normal sets operations.
You could build a set or a dict ID: name (the only values that you are going to use below)
@api.model | ||
def email_is_bounced(self, email): | ||
if email: | ||
return len(self._email_score_tracking_filter([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wouldn't be better to use search_count here, especially if - as stated above - we gonna have tons of records?
if event and event.recipient_address: | ||
recipients.append(event.recipient_address) | ||
else: | ||
recipients = list( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
list()
needed for? mapped
already returns an iterable...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This oddities tend to come from 2to3
. I don't know exactly attending to wich rule. Fixed anyway.
this.bind_events(); | ||
}, | ||
render: function(messages, options) { | ||
var MessageModel = new data.DataSetSearch(this, 'mail.message', session.context); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DataSet*
are deprecate and models too. You should use _rpc
@chienandalu please finish this so that we can merge it. |
Thanks for your comments @simahawk Take a look now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chienandalu small glitches but I'm approving so that I won't block you anymore once you've addressed them 😉
mail_tracking/models/mail_message.py
Outdated
@@ -35,8 +34,8 @@ def tracking_status(self): | |||
res = {} | |||
for message in self: | |||
partner_trackings = [] | |||
partners_already = self.env['res.partner'] | |||
partners = self.env['res.partner'] | |||
partners_already = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't need this list, the dict is enough. lambda x: x.id not in partners
will work.
mail_tracking/controllers/main.py
Outdated
@@ -22,7 +21,7 @@ def _env_get(db, callback, tracking_id, event_type, **kw): | |||
reg = registry(db) | |||
except OperationalError: | |||
_logger.warning("Selected BD '%s' not found", db) | |||
except: # pragma: no cover | |||
except Exception: # pragma: no cover |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove pragma comment
mail_tracking/models/mail_message.py
Outdated
partners[p.id] = p.name | ||
# If there is partners not included, then status is 'unknown' | ||
partner_trackings += [ | ||
('unkown', False, partners[x], x) for x in partners.keys()] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
('unkown', False, pid, name) for pid, name in partners.items()
Please @yajo make a review here in order to merge. Thank you! |
Take into account #257 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The migration looks good overall, but there are some points where things have changed with no good reason for it, and there is another where a change would be really appreciated. More details below.
Thanks!
mail_tracking/models/mail_message.py
Outdated
partners[p.id] = p.name | ||
for p in message.needaction_partner_ids.filtered( | ||
lambda x: x.id not in partners_already): | ||
partners[p.id] = p.name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm not wrong, with the change in this method you're doing the same thing as before, but avoiding the use of recordsets. However recordsets are not harmful; they help making code more understandable.
Would you mind leaving it as it was? Thanks 😊
@@ -102,10 +101,10 @@ def _email_score_tracking_filter(self, domain, order='time desc', | |||
@api.model | |||
def email_is_bounced(self, email): | |||
if email: | |||
return len(self._email_score_tracking_filter([ | |||
return self.search_count([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For what I can see here, we have 2 options:
-
Remove the
_email_score_tracking_filter
method, since it is not being used now. -
Change the
_email_score_tracking_filter
signature to be(*args, **kwargs)
, which get passed down toself.search(*args, **kwargs)
.Then, call here to
_email_score_tracking_filter
, we addcount=True
as an argument, which acts just likesearch_count
, but makes the count in the DB side, which is also more performant.
I think you should check if any submodule overwrites the method, to make the sane choice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems that nobody is using this. I chose to erase the method
@@ -197,7 +196,7 @@ def _partners_email_bounced_set(self, reason, event=None): | |||
if event and event.recipient_address: | |||
recipients.append(event.recipient_address) | |||
else: | |||
recipients = list(filter(None, self.mapped('recipient_address'))) | |||
recipients = [x for x in self.mapped('recipient_address') if x] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see no benefit on this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for the sake of clarity
}; | ||
this.do_action(action); | ||
}, | ||
bind_events: function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to remove this method and add the events as a class property using the extension method you can see here.
This way we leverage Odoo framework to do the binding...
}, | ||
start: function () { | ||
this._super(); | ||
this.bind_events(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... and we avoid the need to overwrite this method too.
}); | ||
self._rpc({ | ||
model: 'mail.message', | ||
method: 'tracking_status', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This thing you're doing here is not exactly wrong, but think about it: every time the chat thread is rendered (which can happens i.e. when removing a message), you're making an additional RPC call and waiting for it to resolve until you actually render the thread.
Since reading mail threads is so common in Odoo, they designed it in a way that uses the web bus and caches messages internally, so it reduces RPC calls and improves responsiveness. Here, we're introducing a bottleneck that honestly I'd prefer to avoid.
By digging into the made calls, you can see that the web client ultimately calls the model's message_fetch
method. Then, it would be much better to simply overwrite that method in the backend and avoid these RPC calls. The JS code would be much less too now.
This would be a really big performance improvement. Would you do it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I'd say that what you propose is alredy happening here: https://github.com/OCA/social/pull/244/files#diff-4e1cf268ea32e1266c1e39d18db0d429R66 Wich is a common point in the already exisiting rpc calls. Indeed, this code could be erased with no harm. Don't you think this method was made to have tighter check of the thread messages status?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand. For what I can see, this could be erased. Could you check please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to work as before. I guess it will lower down the refresh rate but, as you said, it will release a good bunch of unnecesary rpc calls.
@chienandalu please review @yajo comments please. Thanks! |
@chienandalu please remember to add #257 !! Thanks! |
…s and contacts to bounce (OCA#133)
As regular users can't access this object.
* [FIX] Only one data-odoo-tracking-email tag in each email * [FIX] Get status even in multicompany instances
On our server, queries based on "mail_tracking_event"."tracking_email_id" improved from 501,924 ms to 1,840 ms queries based on "mail_tracking_email"."mail_message_id" improved from 167,436 ms to 3,223 ms The last ones are run several times when a thread has many messages
f63de02
to
72ab11e
Compare
72ab11e
to
fd6ecb2
Compare
@yajo give your final review |
fd6ecb2
to
a529e15
Compare
Mail tracking
This module shows email notification tracking status for any messages in
mail thread (chatter). Each notified partner will have an intuitive icon just
right to his name.
cc @Tecnativa