def get_friends(user_id): """Return the list of Facebook friends of user `user_id` who are also using the service. The friends list is a list of native user IDs (not Facebook user IDs), each an object of type ObjectId. A caching layer sits before the database. """ result = FriendsCache.get(user_id) if result is None: user = yield sundowner.data.users.read(user_id) try: fb_friends = user["facebook"]["friends"]["data"] except KeyError: # I don't think it's possible that this path in the user's data # wouldn't exist but if it doesn't, log it so that it can be # investigated print "Facebook user with no/unexpected friends data" fb_friends = [] fb_user_ids = map(itemgetter("id"), fb_friends) result = yield sundowner.data.users.\ read_native_user_ids_from_facebook_user_ids(fb_user_ids) FriendsCache.put(user_id, result) raise tornado.gen.Return(result)
def validate(access_token): """Validate a Facebook access token and return the associated local user ID, creating a new user record if necessary. """ user_id = AccessTokenCache.get(access_token) # If the access token isn't in the cache then validate it with Facebook # and retrieve its metadata. Extract the user ID from the metadata and # query Facebook again for the user metadata. If a record for the user # already exists update it with the latest metadata, otherwise create a new # record. Finally cache the access token until Facebook expires it. # # If new user metadata is being retrieved it may contain a different list # of friends to those already cached for the user, so clear the user's # friends cache. if user_id is None: access_token_meta = yield FacebookGraphAPI.debug_token(access_token) fb_user_id = access_token_meta["user_id"] user_meta = yield FacebookGraphAPI.get_user(fb_user_id, access_token) user_id = yield \ _create_or_update_user_record(fb_user_id, user_meta, access_token) FriendsCache.clear(user_id) AccessTokenCache.put( access_token, user_id, access_token_meta["expires_at"]) raise tornado.gen.Return(user_id)
def validate(access_token): """Validate a Facebook access token and return the associated local user ID, creating a new user record if necessary. """ user_id = AccessTokenCache.get(access_token) # If the access token isn't in the cache then validate it with Facebook # and retrieve its metadata. Extract the user ID from the metadata and # query Facebook again for the user metadata. If a record for the user # already exists update it with the latest metadata, otherwise create a new # record. Finally cache the access token until Facebook expires it. # # If new user metadata is being retrieved it may contain a different list # of friends to those already cached for the user, so clear the user's # friends cache. if user_id is None: access_token_meta = yield FacebookGraphAPI.debug_token(access_token) fb_user_id = access_token_meta["user_id"] user_meta = yield FacebookGraphAPI.get_user(fb_user_id, access_token) user_id = yield \ _create_or_update_user_record(fb_user_id, user_meta, access_token) FriendsCache.clear(user_id) AccessTokenCache.put(access_token, user_id, access_token_meta["expires_at"]) raise tornado.gen.Return(user_id)
def test_get_tags(self): # SETUP ---------------------------------------------------------------- # create mock user docs in the database @tornado.gen.coroutine def setup_users(): result = [] for _ in range(self.NUM_USERS): username = self.rand_noun() user_id = yield sundowner.data.users.create({ "facebook": { "id": None, "name": username, }}) result.append(user_id) raise tornado.gen.Return(result) users = IOLoop.instance().run_sync(setup_users) # one of the users will act as the user issuing the request and another # subset will act as friends of this user friends = random.sample(users, self.NUM_FRIENDS+1) user_id = friends.pop() # add friends to cache FriendsCache.put(user_id, friends) # create mock tags @tornado.gen.coroutine def create_tag(): # pick a random lng/lat inside the query radius # it appears that a lng/lat > (QUERY_RADIUS_RADIANS + .006) will # fall outside the query radius qrr = sundowner.data.content._QUERY_RADIUS_RADIANS lng = random.uniform(self.QUERY_LNG-qrr, self.QUERY_LNG+qrr) lat = random.uniform(self.QUERY_LAT-qrr, self.QUERY_LAT+qrr) user_id = random.choice(users) text = self.rand_noun() content_id = yield sundowner.data.content.put( user_id= user_id, text= text, url= None, accuracy= 0, lng= lng, lat= lat) raise tornado.gen.Return(content_id) for _ in range(self.NUM_TAGS): IOLoop.instance().run_sync(create_tag) # TEST ----------------------------------------------------------------- def test(): @tornado.gen.coroutine def query_content(): result = yield ContentModel.get_nearby( self.QUERY_LNG, self.QUERY_LAT, user_id) raise tornado.gen.Return(result) return IOLoop.instance().run_sync(query_content) """ def test_old(): @tornado.gen.coroutine def query_content(): result = yield ContentModel.get_nearby_old( self.QUERY_LNG, self.QUERY_LAT) raise tornado.gen.Return(result) result = IOLoop.instance().run_sync(query_content) """ #print "OLD", timeit.timeit(test_old, number=self.NUM_TRIALS) #print "NEW", timeit.timeit(test, number=self.NUM_TRIALS) pprint.pprint(test()) raise Exception