示例#1
0
        /// <summary>
        /// Update following relationship.
        /// Following user : someone who i am following.
        /// </summary>
        /// <param name="storageConsistencyMode">Consistency mode</param>
        /// <param name="relationshipHandle">Relationship handle</param>
        /// <param name="userHandle">User handle</param>
        /// <param name="relationshipUserHandle">Relationship user handle</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="userRelationshipStatus">User relationship status</param>
        /// <param name="lastUpdatedTime">Last updated time</param>
        /// <param name="readUserRelationshipLookupEntity">Read user relationship lookup entity</param>
        /// <returns>Update following relationship task</returns>
        public async Task UpdateFollowingRelationship(
            StorageConsistencyMode storageConsistencyMode,
            string relationshipHandle,
            string userHandle,
            string relationshipUserHandle,
            string appHandle,
            UserRelationshipStatus userRelationshipStatus,
            DateTime lastUpdatedTime,
            IUserRelationshipLookupEntity readUserRelationshipLookupEntity)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.UserFollowing);

            ObjectTable lookupTable = this.tableStoreManager.GetTable(ContainerIdentifier.UserFollowing, TableIdentifier.FollowingLookup) as ObjectTable;
            FeedTable   feedTable   = this.tableStoreManager.GetTable(ContainerIdentifier.UserFollowing, TableIdentifier.FollowingFeed) as FeedTable;
            CountTable  countTable  = this.tableStoreManager.GetTable(ContainerIdentifier.UserFollowing, TableIdentifier.FollowingCount) as CountTable;

            await this.UpdateUserRelationship(
                storageConsistencyMode,
                relationshipHandle,
                userHandle,
                relationshipUserHandle,
                appHandle,
                userRelationshipStatus,
                lastUpdatedTime,
                readUserRelationshipLookupEntity,
                store,
                lookupTable,
                feedTable,
                countTable);
        }
        /// <summary>
        /// Process message
        /// </summary>
        /// <param name="message">Queue message</param>
        /// <returns>Process message task</returns>
        protected override async Task Process(IMessage message)
        {
            if (message is RelationshipMessage)
            {
                RelationshipMessage relationshipMessage = message as RelationshipMessage;
                ProcessType         processType         = ProcessType.Backend;
                if (relationshipMessage.DequeueCount > 1)
                {
                    processType = ProcessType.BackendRetry;
                }

                IUserRelationshipLookupEntity followerRelationshipLookupEntity = await this.relationshipsManager.ReadFollowerRelationship(
                    relationshipMessage.FollowerKeyUserHandle,
                    relationshipMessage.FollowingKeyUserHandle,
                    relationshipMessage.AppHandle);

                if (followerRelationshipLookupEntity != null && followerRelationshipLookupEntity.LastUpdatedTime > relationshipMessage.LastUpdatedTime)
                {
                    return;
                }

                IUserRelationshipLookupEntity followingRelationshipLookupEntity = await this.relationshipsManager.ReadFollowingRelationshipToUser(
                    relationshipMessage.FollowingKeyUserHandle,
                    relationshipMessage.FollowerKeyUserHandle,
                    relationshipMessage.AppHandle);

                if (followingRelationshipLookupEntity != null && followingRelationshipLookupEntity.LastUpdatedTime > relationshipMessage.LastUpdatedTime)
                {
                    return;
                }

                await this.relationshipsManager.UpdateRelationshipToUser(
                    processType,
                    relationshipMessage.RelationshipOperation,
                    relationshipMessage.RelationshipHandle,
                    relationshipMessage.FollowerKeyUserHandle,
                    relationshipMessage.FollowingKeyUserHandle,
                    relationshipMessage.AppHandle,
                    relationshipMessage.LastUpdatedTime,
                    followerRelationshipLookupEntity,
                    followingRelationshipLookupEntity);
            }
        }
