def process_waitlist(): from server.db import redis while True: lock = redis.lock('locks:process_waitlist', timeout=600) if lock.acquire(blocking=False): try: user_ids = wigo_db.sorted_set_range_by_score( skey('user_queue'), 0, time(), 0, 50) if user_ids: for user_id in user_ids: logger.info('unlocking user id {}'.format(user_id)) user = User.find(user_id) if user.is_waiting(): user.status = 'active' user.save() # remove from wait list wigo_db.sorted_set_remove(skey('user_queue'), user.id, replicate=False) else: break finally: lock.release()
def run(self): logger.info('running scheduled tasks') while True: lock = redis.lock('locks:run_schedule', timeout=60) if lock.acquire(blocking=False): try: scheduler.enqueue_jobs() finally: lock.release() sleep(5)
def user_lock(user_id, timeout=30, yield_on_blocking_timeout=True): if Configuration.ENVIRONMENT != 'test': from server.db import redis lock = redis.lock('locks:user:{}'.format(user_id), timeout=timeout) if lock.acquire(blocking=True, blocking_timeout=5): try: yield finally: try: lock.release() except LockError: pass elif yield_on_blocking_timeout: yield else: yield
def create_from_city(cls, city): tz = get_timezone(city.lat, city.lon) city_code = city.name.decode('unicode_escape').encode( 'ascii', 'ignore').lower() city_code = re.sub(r'[^\w]+', '_', city_code) for i in range(1, 10): lock = redis.lock('locks:group_create:{}'.format(city.city_id), timeout=10) if lock.acquire(blocking=True, blocking_timeout=.1): try: # look for the city one more time with the lock return get_group_by_city_id(city.city_id) except DoesNotExist: # create a new group with the lock acquired try: return Group({ 'name': city.name, 'code': city_code, 'latitude': city.lat, 'longitude': city.lon, 'city_id': city.city_id, 'timezone': tz or 'US/Eastern', 'population': int(city.population), 'continent': city.continent, 'country': city.country, 'state': city.state, 'continent_id': city.continent_id, 'country_id': city.country_id, 'state_id': city.state_id }).save() except IntegrityException: city_code = '{}_{}'.format(city_code, i) finally: lock.release() raise DoesNotExist()
def run(self): logger.info('running maintenance tasks') while True: lock = redis.lock('locks:run_maintenance', timeout=60) if lock.acquire(blocking=False): try: try: process_waitlist() except: logger.exception('error processing waitlist') try: wigo_db.process_rate_limits() except: logger.exception('error processing rate limits') try: wigo_db.process_expired() except: logger.exception('error processing expired') # kick off a job to cleanup old events clean_old_events.delay() # check the state of the queues try: for q_name in ALL_QUEUES: self.check_queue(Queue(q_name, connection=redis), 4000, 5) f_queue = get_failed_queue(redis) self.check_queue(f_queue, 20, 10) except: logger.exception('error checking queues') finally: lock.release() sleep(60)
def post(self): data = request.get_json() if not data: abort(400, message='No data posted') timezone = pytz.timezone(data.get('timezone', 'US/Eastern')) facebook_id = data.get('facebook_id') facebook_token = data.get('facebook_access_token') facebook_token_expires = datetime.utcnow() + timedelta( seconds=data.get('facebook_access_token_expires') or 1728000) birthdate = data.get('birthdate') education = data.get('education') work = data.get('work') properties = data.get('properties') if not facebook_id or not facebook_token: abort(400, message='Missing facebook id or token') with redis.lock('locks:register:{}'.format(facebook_id), timeout=30): try: User.find(facebook_id=facebook_id) abort(400, message='Account already exists') except DoesNotExist: pass if not facebook_id.startswith('xxx'): facebook = Facebook(facebook_token, facebook_token_expires) user_info = self.get_me(facebook, facebook_id, facebook_token, facebook_token_expires) facebook_token_expires = facebook.get_token_expiration() else: user_info = {} logger.info('creating new user account for facebook_id {}'.format( facebook_id)) user = User() user.key = uuid4().hex user.facebook_id = facebook_id user.facebook_token = facebook_token user.facebook_token_expires = facebook_token_expires user.email = user_info.get('email') if user.email: user.email_validated = True user.email_validated_date = datetime.utcnow() user.email_validated_status = 'validated' user.timezone = timezone.zone user.first_name = user_info.get('first_name') or user_info.get( 'given_name') user.last_name = user_info.get('last_name') or user_info.get( 'family_name') user.username = get_username(user.email or user.full_name) user.gender = user_info.get('gender') if not birthdate: birthdate = user_info.get('birthday') if birthdate: try: user.birthdate = parse(birthdate) except: logger.info('error parsing birthdate {}'.format(birthdate)) if education: user.education = education if work: user.work = work if g.group: user.group_id = g.group.id if properties: for key, value in properties.items(): user.set_custom_property(key, value) user.set_custom_property('events', {'triggers': ['find_referrer']}) platform = request.headers.get('X-Wigo-Device') if not platform: platform = request.user_agent.platform if platform: platform = platform.lower() if platform in ('android', 'iphone', 'ipad'): user.set_custom_property('platforms', [platform]) enterprise = request.headers.get('X-Wigo-Client-Enterprise') if enterprise == 'true': user.enterprise = True user.save() g.user = user # if not user.email_validated and Configuration.PUSH_ENABLED: # send_email_verification.delay(user.id) logger.info( 'registered new account for user {} for facebook_id {}'.format( user.id, facebook_id)) return self.serialize_list(User, [user])
def event_related_change(group_id, event_id, is_global=False, deleted=False): from server.db import redis lock = redis.lock('locks:group_event_change:{}:{}'.format( group_id, event_id), timeout=120) if lock.acquire(blocking=False): try: agent.add_custom_parameter('group_id', group_id) logger.debug('recording event change in group {}'.format(group_id)) if not deleted: try: event = Event.find(event_id) event.deleted = False except DoesNotExist: event = Event({'id': event_id, 'group_id': group_id}) event.deleted = True else: event = Event({'id': event_id, 'group_id': group_id}) event.deleted = True group = Group.find(group_id) with wigo_db.transaction(commit_on_select=False): # add to the time in case other changes come in while this lock is taken, # or in case the job queues get backed up group.track_meta('last_event_change', time() + EVENT_CHANGE_TIME_BUFFER) if is_global or event.is_global: groups_to_add_to = get_all_groups() else: radius = 100 population = group.population or 50000 if population < 60000: radius = 40 elif population < 100000: radius = 60 groups_to_add_to = get_close_groups( group.latitude, group.longitude, radius) num_visited = 0 for group_to_add_to in groups_to_add_to: if group_to_add_to.id == group.id: continue # index this event into the close group if event.deleted is False: event.update_global_events(group=group_to_add_to) else: event.remove_index(group=group_to_add_to) # track the change for the group group_to_add_to.track_meta( 'last_event_change', time() + EVENT_CHANGE_TIME_BUFFER) num_visited += 1 if (num_visited % 25) == 0: lock.extend(30) finally: lock.release()