Completed
Push — master ( ca5031...286e59 )
by Bertrand
57s
created

cachalot._get_tables()   A

Complexity

Conditions 3

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 3
dl 0
loc 3
rs 10
1
# coding: utf-8
2
3
from __future__ import unicode_literals
4
5
from django.conf import settings
6
from django.db import connections
7
from django.utils.six import string_types
8
9
from .cache import cachalot_caches
10
from .signals import post_invalidation
11
from .utils import _get_table_cache_key, _invalidate_tables
12
13
14
__all__ = ('invalidate', 'get_last_invalidation')
15
16
17
def _cache_db_tables_iterator(tables, cache_alias, db_alias):
18
    no_tables = not tables
19
    cache_aliases = settings.CACHES if cache_alias is None else (cache_alias,)
20
    db_aliases = settings.DATABASES if db_alias is None else (db_alias,)
21
    for db_alias in db_aliases:
22
        if no_tables:
23
            tables = connections[db_alias].introspection.table_names()
24
        if tables:
25
            for cache_alias in cache_aliases:
26
                yield cache_alias, db_alias, tables
27
28
29
def _get_tables(tables_or_models):
30
    return [o if isinstance(o, string_types) else o._meta.db_table
31
            for o in tables_or_models]
32
33
34
def invalidate(*tables_or_models, **kwargs):
35
    """
36
    Clears what was cached by django-cachalot implying one or more SQL tables
37
    or models from ``tables_or_models``.
38
    If ``tables_or_models`` is not specified, all tables found in the database
39
    (including those outside Django) are invalidated.
40
41
    If ``cache_alias`` is specified, it only clears the SQL queries stored
42
    on this cache, otherwise queries from all caches are cleared.
43
44
    If ``db_alias`` is specified, it only clears the SQL queries executed
45
    on this database, otherwise queries from all databases are cleared.
46
47
    :arg tables_or_models: SQL tables names or models (or combination of both)
48
    :type tables_or_models: tuple of strings or models
49
    :arg cache_alias: Alias from the Django ``CACHES`` setting
50
    :type cache_alias: string or NoneType
51
    :arg db_alias: Alias from the Django ``DATABASES`` setting
52
    :type db_alias: string or NoneType
53
    :returns: Nothing
54
    :rtype: NoneType
55
    """
56
    # TODO: Replace with positional arguments when we drop Python 2 support.
57
    cache_alias = kwargs.pop('cache_alias', None)
58
    db_alias = kwargs.pop('db_alias', None)
59
    for k in kwargs:
60
        raise TypeError(
61
            "invalidate() got an unexpected keyword argument '%s'" % k)
62
63
    invalidated = set()
64
    for cache_alias, db_alias, tables in _cache_db_tables_iterator(
65
            _get_tables(tables_or_models), cache_alias, db_alias):
66
        _invalidate_tables(
67
            cachalot_caches.get_cache(cache_alias, db_alias), db_alias, tables)
68
        invalidated.update(tables)
69
70
    for table in invalidated:
71
        post_invalidation.send(table, db_alias=db_alias)
72
73
74
def get_last_invalidation(*tables_or_models, **kwargs):
75
    """
76
    Returns the timestamp of the most recent invalidation of the given
77
    ``tables_or_models``.  If ``tables_or_models`` is not specified,
78
    all tables found in the database (including those outside Django) are used.
79
80
    If ``cache_alias`` is specified, it only fetches invalidations
81
    in this cache, otherwise invalidations in all caches are fetched.
82
83
    If ``db_alias`` is specified, it only fetches invalidations
84
    for this database, otherwise invalidations for all databases are fetched.
85
86
    :arg tables_or_models: SQL tables names or models (or combination of both)
87
    :type tables_or_models: tuple of strings or models
88
    :arg cache_alias: Alias from the Django ``CACHES`` setting
89
    :type cache_alias: string or NoneType
90
    :arg db_alias: Alias from the Django ``DATABASES`` setting
91
    :type db_alias: string or NoneType
92
    :returns: The timestamp of the most recent invalidation
93
    :rtype: float
94
    """
95
    # TODO: Replace with positional arguments when we drop Python 2 support.
96
    cache_alias = kwargs.pop('cache_alias', None)
97
    db_alias = kwargs.pop('db_alias', None)
98
    for k in kwargs:
99
        raise TypeError("get_last_invalidation() got an unexpected "
100
                        "keyword argument '%s'" % k)
101
102
    last_invalidation = 0.0
103
    for cache_alias, db_alias, tables in _cache_db_tables_iterator(
104
            _get_tables(tables_or_models), cache_alias, db_alias):
105
        table_cache_keys = [_get_table_cache_key(db_alias, t) for t in tables]
106
        invalidations = cachalot_caches.get_cache(
107
            cache_alias, db_alias).get_many(table_cache_keys).values()
108
        if invalidations:
109
            current_last_invalidation = max(invalidations)
110
            if current_last_invalidation > last_invalidation:
111
                last_invalidation = current_last_invalidation
112
    return last_invalidation
113