Skip to content

Commit

Permalink
Merge pull request #593 from CPSSD/n/refresh_follows
Browse files Browse the repository at this point in the history
Regenerate recommendations when there are new follows or unfollows
  • Loading branch information
iandioch authored Apr 17, 2019
2 parents 62adc29 + fd00423 commit 4bda091
Show file tree
Hide file tree
Showing 19 changed files with 242 additions and 114 deletions.
2 changes: 2 additions & 0 deletions containers/docker-compose.tmpl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ services:
- FOLLOW_ACTIVITY_SERVICE_HOST=follow_activity_service_[[INSTANCE_ID]]
- APPROVER_SERVICE_HOST=approver_service_[[INSTANCE_ID]]
- HOST_NAME=[[EXTERNAL_ADDRESS]]
- FOLLOW_RECOMMENDATIONS_SERVICE_HOST=recommend_follows_service_[[INSTANCE_ID]]
- FOLLOW_RECOMMENDATIONS_NO_OP=[[FOLLOWS_SERVICE_LOCATION]]
logger_service_[[INSTANCE_ID]]:
build:
context: ./services/logger
Expand Down
3 changes: 2 additions & 1 deletion services/follows/accept_follow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from services.proto import database_pb2
from services.proto import follows_pb2


class AcceptFollowServicer:
def __init__(self, logger, util, users_util, db_stub):
self._logger = logger
Expand All @@ -25,7 +26,7 @@ def _get_users(self, resp, request):
return None, None

follower = self._users_util.get_user_from_db(handle=request.follower.handle,
host=request.follower.host)
host=request.follower.host)
if not follower:
self._logger.error('Could not find follower.')
resp.result_type = follows_pb2.FollowResponse.ERROR
Expand Down
1 change: 1 addition & 0 deletions services/follows/get_followers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from services.proto import database_pb2
from services.proto import follows_pb2


class GetFollowsReceiver:

def __init__(self, logger, util, users_util, database_stub):
Expand Down
15 changes: 11 additions & 4 deletions services/follows/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from utils.connect import get_service_channel
from utils.logger import get_logger
from utils.users import UsersUtil
from utils.recommenders import RecommendersUtil
from servicer import FollowsServicer
from util import Util

Expand All @@ -26,6 +27,7 @@ def get_args():
help='Log more verbosely.')
return parser.parse_args()


def main():
args = get_args()
logger = get_logger('follows_service', args.v)
Expand All @@ -37,9 +39,9 @@ def main():
rss_env = 'RSS_SERVICE_HOST'

with get_service_channel(logger, db_env, 1798) as db_chan, \
get_service_channel(logger, follow_env, 1922) as follow_chan, \
get_service_channel(logger, approver_env, 2077) as approver_chan, \
get_service_channel(logger, rss_env, 1973) as rss_chan:
get_service_channel(logger, follow_env, 1922) as follow_chan, \
get_service_channel(logger, approver_env, 2077) as approver_chan, \
get_service_channel(logger, rss_env, 1973) as rss_chan:

db_stub = database_pb2_grpc.DatabaseStub(db_chan)
rss_stub = rss_pb2_grpc.RSSStub(rss_chan)
Expand All @@ -50,8 +52,12 @@ def main():
util = Util(logger, db_stub, approver_stub, users_util)
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))

recommender_util = RecommendersUtil(logger, db_stub)
follow_recommender_stub = recommender_util.get_follow_recommender_stub()

follows_servicer = FollowsServicer(logger, util, users_util, db_stub,
follow_stub, approver_stub, rss_stub)
follow_stub, approver_stub, rss_stub,
follow_recommender_stub)
follows_pb2_grpc.add_FollowsServicer_to_server(follows_servicer,
server)

Expand All @@ -64,5 +70,6 @@ def main():
except KeyboardInterrupt:
pass


if __name__ == '__main__':
main()
15 changes: 12 additions & 3 deletions services/follows/receive_follow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@
from services.proto import database_pb2
from services.proto import follows_pb2
from services.proto import s2s_follow_pb2
from services.proto import recommend_follows_pb2


class ReceiveFollowServicer:

def __init__(self, logger, util, users_util, database_stub):
def __init__(self, logger, util, users_util, database_stub, recommender_stub):
self._logger = logger
self._util = util
self._users_util = users_util
self._database_stub = database_stub
self._recommender_stub = recommender_stub
self._host_name = os.environ.get("HOST_NAME")
if not self._host_name:
print("Please set HOST_NAME env variable")
Expand All @@ -29,10 +31,10 @@ def ReceiveFollowRequest(self, request, context):
foreign_user.global_id,
local_user.global_id)


