-
Notifications
You must be signed in to change notification settings - Fork 18
/
Redis.py
116 lines (92 loc) · 3.19 KB
/
Redis.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
# BSD Licensed, Copyright (c) 2006-2010 TileCache Contributors
from TileCache.Cache import Cache
import time
class Redis(Cache):
"""Redis-based caching mechanism"""
def __init__(self, host, port, expiration=0, **kwargs):
"""Initialize redis"""
Cache.__init__(self, **kwargs)
import redis
self.cache = redis.StrictRedis(host=host, port=port, db=0)
self.expiration = int(expiration)
def getKey(self, tile):
"""Construct the cache key for the given tile.
:param tile: A tile
:type tile: TileCache.Layer.Tile
:rtype: str or unicode
"""
return ":".join(map(str, [tile.layer.name, tile.x, tile.y, tile.z]))
def getLockName(self, tile):
"""Construct the lock name for the given tile.
:param tile: A tile
:type tile: TileCache.Layer.Tile
:rtype: str or unicode
"""
return self.getKey(tile) + ":lock"
def get(self, tile):
"""Retrieve the cached data for the given tile.
:param tile: A tile
:type tile: TileCache.Layer.Tile
:rtype: str or unicode
"""
key = self.getKey(tile)
tile.data = self.cache.hget(key, 'data')
return tile.data
def set(self, tile, data):
"""Cache data for the given tile.
:param tile: A tile
:type tile: TileCache.Layer.Tile
:rtype: str or unicode
"""
if self.readonly:
return data
key = self.getKey(tile)
pipeline = self.cache.pipeline()
pipeline.hmset(key, {'data': data, 'last_updated': time.time()})
pipeline.expire(key, int(self.expiration))
pipeline.execute()
return data
def delete(self, tile):
"""Delete the cached data for the given tile.
:param tile: A tile
:type tile: TileCache.Layer.Tile
"""
key = self.getKey(tile)
self.cache.delete(key)
def isExpired(self, key, layer):
"""Indicates whether or not the given layer is expired.
:param key: The key of the tile to test
:type key: str or unicode
:param layer: A layer
:type layer: TileCache::Layer
:rtype: bool
"""
if layer.expired is not None:
result = self.cache.hget(key, 'last_updated')
if result:
# Result comes back from redis as a string so we cast it here.
return float(result) < layer.expired
return False
def attemptLock(self, tile):
"""Attempt to acquire a lock for the given tile.
:param tile: A tile
:type tile: TileCache.Layer.Tile
:rtype: bool
"""
result = self.cache.setnx(
self.getLockName(tile),
time.time() + self.timeout + 1
)
# Expire the lock so it can't become stuck permanently
if result:
self.cache.expire(
self.getLockName(tile),
int(self.timeout + 1)
)
return result
def unlock(self, tile):
"""Unlock the given tile
:param tile: A tile
:type tile: TileCache.Layer.Tile
"""
self.cache.delete(self.getLockName(tile))