示例#3
0
        /// <summary>
        /// Update user relationship
        /// </summary>
        /// <param name="storageConsistencyMode">Consistency mode</param>
        /// <param name="relationshipHandle">Relationship handle</param>
        /// <param name="userHandle">User handle</param>
        /// <param name="relationshipUserHandle">Relationship user handle</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="userRelationshipStatus">Relationship status</param>
        /// <param name="lastUpdatedTime">Last updated time</param>
        /// <param name="readUserRelationshipLookupEntity">Read user relationship lookup entity</param>
        /// <param name="store">store object</param>
        /// <param name="lookupTable">lookup table</param>
        /// <param name="feedTable">feed table</param>
        /// <param name="countTable">count table</param>
        /// <returns>Update follower relationship task</returns>
        private async Task UpdateUserRelationship(
            StorageConsistencyMode storageConsistencyMode,
            string relationshipHandle,
            string userHandle,
            string relationshipUserHandle,
            string appHandle,
            UserRelationshipStatus userRelationshipStatus,
            DateTime lastUpdatedTime,
            IUserRelationshipLookupEntity readUserRelationshipLookupEntity,
            CTStore store,
            ObjectTable lookupTable,
            FeedTable feedTable,
            CountTable countTable)
        {
            string objectKey = this.GetObjectKey(appHandle, relationshipUserHandle);
            string feedKey   = this.GetFeedKey(appHandle, userRelationshipStatus);
            string countKey  = this.GetCountKey(appHandle, userRelationshipStatus);

            Transaction transaction = new Transaction();

            UserRelationshipFeedEntity relationshipFeedEntity = new UserRelationshipFeedEntity()
            {
                RelationshipHandle = relationshipHandle,
                UserHandle         = relationshipUserHandle
            };

            if (readUserRelationshipLookupEntity == null)
            {
                UserRelationshipLookupEntity newRelationshipLookupEntity = new UserRelationshipLookupEntity()
                {
                    RelationshipHandle     = relationshipHandle,
                    LastUpdatedTime        = lastUpdatedTime,
                    UserRelationshipStatus = userRelationshipStatus,
                };

                transaction.Add(Operation.Insert(lookupTable, userHandle, objectKey, newRelationshipLookupEntity));

                if (userRelationshipStatus != UserRelationshipStatus.None)
                {
                    transaction.Add(Operation.Insert(feedTable, userHandle, feedKey, relationshipHandle, relationshipFeedEntity));
                    transaction.Add(Operation.InsertOrIncrement(countTable, userHandle, countKey));
                }
            }
            else
            {
                UserRelationshipStatus oldUserRelationshipStatus = readUserRelationshipLookupEntity.UserRelationshipStatus;
                string oldRelationshipHandle = readUserRelationshipLookupEntity.RelationshipHandle;

                readUserRelationshipLookupEntity.RelationshipHandle     = relationshipHandle;
                readUserRelationshipLookupEntity.UserRelationshipStatus = userRelationshipStatus;
                readUserRelationshipLookupEntity.LastUpdatedTime        = lastUpdatedTime;

                string oldFeedKey  = this.GetFeedKey(appHandle, oldUserRelationshipStatus);
                string oldCountKey = this.GetCountKey(appHandle, oldUserRelationshipStatus);

                transaction.Add(Operation.Replace(lookupTable, userHandle, objectKey, readUserRelationshipLookupEntity as UserRelationshipLookupEntity));

                if (userRelationshipStatus == oldUserRelationshipStatus)
                {
                    if (userRelationshipStatus != UserRelationshipStatus.None && relationshipHandle != oldRelationshipHandle)
                    {
                        transaction.Add(Operation.Delete(feedTable, userHandle, oldFeedKey, oldRelationshipHandle));
                        transaction.Add(Operation.Insert(feedTable, userHandle, feedKey, relationshipHandle, relationshipFeedEntity));
                    }
                }
                else
                {
                    if (userRelationshipStatus != UserRelationshipStatus.None)
                    {
                        transaction.Add(Operation.Insert(feedTable, userHandle, feedKey, relationshipHandle, relationshipFeedEntity));
                        transaction.Add(Operation.InsertOrIncrement(countTable, userHandle, countKey));
                    }

                    if (oldUserRelationshipStatus != UserRelationshipStatus.None)
                    {
                        transaction.Add(Operation.Delete(feedTable, userHandle, oldFeedKey, oldRelationshipHandle));
                        transaction.Add(Operation.Increment(countTable, userHandle, oldCountKey, -1.0));
                    }
                }
            }

            await store.ExecuteTransactionAsync(transaction, storageConsistencyMode.ToConsistencyMode());
        }
