Ticket #6436: t6436-slowness-query-r7610.diff
| File t6436-slowness-query-r7610.diff, 9.4 KB (added by cboos, 4 years ago) |
|---|
-
trac/ticket/api.py
16 16 17 17 import re 18 18 from datetime import datetime 19 try: 20 import threading 21 except ImportError: 22 import dummy_threading as threading 19 23 20 24 from genshi.builder import tag 21 25 22 26 from trac.config import * 23 27 from trac.core import * 24 from trac.perm import IPermissionRequestor, Permission System, PermissionError28 from trac.perm import IPermissionRequestor, PermissionCache, PermissionSystem 25 29 from trac.resource import IResourceManager 26 from trac.util import Ranges 30 from trac.util import Ranges, arity 27 31 from trac.util.compat import set, sorted 28 32 from trac.util.datefmt import utc 29 33 from trac.util.text import shorten_line, obfuscate_email_address … … 157 161 def __init__(self): 158 162 self.log.debug('action controllers for ticket workflow: %r' % 159 163 [c.__class__.__name__ for c in self.action_controllers]) 164 self._fields_lock = threading.RLock() 160 165 161 166 # Public API 162 167 … … 185 190 186 191 def get_ticket_fields(self): 187 192 """Returns the list of fields available for tickets.""" 193 # This is now cached - as it makes quite a number of things faster, 194 # e.g. #6436 195 if self._fields is None: 196 self._fields_lock.acquire() 197 try: 198 self._fields = self._get_ticket_fields() 199 finally: 200 self._fields_lock.release() 201 return [f.copy() for f in self._fields] 202 203 def reset_ticket_fields(self): 204 self._fields_lock.acquire() 205 try: 206 self._fields = None 207 self.config.touch() # brute force approach for now 208 finally: 209 self._fields_lock.release() 210 211 _fields = None 212 def _get_ticket_fields(self): 188 213 from trac.ticket import model 189 214 190 215 db = self.env.get_db_cnx() … … 195 220 field = {'name': name, 'type': 'text', 'label': name.title()} 196 221 fields.append(field) 197 222 198 # Owner field, can be text or drop-down depending on configuration 223 # Owner field, by default text but can be changed dynamically 224 # into a drop-down depending on configuration (restrict_owner=true) 199 225 field = {'name': 'owner', 'label': 'Owner'} 200 if self.restrict_owner: 201 field['type'] = 'select' 202 perm = PermissionSystem(self.env) 203 field['options'] = perm.get_users_with_permission('TICKET_MODIFY') 204 field['options'].sort() 205 field['optional'] = True 206 else: 207 field['type'] = 'text' 226 field['type'] = 'text' 208 227 fields.append(field) 209 228 210 229 # Description … … 256 275 return fields 257 276 258 277 def get_custom_fields(self): 278 if self._custom_fields is None: 279 self._fields_lock.acquire() 280 try: 281 self._custom_fields = self._get_custom_fields() 282 finally: 283 self._fields_lock.release() 284 return [f.copy() for f in self._custom_fields] 285 286 _custom_fields = None 287 def _get_custom_fields(self): 259 288 fields = [] 260 289 config = self.config['ticket-custom'] 261 290 for name in [option for option, value in config.options() … … 280 309 fields.sort(lambda x, y: cmp(x['order'], y['order'])) 281 310 return fields 282 311 312 def eventually_restrict_owner(self, field, ticket=None): 313 """Restrict given owner field to be a list of users having 314 the TICKET_MODIFY permission (for the given ticket) 315 """ 316 if self.restrict_owner: 317 field['type'] = 'select' 318 possible_owners = [] 319 for user in PermissionSystem(self.env) \ 320 .get_users_with_permission('TICKET_MODIFY'): 321 if not ticket or \ 322 'TICKET_MODIFY' in PermissionCache(self.env, user, 323 ticket.resource): 324 possible_owners.append(user) 325 possible_owners.sort() 326 field['options'] = possible_owners 327 field['optional'] = True 328 283 329 # IPermissionRequestor methods 284 330 285 331 def get_permission_actions(self): -
trac/ticket/web_ui.py
1067 1067 def _prepare_fields(self, req, ticket): 1068 1068 context = Context.from_request(req, ticket.resource) 1069 1069 fields = [] 1070 owner Field = None1070 owner_field = None 1071 1071 for field in ticket.fields: 1072 1072 name = field['name'] 1073 1073 type_ = field['type'] … … 1077 1077 'resolution'): 1078 1078 field['skip'] = True 1079 1079 elif name == 'owner': 1080 TicketSystem(self.env).eventually_restrict_owner(field, ticket) 1081 type_ = field['type'] 1080 1082 field['skip'] = True 1081 1083 if not ticket.exists: 1082 1084 field['label'] = 'Assign to' 1083 1085 if 'TICKET_MODIFY' in req.perm(ticket.resource): 1084 1086 field['skip'] = False 1085 owner Field = field1087 owner_field = field 1086 1088 elif name == 'milestone': 1087 1089 milestones = [(opt, Milestone(self.env, opt)) 1088 1090 for opt in field['options']] … … 1147 1149 fields.append(field) 1148 1150 1149 1151 # Move owner field to end when shown 1150 if owner Field is not None:1151 fields.remove(owner Field)1152 fields.append(owner Field)1152 if owner_field is not None: 1153 fields.remove(owner_field) 1154 fields.append(owner_field) 1153 1155 return fields 1154 1156 1155 1157 def _insert_ticket_data(self, req, ticket, data, author_id, field_changes): -
trac/ticket/model.py
408 408 db.commit() 409 409 self.value = self._old_value = None 410 410 self.name = self._old_name = None 411 TicketSystem(self.env).reset_ticket_fields() 411 412 412 413 def insert(self, db=None): 413 414 assert not self.exists, 'Cannot insert existing %s' % self.type … … 433 434 db.commit() 434 435 self._old_name = self.name 435 436 self._old_value = self.value 437 TicketSystem(self.env).reset_ticket_fields() 436 438 437 439 def update(self, db=None): 438 440 assert self.exists, 'Cannot update non-existent %s' % self.type … … 459 461 db.commit() 460 462 self._old_name = self.name 461 463 self._old_value = self.value 464 TicketSystem(self.env).reset_ticket_fields() 462 465 463 466 def select(cls, env, db=None): 464 467 if not db: … … 545 548 546 549 if handle_ta: 547 550 db.commit() 551 TicketSystem(self.env).reset_ticket_fields() 548 552 549 553 def insert(self, db=None): 550 554 assert not self.exists, 'Cannot insert existing component' … … 564 568 565 569 if handle_ta: 566 570 db.commit() 571 TicketSystem(self.env).reset_ticket_fields() 567 572 568 573 def update(self, db=None): 569 574 assert self.exists, 'Cannot update non-existent component' … … 589 594 590 595 if handle_ta: 591 596 db.commit() 597 TicketSystem(self.env).reset_ticket_fields() 592 598 593 599 def select(cls, env, db=None): 594 600 if not db: … … 669 675 670 676 if handle_ta: 671 677 db.commit() 678 TicketSystem(self.env).reset_ticket_fields() 672 679 673 680 def insert(self, db=None): 674 681 assert self.name, 'Cannot create milestone with no name' … … 688 695 689 696 if handle_ta: 690 697 db.commit() 698 TicketSystem(self.env).reset_ticket_fields() 691 699 692 700 def update(self, db=None): 693 701 assert self.name, 'Cannot update milestone with no name' … … 713 721 714 722 if handle_ta: 715 723 db.commit() 724 TicketSystem(self.env).reset_ticket_fields() 716 725 717 726 def select(cls, env, include_completed=True, db=None): 718 727 if not db: … … 775 784 776 785 if handle_ta: 777 786 db.commit() 787 TicketSystem(self.env).reset_ticket_fields() 778 788 779 789 def insert(self, db=None): 780 790 assert not self.exists, 'Cannot insert existing version' … … 794 804 795 805 if handle_ta: 796 806 db.commit() 807 TicketSystem(self.env).reset_ticket_fields() 797 808 798 809 def update(self, db=None): 799 810 assert self.exists, 'Cannot update non-existent version' … … 819 830 820 831 if handle_ta: 821 832 db.commit() 833 TicketSystem(self.env).reset_ticket_fields() 822 834 823 835 def select(cls, env, db=None): 824 836 if not db: -
trac/ticket/query.py
885 885 orig_time = query_time 886 886 887 887 context = Context.from_request(req, 'query') 888 owner_field = [f for f in query.fields if f['name'] == 'owner'] 889 if owner_field: 890 TicketSystem(self.env).eventually_restrict_owner(owner_field[0]) 888 891 data = query.template_data(context, tickets, orig_list, orig_time, req) 889 892 890 893 # For clients without JavaScript, we add a new constraint here if