if not local_user.private.value:
self._logger.info('Accepting follow request')
self._util.attempt_to_accept(local_user, foreign_user, self._host_name, True)
self._util.attempt_to_accept(
local_user, foreign_user, self._host_name, True)

state = database_pb2.Follow.ACTIVE
if local_user.private.value:
Expand All @@ -48,5 +50,12 @@ def ReceiveFollowRequest(self, request, context):
resp.error = 'Could not add requested follow to database'
return resp

if self._recommender_stub is not None:
req = recommend_follows_pb2.UpdateFollowRecommendationsRequest(
follower=foreign_user.global_id,
followed=local_user.global_id,
following=True)
self._recommender_stub.UpdateFollowRecommendations(req)

resp.result_type = follows_pb2.FollowResponse.OK
return resp
12 changes: 11 additions & 1 deletion services/follows/receive_unfollow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
from services.proto import database_pb2
from services.proto import follows_pb2
from services.proto import s2s_follow_pb2
from services.proto import recommend_follows_pb2


class ReceiveUnfollowServicer:

def __init__(self, logger, util, users_util, database_stub):
def __init__(self, logger, util, users_util, database_stub,
recommender_stub):
self._logger = logger
self._util = util
self._users_util = users_util
self._database_stub = database_stub
self._recommender_stub = recommender_stub
self._host_name = os.environ.get("HOST_NAME")
if not self._host_name:
print("Please set HOST_NAME env variable")
Expand All @@ -39,5 +42,12 @@ def ReceiveUnfollow(self, request, context):
resp.error = 'Could not delete requested follow from database'
return resp

if self._recommender_stub is not None:
req = recommend_follows_pb2.UpdateFollowRecommendationsRequest(
follower=foreign_user.global_id,
followed=local_user.global_id,
following=False)
self._recommender_stub.UpdateFollowRecommendations(req)

resp.result_type = follows_pb2.FollowResponse.OK
return resp
5 changes: 2 additions & 3 deletions services/follows/rss_follow.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,17 @@ def _validate_url(self, url):
def _create_rss_user(self, feed_url):
# send to rss service to be created
rss_entry = rss_pb2.NewRssFeed(
rss_url = feed_url
rss_url=feed_url
)
rss_resp = self._rss_stub.NewRssFollow(rss_entry)

# check response for new/rss service id
if (rss_resp.result_type == rss_pb2.NewRssFeedResponse.ERROR or
rss_resp.result_type == rss_pb2.NewRssFeedResponse.DENIED):
rss_resp.result_type == rss_pb2.NewRssFeedResponse.DENIED):
self._logger.error("Rss service couldn't follow url: %s", feed_url)
return None, rss_resp.message
return rss_resp.global_id, None


def RssFollowRequest(self, req, context):
resp = follows_pb2.FollowResponse()
self._logger.info("Got follow rss request.")
Expand Down
11 changes: 10 additions & 1 deletion services/follows/send_follow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
from services.proto import database_pb2
from services.proto import follows_pb2
from services.proto import s2s_follow_pb2
from services.proto import recommend_follows_pb2


class SendFollowServicer:

