def save(self): """Saves or updates the ShortLink instance in database""" if not self.url: raise ShortLinkError("Token or url are empty") r = get_redis_connection() #If not token or counter then we need to get the apropiate one (last) if not self.token and not self.counter: self.counter = ShortLink.incr_counter() # Do all in pipeline pipe = r.pipeline() # Save token(Hash) and url(set) #If there is not a date then take now if not self.creation_date: self.creation_date = dateutils.unix_now_utc() disabled = 1 if self.disabled else 0 mappings = {'url': self.url, 'creation_date': self.creation_date, 'clicks': self.clicks, 'title': self.title, 'host': self.host, 'disabled': disabled} pipe.hmset(ShortLink.REDIS_TOKEN_KEY.format(self.token), mappings) pipe.sadd(ShortLink.REDIS_URL_KEY.format(self.url), self.token) return pipe.execute()
def test_delete_link(self): counter = random.randrange(0, 100000) url = "xlarrakoetxea.org" sl = ShortLink(counter=counter, url=url) sl.save() r = get_redis_connection() times = random.randrange(10, 100) for i in range(times): c = Click(token=sl.token) c.save() self.assertTrue(r.exists(ShortLink.REDIS_TOKEN_KEY.format(sl.token))) self.assertTrue(r.sismember(ShortLink.REDIS_URL_KEY.format(sl.url), sl.token)) self.assertEquals(times, len(r.keys( Click.REDIS_CLICK_KEY.format(sl.token, "*")))) sl.delete() self.assertFalse(r.exists(ShortLink.REDIS_TOKEN_KEY.format(sl.token))) self.assertFalse(r.sismember(ShortLink.REDIS_URL_KEY.format(sl.url), sl.token)) self.assertEquals(0, len(r.keys( Click.REDIS_CLICK_KEY.format(sl.token, "*"))))
def test_achievement_notification_get_all_asc(self): #with three we have enought to test achieves = Achievement.objects.all() user = User.objects.get(id=1) r = get_redis_connection() a_len = len(achieves) for i in achieves: notif = AchievementNotification(achievement=i, user=user) time.sleep(1) if random.randrange(100) % 2: key = Notification.STORE_KEY_UNREAD_FORMAT.format(user.id) else: key = Notification.STORE_KEY_READ_FORMAT.format(user.id) r.zadd(key, notif.date, notif.to_json()) # Get notifications res = Notification.all(user, desc=False) self.assertEquals(a_len, len(res)) for i in range(len(res)): before = achieves[i] after = res[i] self.assertEquals(before.id, after.achievement_id)
def delete(self): lua_script = """ local token = ARGV[1] --Delete all the data --Clicks local i = 0 local result = 1 while result > 0 do i = i + 1 result = redis.call('del',KEYS[3] .. tostring(i)) end --Token redis.call('del',KEYS[1]) return redis.call('srem',KEYS[2], token) """ r = get_redis_connection() delete = r.register_script(lua_script) token_key = ShortLink.REDIS_TOKEN_KEY.format(self.token) url_key = ShortLink.REDIS_URL_KEY.format(self.url) #Circular dependency destroyer! from clickmanager.models import Click click_key = Click.REDIS_CLICK_KEY.format(self.token, "") delete(keys=[token_key, url_key, click_key], args=[self.token, ])
def test_achievement_notification_count_range(self): achieves = Achievement.objects.all()[:5] notifs = [] user = User.objects.get(id=1) r = get_redis_connection() for i in achieves: notif = AchievementNotification(achievement=i, user=user) time.sleep(1) if random.randrange(100) % 2: key = Notification.STORE_KEY_UNREAD_FORMAT.format(user.id) else: key = Notification.STORE_KEY_READ_FORMAT.format(user.id) r.zadd(key, notif.date, notif.to_json()) notifs.append(notif) achieves = achieves[2:5] # 2, 3 and 4 only a_len = len(achieves) lowerbound = notifs[2].date upperbound = notifs[4].date result = AchievementNotification.count(user, lowerbound, upperbound, mode=2) self.assertEquals(a_len, result)
def check_flag(cls, key, position): """Checks a bit in the bitmap in the redis databases :param key: The key of redis where the bitmap resides :param position: The bitmap position to check """ r = get_redis_connection() return r.getbit(key, position)
def test_achievement_notification_get_range(self): achieves = Achievement.objects.all()[:5] notifs = [] user = User.objects.get(id=1) r = get_redis_connection() for i in achieves: notif = AchievementNotification(achievement=i, user=user) time.sleep(1) if random.randrange(100) % 2: key = Notification.STORE_KEY_UNREAD_FORMAT.format(user.id) else: key = Notification.STORE_KEY_READ_FORMAT.format(user.id) r.zadd(key, notif.date, notif.to_json()) notifs.append(notif) achieves = achieves[2:5] # 2, 3 and 4 only a_len = len(achieves) # Get notifications res = Notification.time_range(user, lowerbound=notifs[2].date, upperbound=notifs[4].date, desc=False, mode=2) self.assertEquals(a_len, len(res)) for i in range(len(res)): before = achieves[i] after = res[i] self.assertEquals(before.id, after.achievement_id)
def test_achievement_notification_find_all_with_limits(self): achieves = Achievement.objects.all()[:5] user = User.objects.get(id=1) r = get_redis_connection() for i in achieves: notif = AchievementNotification(achievement=i, user=user) time.sleep(1) if random.randrange(100) % 2: key = Notification.STORE_KEY_UNREAD_FORMAT.format(user.id) else: key = Notification.STORE_KEY_READ_FORMAT.format(user.id) r.zadd(key, notif.date, notif.to_json()) # Get notifications res = Notification.find(user, offset=2, limit=3, desc=False, mode=2) achieves = achieves[2:4] # 2 and 3 only a_len = len(achieves) self.assertEquals(a_len, len(res)) for i in range(len(res)): before = achieves[i] after = res[i] self.assertEquals(before.id, after.achievement_id)
def _find_by_token(self): """Private method that searches a shortlink in the database by it's token and returns a ShortLink redis raw data. In this case returns a list with [url, creation_date, clicks]""" r = get_redis_connection() return r.hgetall(ShortLink.REDIS_TOKEN_KEY.format(self.token))
def get_counter(cls): """Gets the global counter of links stored in database""" r = get_redis_connection() key = ShortLink.REDIS_COUNTER_KEY if not r.exists(key): r.set(key, 0) # Initialize the counter return int(r.get(key))
def _incr_decr_clicks(cls, token, value): """Increments/decrements the clicks of short link and returns the new counter incremented""" r = get_redis_connection() key = ShortLink.REDIS_TOKEN_KEY.format(token) if not r.exists(key): raise ShortLinkNotFoundError("Token doesn't exists") return r.hincrby(key, 'clicks', value)
def or_operation(cls, keys, store_key=None): """Makes an OR operation with all the redis keys. Returns the key on redis where the operation is stored :param keys: The list of redis keys of the values for the OR operation """ if not store_key: rand_id = random.randrange(0, 10000) store_key = BitmapMetrics.OP_KEY.format("or", rand_id) r = get_redis_connection() r.bitop("or", store_key, *keys) return store_key
def not_operation(cls, key, store_key=None): """Makes an NOT operation In the bitmap of the redis key. Returns the key on redis where the operation is stored :param key: The redis key of the value for the NOT operation """ if not store_key: rand_id = random.randrange(0, 10000) store_key = BitmapMetrics.OP_KEY.format("not", rand_id) r = get_redis_connection() r.bitop("not", store_key, key) return store_key
def test_achievement_notification_count(self): achieves = Achievement.objects.all() user = User.objects.get(id=1) r = get_redis_connection() for i in achieves: notif = AchievementNotification(achievement=i, user=user) if random.randrange(100) % 2: key = Notification.STORE_KEY_UNREAD_FORMAT.format(user.id) else: key = Notification.STORE_KEY_READ_FORMAT.format(user.id) r.zadd(key, notif.date, notif.to_json()) a_len = len(achieves) self.assertEquals(a_len, AchievementNotification.count(user, mode=2))
def setUp(self): self.year = 2013 self.month = "03" self.day = 18 self.hour = 20 self.minutes = "00" self.date = datetime(year=self.year, month=int(self.month), day=self.day, hour=self.hour, minute=int(self.minutes)) self.r = get_redis_connection() self.LOGIN_METRICS_FORMAT = "Metrics:login:{0}" self.SHAREDLINKS_METRICS_FORMAT = "Metrics:sharedlinks:{0}" self.ACHIEVEMENTS_METRICS_FORMAT = "Metrics:achievements:{0}" self.DATE_FORMAT = "%Y-%m-%dT%H"
def test_level_notification_store(self): #with three we have enought to test levels = Level.objects.all()[:3] user = User.objects.get(id=1) a_len = len(levels) for i in levels: notif = LevelNotification(level=i, user=user) time.sleep(1) # We need notification order notif.save() r = get_redis_connection() res = r.zrange( Notification.STORE_KEY_UNREAD_FORMAT.format(user.id), 0, -1) self.assertEquals(a_len, len(res)) for i in range(len(res)): before = levels[i] after = json.loads(res[i]) self.assertEquals(before.level_number, after['level'])
def test_achievement_notification_store_read(self): #with three we have enought to test achieves = Achievement.objects.all()[:3] user = User.objects.get(id=1) a_len = len(achieves) for i in achieves: notif = AchievementNotification(achievement=i, user=user) time.sleep(1) notif.save(read=True) r = get_redis_connection() res = r.zrange( Notification.STORE_KEY_READ_FORMAT.format(user.id), 0, -1) self.assertEquals(a_len, len(res)) for i in range(len(res)): before = achieves[i] after = json.loads(res[i]) self.assertEquals(before.id, after['achievement_id'])
def test_shortlink_notification_store(self): #with three we have enought to test sls = ShortLink.findall()[:3] user = User.objects.get(id=1) a_len = len(sls) for i in sls: notif = ShortLinkNotification(short_link=i, user=user) time.sleep(1) # We need notification order notif.save() r = get_redis_connection() res = r.zrange( Notification.STORE_KEY_UNREAD_FORMAT.format(user.id), 0, -1) self.assertEquals(a_len, len(res)) for i in range(len(res)): before = sls[i] after = json.loads(res[i]) self.assertEquals(before.token, after['token'])
def test_achievement_notification_get_unread(self): #with three we have enought to test achieves = Achievement.objects.all()[:3] user = User.objects.get(id=1) r = get_redis_connection() a_len = len(achieves) for i in achieves: notif = AchievementNotification(achievement=i, user=user) time.sleep(1) key = Notification.STORE_KEY_UNREAD_FORMAT.format(user.id) r.zadd(key, notif.date, notif.to_json()) # Get notifications res = Notification.unreads(user)[::-1] self.assertEquals(a_len, len(res)) for i in range(len(res)): before = achieves[i] after = res[i] self.assertEquals(before.id, after.achievement_id)
def get_flags(self, flag_positions): r = get_redis_connection() pipe = r.pipeline() for i in flag_positions: pipe.getbit(self._key, i) return pipe.execute()
def count_flags(cls, key): """Counts all the flags activated in a given key (containing a bitmap) :param key: the key where the bitmap resides """ r = get_redis_connection() return r.bitcount(key)
def unset_flags(self, flag_positions): r = get_redis_connection() pipe = r.pipeline() for i in flag_positions: pipe.setbit(self._key, i, BitmapMetrics.FLAG_DOWN) pipe.execute()
def get_flag(self, flag_position): r = get_redis_connection() return r.getbit(self._key, flag_position)
def get_count(cls, key): r = get_redis_connection() try: return int(r.get(key)) except TypeError: return 0
def unset_flag(self, flag_position): r = get_redis_connection() r.setbit(self._key, flag_position, BitmapMetrics.FLAG_DOWN)
def count(self): r = get_redis_connection() try: return int(r.get(self.key)) except TypeError: return 0
def decrement(self, count=1): """ Decrements the counter and returns the result""" r = get_redis_connection() return r.decr(self._key, count)
def enable(self): r = get_redis_connection() key = ShortLink.REDIS_TOKEN_KEY.format(self.token) self.disabled = False r.hset(key, "disabled", 0)
def set_counter(cls, counter): """Sets the global counter of links stored in database""" r = get_redis_connection() r.set(ShortLink.REDIS_COUNTER_KEY, counter)
def decr_counter(cls): """ Decrements the counter and returns the new counter incremented""" r = get_redis_connection() return r.decr(ShortLink.REDIS_COUNTER_KEY)