5
5
from django .core .cache .backends .db import Options
6
6
from django .db import connections , router
7
7
from django .utils .functional import cached_property
8
+ from pymongo import IndexModel
8
9
from pymongo .errors import DuplicateKeyError
9
10
10
11
@@ -41,20 +42,29 @@ class CacheEntry:
41
42
self .cache_model_class = CacheEntry
42
43
43
44
def create_indexes (self ):
44
- self .collection .create_index ("expires_at" , expireAfterSeconds = 0 )
45
- self .collection .create_index ("key" , unique = True )
45
+ expires_index = IndexModel ("expires_at" , expireAfterSeconds = 0 )
46
+ key_index = IndexModel ("key" , unique = True )
47
+ self .collection_to_write .create_indexes ([expires_index , key_index ])
46
48
47
49
@cached_property
48
50
def serializer (self ):
49
51
return MongoSerializer (self .pickle_protocol )
50
52
51
53
@property
52
- def _db (self ):
54
+ def _db_to_read (self ):
53
55
return connections [router .db_for_read (self .cache_model_class )]
54
56
55
57
@property
56
- def collection (self ):
57
- return self ._db .get_collection (self ._collection_name )
58
+ def collection_to_read (self ):
59
+ return self ._db_to_read .get_collection (self ._collection_name )
60
+
61
+ @property
62
+ def _db_to_write (self ):
63
+ return connections [router .db_for_write (self .cache_model_class )]
64
+
65
+ @property
66
+ def collection_to_write (self ):
67
+ return self ._db_to_read .get_collection (self ._collection_name )
58
68
59
69
def get (self , key , default = None , version = None ):
60
70
result = self .get_many ([key ], version )
@@ -71,18 +81,18 @@ def get_many(self, keys, version=None):
71
81
if not keys :
72
82
return {}
73
83
keys_map = {self .make_and_validate_key (key , version = version ): key for key in keys }
74
- with self .collection .find (
84
+ with self .collection_to_read .find (
75
85
{"key" : {"$in" : tuple (keys_map )}, ** self ._filter_expired (expired = False )}
76
86
) as cursor :
77
87
return {keys_map [row ["key" ]]: self .serializer .loads (row ["value" ]) for row in cursor }
78
88
79
89
def set (self , key , value , timeout = DEFAULT_TIMEOUT , version = None ):
80
90
key = self .make_and_validate_key (key , version = version )
81
91
serialized_data = self .serializer .dumps (value )
82
- num = self .collection .count_documents ({})
92
+ num = self .collection_to_write .count_documents ({})
83
93
if num >= self ._max_entries :
84
94
self ._cull (num )
85
- return self .collection .update_one (
95
+ return self .collection_to_write .update_one (
86
96
{"key" : key },
87
97
{
88
98
"$set" : {
@@ -97,11 +107,11 @@ def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
97
107
def add (self , key , value , timeout = DEFAULT_TIMEOUT , version = None ):
98
108
key = self .make_and_validate_key (key , version = version )
99
109
serialized_data = self .serializer .dumps (value )
100
- num = self .collection .count_documents ({})
110
+ num = self .collection_to_write .count_documents ({})
101
111
if num >= self ._max_entries :
102
112
self ._cull (num )
103
113
try :
104
- self .collection .update_one (
114
+ self .collection_to_write .update_one (
105
115
{"key" : key , ** self ._filter_expired (expired = True )},
106
116
{
107
117
"$set" : {
@@ -124,7 +134,7 @@ def _cull(self, num):
124
134
try :
125
135
# Delete the first expiration date.
126
136
deleted_from = next (
127
- self .collection .aggregate (
137
+ self .collection_to_write .aggregate (
128
138
[
129
139
{"$sort" : {"expires_at" : - 1 , "key" : 1 }},
130
140
{"$skip" : keep_num },
@@ -136,7 +146,7 @@ def _cull(self, num):
136
146
except StopIteration :
137
147
pass
138
148
else :
139
- self .collection .delete_many (
149
+ self .collection_to_write .delete_many (
140
150
{
141
151
"$or" : [
142
152
{"expires_at" : {"$lt" : deleted_from ["expires_at" ]}},
@@ -152,7 +162,7 @@ def _cull(self, num):
152
162
153
163
def touch (self , key , timeout = DEFAULT_TIMEOUT , version = None ):
154
164
key = self .make_and_validate_key (key , version = version )
155
- res = self .collection .update_one (
165
+ res = self .collection_to_write .update_one (
156
166
{"key" : key }, {"$set" : {"expires_at" : self ._get_expiration_time (timeout )}}
157
167
)
158
168
return res .matched_count > 0
@@ -173,13 +183,16 @@ def _delete_many(self, keys, version=None):
173
183
if not keys :
174
184
return False
175
185
keys = tuple (self .make_and_validate_key (key , version = version ) for key in keys )
176
- return bool (self .collection .delete_many ({"key" : {"$in" : keys }}).deleted_count )
186
+ return bool (self .collection_to_write .delete_many ({"key" : {"$in" : keys }}).deleted_count )
177
187
178
188
def has_key (self , key , version = None ):
179
189
key = self .make_and_validate_key (key , version = version )
180
190
return (
181
- self .collection .count_documents ({"key" : key , ** self ._filter_expired (expired = False )}) > 0
191
+ self .collection_to_read .count_documents (
192
+ {"key" : key , ** self ._filter_expired (expired = False )}
193
+ )
194
+ > 0
182
195
)
183
196
184
197
def clear (self ):
185
- self .collection .delete_many ({})
198
+ self .collection_to_write .delete_many ({})
0 commit comments