Projet

Général

Profil

0001-misc-limit-query-to-recent-sessions-when-checking-fo.patch

Frédéric Péters, 19 juin 2019 15:53

Télécharger (5,79 ko)

Voir les différences:

Subject: [PATCH] misc: limit query to recent sessions when checking for locked
 objects (#34097)

 wcs/sessions.py | 21 ++++++++++++++++++---
 wcs/sql.py      | 26 ++++++++++++++++++++++----
 2 files changed, 40 insertions(+), 7 deletions(-)
wcs/sessions.py
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17
import os
17 18
import time
18 19
import uuid
19 20

  
......
72 73
                del self.visiting_objects[object_key]
73 74
        self.visiting_objects[key] = current_timestamp
74 75

  
76
    @classmethod
77
    def select_recent(cls, seconds=30*60, **kwargs):
78
        objects_dir = cls.get_objects_dir()
79
        if not os.path.exists(objects_dir):
80
            return []
81
        ids = []
82
        time_limit = time.time() - seconds
83
        for filename in os.listdir(objects_dir):
84
            if filename[0] == '.':
85
                continue
86
            if os.stat(os.path.join(objects_dir, filename)).st_mtime > time_limit:
87
                ids.append(filename)
88
        return cls.get_ids(ids, **kwargs)
89

  
75 90
    @classmethod
76 91
    def get_visited_objects(cls, exclude_user=None):
77 92
        # return the list of visited objects
78 93
        current_timestamp = time.time()
79 94
        visited_objects = {}
80
        for session in cls.select(ignore_errors=True):
95
        for session in cls.select_recent(ignore_errors=True):
81 96
            if session.user and session.user == exclude_user:
82 97
                continue
83 98
            visiting_objects = getattr(session, 'visiting_objects', None)
......
90 105

  
91 106
    @classmethod
92 107
    def get_sessions_with_visited_object(cls, object_key):
93
        for session in cls.select(ignore_errors=True):
108
        for session in cls.select_recent(ignore_errors=True):
94 109
            visiting_objects = getattr(session, 'visiting_objects', None)
95 110
            if not visiting_objects:
96 111
                continue
......
114 129
        if object_key in (getattr(self, 'visiting_objects', None) or {}):
115 130
            del self.visiting_objects[object_key]
116 131
        # and from others
117
        for session in self.__class__.select(ignore_errors=True):
132
        for session in self.__class__.select_recent(ignore_errors=True):
118 133
            if session.id == self.id:
119 134
                continue
120 135
            visiting_objects = getattr(session, 'visiting_objects', None)
wcs/sql.py
659 659
                      AND table_name = %s''', (table_name,))
660 660
    existing_fields = set([x[0] for x in cur.fetchall()])
661 661

  
662
    needed_fields = set(['id', 'session_data', 'name_identifier', 'visiting_objects_keys'])
662
    needed_fields = set(['id', 'session_data', 'name_identifier',
663
        'visiting_objects_keys', 'last_update_time'])
664

  
665
    # migrations
666
    if not 'last_update_time' in existing_fields:
667
        cur.execute('''ALTER TABLE %s ADD COLUMN last_update_time timestamp DEFAULT NOW()''' % table_name)
668
        cur.execute('''CREATE INDEX %s_ts ON %s (last_update_time)''' % (
669
                                table_name, table_name))
663 670

  
664 671
    # delete obsolete fields
665 672
    for field in (existing_fields - needed_fields):
......
1819 1826
        ('session_data', 'bytea'),
1820 1827
    ]
1821 1828

  
1829
    @classmethod
1830
    @guard_postgres
1831
    def select_recent(cls, seconds=30*60, **kwargs):
1832
        clause = [GreaterOrEqual('last_update_time', datetime.datetime.now() - datetime.timedelta(seconds=seconds))]
1833
        return cls.select(clause=clause, **kwargs)
1834

  
1822 1835
    @guard_postgres
1823 1836
    def store(self):
1824 1837
        sql_dict = {
......
1828 1841
            # table, they are ignored when loading the data.
1829 1842
            'name_identifier': self.name_identifier,
1830 1843
            'visiting_objects_keys': self.visiting_objects.keys() if getattr(self, 'visiting_objects') else None,
1844
            'last_update_time': datetime.datetime.now(),
1831 1845
        }
1832 1846

  
1833 1847
        conn, cur = get_connection_and_cursor()
......
1877 1891

  
1878 1892
        sql_statement = '''SELECT %s
1879 1893
                             FROM %s
1880
                            WHERE %%(value)s = ANY(visiting_objects_keys)''' % (
1894
                            WHERE %%(value)s = ANY(visiting_objects_keys)
1895
                              AND last_update_time > (now() - interval '30 minutes')
1896
                        ''' % (
1881 1897
                                    ', '.join([x[0] for x in cls._table_static_fields]
1882 1898
                                              + cls.get_data_fields()),
1883 1899
                                    cls._table_name)
......
2174 2190
    return result
2175 2191

  
2176 2192

  
2177
SQL_LEVEL = 31
2193
SQL_LEVEL = 32
2178 2194

  
2179 2195
def migrate_global_views(conn, cur):
2180 2196
    cur.execute('''SELECT COUNT(*) FROM information_schema.tables
......
2291 2307
        # 24: add index on evolution(formdata_id)
2292 2308
        for formdef in FormDef.select():
2293 2309
            do_formdef_indexes(formdef, created=False, conn=conn, cur=cur)
2294
    if sql_level < 25:
2310
    if sql_level < 32:
2311
        # 25: create session_table
2312
        # 32: add last_update_time column to session table
2295 2313
        do_session_table()
2296 2314
    if sql_level < 30:
2297 2315
        # 30: actually remove evo.who on anonymised formdatas
2298
-