/// <summary>
        /// Gets the personalized video suggestions for a specific user.
        /// </summary>
        public override async Task <GetSuggestedForUserResponse> GetSuggestedForUser(GetSuggestedForUserRequest request, ServerCallContext context)
        {
            // Return the output of a Spark job that runs periodically in the background to populate the video_recommendations table
            // (see the /data/spark folder in the repo for more information)
            PreparedStatement prepared = await _statementCache.GetOrAddAsync(
                "SELECT videoid, authorid, name, added_date, preview_image_location FROM video_recommendations WHERE userid=?");

            IStatement bound = prepared.Bind(request.UserId.ToGuid())
                               .SetAutoPage(false)
                               .SetPageSize(request.PageSize);

            // The initial query won't have a paging state, but subsequent calls should if there are more pages
            if (string.IsNullOrEmpty(request.PagingState) == false)
            {
                bound.SetPagingState(Convert.FromBase64String(request.PagingState));
            }

            RowSet rows = await _session.ExecuteAsync(bound).ConfigureAwait(false);

            var response = new GetSuggestedForUserResponse
            {
                UserId      = request.UserId,
                PagingState = rows.PagingState != null && rows.PagingState.Length > 0 ? Convert.ToBase64String(rows.PagingState) : ""
            };

            response.Videos.Add(rows.Select(MapRowToVideoPreview));
            return(response);
        }
        /// <summary>
        /// Gets the personalized video suggestions for a specific user.
        /// Based on DSL tutorial provided here, we changed the recommendation from pre-aggration
        /// tables to real-time graph recommendation.
        /// https://academy.datastax.com/content/gremlin-dsls-net-dse-graph
        /// </summary>
        public override async Task <GetSuggestedForUserResponse> GetSuggestedForUser(GetSuggestedForUserRequest request,
                                                                                     ServerCallContext context)
        {
            Logger.Information("Request suggested video(s) for user {user}", request.UserId.Value);
            GraphTraversalSource g = DseGraph.Traversal(_session);

            // DSL Baby !
            var traversal = g.RecommendVideos(request.UserId.ToGuid().ToString(), 5, 4, 1000, 5);

            GraphResultSet result = await _session.ExecuteGraphAsync(traversal);

            // Building GRPC response from list of results vertices (hopefully 'numberOfVideosExpected')
            var grpcResponse = new GetSuggestedForUserResponse
            {
                UserId      = request.UserId,
                PagingState = ""
            };

            foreach (IVertex vertex in result.To <IVertex>())
            {
                Logger.Information("Result " + vertex);
                grpcResponse.Videos.Add(MapVertexToVideoPreview(vertex));
            }
            return(grpcResponse);
        }
        /// <summary>
        /// Gets the personalized video suggestions for a specific user.
        /// </summary>
        public override Task <GetSuggestedForUserResponse> GetSuggestedForUser(GetSuggestedForUserRequest request, ServerCallContext context)
        {
            // TODO: Can we implement suggestions without DSE and Spark? (Yeah, probably not)
            var response = new GetSuggestedForUserResponse {
                UserId = request.UserId
            };

            return(Task.FromResult(response));
        }