示例#4
0
        /// <summary>
        /// Update a relationship between two users
        /// </summary>
        /// <param name="processType">Process type</param>
        /// <param name="relationshipOperation">User relationship operation</param>
        /// <param name="relationshipHandle">Relationship handle</param>
        /// <param name="followerKeyUserHandle">Follower key user handle</param>
        /// <param name="followingKeyUserHandle">Following key user handle</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="lastUpdatedTime">Last updated time</param>
        /// <param name="followerRelationshipLookupEntity">Follower relationship lookup entity</param>
        /// <param name="followingRelationshipLookupEntity">Following relationship lookup entity</param>
        /// <returns>Update relationship task</returns>
        public async Task UpdateRelationshipToUser(
            ProcessType processType,
            RelationshipOperation relationshipOperation,
            string relationshipHandle,
            string followerKeyUserHandle,
            string followingKeyUserHandle,
            string appHandle,
            DateTime lastUpdatedTime,
            IUserRelationshipLookupEntity followerRelationshipLookupEntity,
            IUserRelationshipLookupEntity followingRelationshipLookupEntity)
        {
            UserRelationshipStatus userRelationshipStatus = this.GetRelationshipStatus(relationshipOperation);

            if (processType == ProcessType.Frontend)
            {
                await this.userRelationshipsStore.UpdateFollowerRelationship(
                    StorageConsistencyMode.Strong,
                    relationshipHandle,
                    followerKeyUserHandle,
                    followingKeyUserHandle,
                    appHandle,
                    userRelationshipStatus,
                    lastUpdatedTime,
                    followerRelationshipLookupEntity);

                await this.userRelationshipsStore.UpdateFollowingRelationship(
                    StorageConsistencyMode.Strong,
                    relationshipHandle,
                    followingKeyUserHandle,
                    followerKeyUserHandle,
                    appHandle,
                    userRelationshipStatus,
                    lastUpdatedTime,
                    followingRelationshipLookupEntity);

                await this.relationshipsQueue.SendRelationshipMessage(
                    relationshipOperation,
                    relationshipHandle,
                    followerKeyUserHandle,
                    followingKeyUserHandle,
                    appHandle,
                    lastUpdatedTime);
            }
            else if (processType == ProcessType.Backend || processType == ProcessType.BackendRetry)
            {
                if (relationshipOperation == RelationshipOperation.FollowUser)
                {
                    await this.notificationsManager.CreateNotification(
                        processType,
                        followerKeyUserHandle,
                        appHandle,
                        relationshipHandle,
                        ActivityType.Following,
                        followingKeyUserHandle,
                        followerKeyUserHandle,
                        ContentType.Unknown,
                        null,
                        lastUpdatedTime);

                    await this.fanoutActivitiesQueue.SendFanoutActivityMessage(
                        followingKeyUserHandle,
                        appHandle,
                        relationshipHandle,
                        ActivityType.Following,
                        followingKeyUserHandle,
                        followerKeyUserHandle,
                        ContentType.Unknown,
                        null,
                        lastUpdatedTime);

                    await this.followingImportsQueue.SendFollowingImportMessage(
                        followingKeyUserHandle,
                        appHandle,
                        followerKeyUserHandle);
                }
                else if (relationshipOperation == RelationshipOperation.PendingUser)
                {
                    await this.notificationsManager.CreateNotification(
                        processType,
                        followerKeyUserHandle,
                        appHandle,
                        relationshipHandle,
                        ActivityType.FollowRequest,
                        followingKeyUserHandle,
                        followerKeyUserHandle,
                        ContentType.Unknown,
                        null,
                        lastUpdatedTime);
                }
                else if (relationshipOperation == RelationshipOperation.AcceptUser)
                {
                    await this.notificationsManager.CreateNotification(
                        processType,
                        followingKeyUserHandle,
                        appHandle,
                        relationshipHandle,
                        ActivityType.FollowAccept,
                        followerKeyUserHandle,
                        followingKeyUserHandle,
                        ContentType.Unknown,
                        null,
                        lastUpdatedTime);

                    await this.followingImportsQueue.SendFollowingImportMessage(
                        followingKeyUserHandle,
                        appHandle,
                        followerKeyUserHandle);
                }

                // Update popular user feed when follower count changes
                if (relationshipOperation == RelationshipOperation.FollowUser ||
                    relationshipOperation == RelationshipOperation.UnfollowUser ||
                    relationshipOperation == RelationshipOperation.DeleteFollower ||
                    relationshipOperation == RelationshipOperation.BlockUser ||
                    relationshipOperation == RelationshipOperation.AcceptUser)
                {
                    long?followersCount = await this.userRelationshipsStore.QueryFollowersCount(followerKeyUserHandle, appHandle);

                    long followersCountValue = followersCount.HasValue ? followersCount.Value : 0;
                    if (followersCountValue % PopularUsersUpdateFollowersCount == 0)
                    {
                        await this.popularUsersManager.UpdatePopularUser(processType, followerKeyUserHandle, appHandle, followersCountValue);
                    }
                }
            }
        }
        /// <summary>
        /// Update a relationship with another user
        /// </summary>
        /// <param name="callerClassName">name of the controller class of the caller</param>
        /// <param name="callerMethodName">name of method insider controller class of the caller (should correspond to an HTTP action)</param>
        /// <param name="relationshipOperation">Relationship operation</param>
        /// <param name="actedOnUserHandle">Acted on user handle</param>
        /// <returns>No content on success</returns>
        protected async Task <IHttpActionResult> UpdateRelationshipToUser(
            string callerClassName,
            string callerMethodName,
            RelationshipOperation relationshipOperation,
            string actedOnUserHandle)
        {
            string   actorUserHandle = this.UserHandle;
            DateTime currentTime     = DateTime.UtcNow;

            if (actorUserHandle == actedOnUserHandle)
            {
                this.BadRequest(ResponseStrings.NotAllowed);
            }

            IUserProfileEntity userProfileEntity = await this.usersManager.ReadUserProfile(actedOnUserHandle, this.AppHandle);

            if (userProfileEntity == null)
            {
                this.NotFound(ResponseStrings.UserNotFound);
            }

            if (relationshipOperation == RelationshipOperation.FollowUser &&
                userProfileEntity.Visibility == UserVisibilityStatus.Private)
            {
                relationshipOperation = RelationshipOperation.PendingUser;
            }

            string followerKeyUserHandle  = actorUserHandle;
            string followingKeyUserHandle = actedOnUserHandle;

            if (relationshipOperation == RelationshipOperation.FollowUser ||
                relationshipOperation == RelationshipOperation.PendingUser ||
                relationshipOperation == RelationshipOperation.UnfollowUser)
            {
                followerKeyUserHandle  = actedOnUserHandle;
                followingKeyUserHandle = actorUserHandle;
            }

            IUserRelationshipLookupEntity followerRelationshipLookupEntity
                = await this.relationshipsManager.ReadFollowerRelationship(followerKeyUserHandle, followingKeyUserHandle, this.AppHandle);

            if (followerRelationshipLookupEntity != null && followerRelationshipLookupEntity.LastUpdatedTime > currentTime)
            {
                return(this.Conflict(ResponseStrings.NewerItemExists));
            }

            IUserRelationshipLookupEntity followingRelationshipLookupEntity
                = await this.relationshipsManager.ReadFollowingRelationshipToUser(followingKeyUserHandle, followerKeyUserHandle, this.AppHandle);

            if (followingRelationshipLookupEntity != null && followingRelationshipLookupEntity.LastUpdatedTime > currentTime)
            {
                return(this.Conflict(ResponseStrings.NewerItemExists));
            }

            if (relationshipOperation == RelationshipOperation.AcceptUser)
            {
                if (followerRelationshipLookupEntity == null ||
                    followerRelationshipLookupEntity.UserRelationshipStatus != UserRelationshipStatus.Pending)
                {
                    return(this.Forbidden(ResponseStrings.NotAllowed));
                }
            }

            string relationshipHandle = null;

            if (relationshipOperation == RelationshipOperation.AcceptUser ||
                relationshipOperation == RelationshipOperation.BlockUser ||
                relationshipOperation == RelationshipOperation.FollowUser ||
                relationshipOperation == RelationshipOperation.PendingUser)
            {
                relationshipHandle = this.handleGenerator.GenerateShortHandle();
            }

            await this.relationshipsManager.UpdateRelationshipToUser(
                ProcessType.Frontend,
                relationshipOperation,
                relationshipHandle,
                followerKeyUserHandle,
                followingKeyUserHandle,
                this.AppHandle,
                currentTime,
                followerRelationshipLookupEntity,
                followingRelationshipLookupEntity);

            string logEntry = $"ActedOnUserHandle = {actedOnUserHandle}, RelationshipOperation = {relationshipOperation.ToString()}, RelationshipHandle = {relationshipHandle}";

            logEntry += $", OldRelationshipStatus = {followingRelationshipLookupEntity?.UserRelationshipStatus.ToString()}, NewRelationshipStatus = {relationshipOperation.ToString()}";
            this.LogControllerEnd(this.log, callerClassName, callerMethodName, logEntry);
            return(this.NoContent());
        }