-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMiniCache.py
132 lines (100 loc) · 3.29 KB
/
MiniCache.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import time
import threading
import copy
from datetime import datetime, timedelta
from threading import Timer
from functools import partial
def seconds(n):
return n
def minutes(n):
return n * 60
def hours(n):
return n * 60 * 60
class Interval(object):
def __init__(self, interval, function, args=[], kwargs={}):
"""
Runs the function at a specified interval with given arguments.
"""
self.interval = interval
self.function = partial(function, *args, **kwargs)
self.running = False
self._timer = None
def __call__(self):
"""
Handler function for calling the partial and continuting.
"""
self.running = False # mark not running
self.start() # reset the timer for the next go
self.function() # call the partial function
def start(self):
"""
Starts the interval and lets it run.
"""
if self.running:
# Don't start if we're running!
return
# Create the timer object, start and set state.
self._timer = Timer(self.interval, self)
self._timer.start()
self.running = True
def stop(self):
"""
Cancel the interval (no more function calls).
"""
if self._timer:
self._timer.cancel()
self.running = False
self._timer = None
class MiniCache(dict):
def __init__(self):
self._cache = {}
self.watcher = Interval(0.1, self._cleaner)
self.watcher.start()
def set(self, key, value, ttl=None):
if not ttl:
self._cache[key] = {"value": value}
else:
self._cache[key] = {"value": value, "ttl": datetime.now() + timedelta(seconds=ttl)}
def get(self, key):
try:
return self._cache[key]["value"]
except KeyError:
return None
def flush_all(self):
self._cache = {}
self.watcher.stop()
def flush_all_temporary_keys(self):
tempcache = copy.copy(self._cache)
for key, value in self._cache.items():
if 'ttl' not in value:
tempcache[key] = value
self._cache = tempcache
def flush_all_parament_keys(self):
tempcache = copy.copy(self._cache)
for key, value in self._cache.items():
if 'ttl' in value:
tempcache[key] = value
self._cache = tempcache
def num_of_temporary_keys(self):
return sum(1 for _, value in self._cache.items() if 'ttl' in value)
def num_of_parament_keys(self):
return sum(1 for _, value in self._cache.items() if 'ttl' not in value)
def num_of_keys(self):
return len(self._cache)
def _cleaner(self):
try:
for key, value in self._cache.items():
if "ttl" not in value:
continue
if datetime.now() >= value["ttl"]:
del self._cache[key]
except RuntimeError:
pass
if __name__ == '__main__':
cache = MiniCache()
cache.set("game", "Oni 2")
print(cache.num_of_keys())
cache.set("game2", "Oni 4")
print(cache.num_of_keys())
cache.set("expired_key", "Oni 5", ttl=seconds(5))
cache.flush_all()