def __init__(self, logger, util, users_util,
database_stub, follow_activity_stub):
database_stub, follow_activity_stub, recommender_stub):
host_name = os.environ.get("HOST_NAME")
if not host_name:
print("Please set HOST_NAME env variable")
Expand All @@ -20,6 +21,7 @@ def __init__(self, logger, util, users_util,
self._users_util = users_util
self._database_stub = database_stub
self._follow_activity_stub = follow_activity_stub
self._recommender_stub = recommender_stub

def _send_s2s(self, from_handle, to_handle, to_host):
local_user = s2s_follow_pb2.FollowActivityUser()
Expand Down Expand Up @@ -132,5 +134,12 @@ def SendFollowRequest(self, request, context):
resp.error = err
return resp

if self._recommender_stub is not None:
req = recommend_follows_pb2.UpdateFollowRecommendationsRequest(
follower=follower_entry.global_id,
followed=followed_entry.global_id,
following=True)
self._recommender_stub.UpdateFollowRecommendations(req)

resp.result_type = follows_pb2.FollowResponse.OK
return resp
13 changes: 12 additions & 1 deletion services/follows/send_unfollow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
from services.proto import database_pb2
from services.proto import follows_pb2
from services.proto import s2s_follow_pb2
from services.proto import recommend_follows_pb2


class SendUnfollowServicer:

def __init__(self, logger, util, users_util, database_stub, s2s_stub):
def __init__(self, logger, util, users_util,
database_stub, s2s_stub, recommender_stub):
host_name = os.environ.get("HOST_NAME")
if not host_name:
print("Please set HOST_NAME env variable")
Expand All @@ -19,6 +21,7 @@ def __init__(self, logger, util, users_util, database_stub, s2s_stub):
self._users_util = users_util
self._database_stub = database_stub
self._s2s_stub = s2s_stub
self._recommender_stub = recommender_stub

def _remove_follow(self,
resp,
Expand Down Expand Up @@ -99,5 +102,13 @@ def SendUnfollow(self, request, context):
s2s_req = s2s_follow_pb2.FollowDetails(follower=s2s_follower,
followed=s2s_followed)
self._s2s_stub.SendUnfollowActivity(s2s_req)

if self._recommender_stub is not None:
req = recommend_follows_pb2.UpdateFollowRecommendationsRequest(
follower=follower_entry.global_id,
followed=followed_entry.global_id,
following=False)
self._recommender_stub.UpdateFollowRecommendations(req)

resp.result_type = follows_pb2.FollowResponse.OK
return resp
16 changes: 11 additions & 5 deletions services/follows/servicer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,34 @@
class FollowsServicer(follows_pb2_grpc.FollowsServicer):

def __init__(self, logger, util, users_util, database_stub,
follow_activity_stub, approver_stub, rss_stub):
follow_activity_stub, approver_stub, rss_stub,
follow_recommender_stub):
self._logger = logger
self._util = util
self._users_util = users_util
self._follow_activity_stub = follow_activity_stub
self._rss_stub = rss_stub
self._approver_stub = approver_stub
self._recommender_stub = follow_recommender_stub

send_servicer = SendFollowServicer(logger, util, users_util,
database_stub, follow_activity_stub)
database_stub, follow_activity_stub,
follow_recommender_stub)
self.SendFollowRequest = send_servicer.SendFollowRequest

send_unfollow_servicer = SendUnfollowServicer(logger,
util,
users_util,
database_stub,
follow_activity_stub)
follow_activity_stub,
follow_recommender_stub)
self.SendUnfollow = send_unfollow_servicer.SendUnfollow
rss_servicer = RssFollowServicer(logger, util, users_util,
database_stub, rss_stub)
self.RssFollowRequest = rss_servicer.RssFollowRequest
rec_servicer = ReceiveFollowServicer(logger, util, users_util,
database_stub)
database_stub,
follow_recommender_stub)
self.ReceiveFollowRequest = rec_servicer.ReceiveFollowRequest

get_follows_receiver = GetFollowsReceiver(logger, util, users_util,
Expand All @@ -49,5 +54,6 @@ def __init__(self, logger, util, users_util, database_stub,
rec_unfollow_servicer = ReceiveUnfollowServicer(logger,
util,
users_util,
database_stub)
database_stub,
follow_recommender_stub)
self.ReceiveUnfollow = rec_unfollow_servicer.ReceiveUnfollow
1 change: 1 addition & 0 deletions services/follows/test_receive_follow.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def setUp(self):
self.servicer = ReceiveFollowServicer(Mock(),
util,
user_util,
Mock(),
Mock())

def tearDown(self):
Expand Down
3 changes: 2 additions & 1 deletion services/follows/test_send_unfollow.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ def setUp(self):
util,
user_util,
database_stub,
s2s_stub)
s2s_stub,
Mock())

def tearDown(self):
del os.environ["HOST_NAME"]
Expand Down
17 changes: 16 additions & 1 deletion services/proto/recommend_follows.proto
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ message FollowRecommendationUser {
}

message FollowRecommendationRequest {
/* Eg. "admin", "[email protected]", "@jose" */
/* The Rabble integer ID of the user. */
int64 user_id = 1;
}

Expand All @@ -32,6 +32,21 @@ message FollowRecommendationResponse {
repeated FollowRecommendationUser results = 3;
}

message UpdateFollowRecommendationsRequest {
/* Rabble user_id of follower. */
int64 follower = 1;
/* Rabble user_id of follower. */
int64 followed = 2;
/* True if this is a new follow, false if it is an unfollow. */
bool following = 3;
}

message UpdateFollowRecommendationsResponse {
/* Don't return any error, the caller doesn't really care.
Just log it in the recommender service. */
}

service FollowRecommendations {
rpc GetFollowRecommendations(FollowRecommendationRequest) returns (FollowRecommendationResponse);
rpc UpdateFollowRecommendations(UpdateFollowRecommendationsRequest) returns (UpdateFollowRecommendationsResponse);
}
Loading

0 comments on commit 4bda091

Please sign in to comment.