예제 #1
0
        /// <summary>
        /// Gets multiple user profiles by their Ids.
        /// </summary>
        public override async Task <GetUserProfileResponse> GetUserProfile(GetUserProfileRequest request, ServerCallContext context)
        {
            var response = new GetUserProfileResponse();

            if (request.UserIds == null || request.UserIds.Count == 0)
            {
                return(response);
            }

            // Since we're essentially doing a multi-get here, limit the number userIds (i.e. partition keys) to 20 in an attempt
            // to enforce some performance sanity.  Anything larger and we might want to consider a different data model that doesn't
            // involve doing a multi-get
            if (request.UserIds.Count > 20)
            {
                var status = new Status(StatusCode.InvalidArgument, "Cannot get more than 20 user profiles at once");
                throw new RpcException(status);
            }

            // Do some LINQ queries in parallel
            IEnumerable <Task <IEnumerable <LinqDtos.UserProfile> > > getProfilesTasks = request.UserIds.Select(uuid => _userProfileTable.Where(up => up.UserId == uuid.ToGuid()).ExecuteAsync());

            IEnumerable <LinqDtos.UserProfile>[] profiles = await Task.WhenAll(getProfilesTasks).ConfigureAwait(false);

            // Get first profile returned for each query if not null and add to response
            response.Profiles.Add(profiles.Select(ps => ps.SingleOrDefault()).Where(p => p != null).Select(p => new UserProfile
            {
                UserId    = p.UserId.ToUuid(),
                Email     = p.EmailAddress,
                FirstName = p.FirstName,
                LastName  = p.LastName
            }));
            return(response);
        }
        /// <summary>
        /// Gets multiple user profiles by their Ids.
        /// </summary>
        public override async Task <GetUserProfileResponse> GetUserProfile(GetUserProfileRequest request, ServerCallContext context)
        {
            var response = new GetUserProfileResponse();

            if (request.UserIds == null || request.UserIds.Count == 0)
            {
                return(response);
            }

            // Since we're essentially doing a multi-get here, limit the number userIds (i.e. partition keys) to 20 in an attempt
            // to enforce some performance sanity.  Anything larger and we might want to consider a different data model that doesn't
            // involve doing a multi-get
            if (request.UserIds.Count > 20)
            {
                var status = new Status(StatusCode.InvalidArgument, "Cannot get more than 20 user profiles at once");
                throw new RpcException(status);
            }

            // As an example, we'll do the multi-get at the CQL level using an IN() clause (i.e. let Cassandra handle it).  For an example of
            // doing it at the driver level, see the VideoCatalog's GetVideoPreviews method

            // Build a parameterized CQL statement with an IN clause
            var parameterList = string.Join(", ", Enumerable.Repeat("?", request.UserIds.Count));
            var cql           = $"SELECT userid, firstname, lastname, email FROM users WHERE userid IN ({parameterList})";
            var statement     = new SimpleStatement(cql, request.UserIds.Select(uuid => uuid.ToGuid()).Cast <object>().ToArray());

            // Execute and map to UserProfile object
            RowSet resultRows = await _session.ExecuteAsync(statement).ConfigureAwait(false);

            response.Profiles.Add(resultRows.Select(MapRowToUserProfile));
            return(response);
        }