Example #1
0
        public async Task <IEnumerable <Movie> > GetMoviesAsync(MovieQueryParameters movieQueryParameters)
        {
            if (movieQueryParameters == null)
            {
                throw new ArgumentNullException(nameof(movieQueryParameters));
            }

            string key = movieQueryParameters.GetKey();

            if (App.UseCache && cache.Contains(key) && cache.Get(key) is List <Movie> m)
            {
                return(m);
            }

            string ids = App.SearchService.GetMovieIds(movieQueryParameters);

            // todo - add CVectorBase
            // todo - remove trace headers
            // todo - change to dataservice app name
            // todo - should we cache this?
            // nothing found
            if (string.IsNullOrEmpty(ids))
            {
                return(new List <Movie>());
            }

            List <Movie> movies = (List <Movie>) await InternalCosmosDBSqlQuery <Movie>(ids).ConfigureAwait(false);

            cache.Add(new CacheItem(key, movies), cachePolicy);

            return(movies);
        }
Example #2
0
        /// <summary>
        /// Get Cosmos query string based on query parameters
        /// </summary>
        /// <param name="movieQueryParameters">query params</param>
        /// <returns>Cosmos query string</returns>
        public string GetMovieIds(MovieQueryParameters movieQueryParameters)
        {
            List <Movie> cache;
            string       ids = string.Empty;

            if (movieQueryParameters == null)
            {
                cache = GetMovies(string.Empty, string.Empty, offset: 0, limit: 100);
            }
            else
            {
                cache = GetMovies(movieQueryParameters.Q, movieQueryParameters.Genre, movieQueryParameters.Year, movieQueryParameters.Rating, movieQueryParameters.ActorId, movieQueryParameters.GetOffset(), movieQueryParameters.PageSize);
            }

            foreach (Movie m in cache)
            {
                ids += $"'{m.Id}',";
            }

            // nothing found
            if (string.IsNullOrEmpty(ids))
            {
                return(string.Empty);
            }

            string sql = "select m.id, m.partitionKey, m.movieId, m.type, m.textSearch, m.title, m.year, m.runtime, m.rating, m.votes, m.totalScore, m.genres, m.roles from m where m.id in ({0}) order by m.textSearch ASC, m.movieId ASC";

            return(sql.Replace("{0}", ids[0..^ 1], StringComparison.Ordinal));
Example #3
0
        /// <summary>
        /// Search Movies Healthcheck
        /// </summary>
        /// <returns>HealthzCheck</returns>
        private async Task <HealthzCheck> SearchMoviesAsync(string query, Dictionary <string, object> data)
        {
            const string name = "searchMovies";

            MovieQueryParameters movieQuery = new MovieQueryParameters {
                Q = query
            };

            string path = "/api/movies?q=" + movieQuery.Q;

            stopwatch.Restart();

            try
            {
                _ = await DataService.Read <List <Movie> >(path, CVector).ConfigureAwait(false);

                return(BuildHealthzCheck(path, MaxResponseTime, null, data, name));
            }
            catch (Exception ex)
            {
                BuildHealthzCheck(path, MaxResponseTime, ex, data, name);

                // throw the exception so that HealthCheck logs
                throw;
            }
        }
Example #4
0
        public async Task <IActionResult> GetMoviesAsync([FromQuery] MovieQueryParameters movieQueryParameters)
        {
            if (movieQueryParameters == null)
            {
                throw new ArgumentNullException(nameof(movieQueryParameters));
            }

            System.Collections.Generic.List <Middleware.Validation.ValidationError> list = movieQueryParameters.Validate();

            if (list.Count > 0)
            {
                Logger.LogWarning(
                    new EventId((int)HttpStatusCode.BadRequest, HttpStatusCode.BadRequest.ToString()),
                    nameof(GetMoviesAsync),
                    "Invalid query string",
                    HttpContext);

                return(ResultHandler.CreateResult(list, Request.Path.ToString() + (Request.QueryString.HasValue ? Request.QueryString.Value : string.Empty)));
            }

            // get the result
            IActionResult res = await ResultHandler.Handle(dal.GetMoviesAsync(movieQueryParameters), Logger).ConfigureAwait(false);

            // use cache dal on Cosmos 429 errors
            if (App.Cache && res is JsonResult jres && jres.StatusCode == 429)
            {
                res = await ResultHandler.Handle(App.CacheDal.GetMoviesAsync(movieQueryParameters), Logger).ConfigureAwait(false);
            }

            return(res);
        }
Example #5
0
        public async Task <IEnumerable <Movie> > GetMoviesAsync(MovieQueryParameters movieQueryParameters)
        {
            if (movieQueryParameters == null)
            {
                throw new ArgumentNullException(nameof(movieQueryParameters));
            }

            string key = movieQueryParameters.GetKey();

            if (App.Cache && cache.Contains(key) && cache.Get(key) is List <Movie> m)
            {
                return(m);
            }

            string sql = App.SearchService.GetMovieIds(movieQueryParameters);

            List <Movie> movies = new List <Movie>();

            // retrieve the items
            if (!string.IsNullOrWhiteSpace(sql))
            {
                movies = (List <Movie>) await InternalCosmosDBSqlQuery <Movie>(sql).ConfigureAwait(false);
            }

            // add to cache
            if (App.Cache)
            {
                cache.Add(new CacheItem(key, movies), cachePolicy);
            }

            return(movies);
        }
        public async Task <IActionResult> GetMoviesAsync([FromQuery] MovieQueryParameters movieQueryParameters)
        {
            _ = movieQueryParameters ?? throw new ArgumentNullException(nameof(movieQueryParameters));

            return(await ResultHandler.Handle(
                       dal.GetMoviesAsync(movieQueryParameters), movieQueryParameters.GetMethodText(HttpContext), Constants.MoviesControllerException, logger)
                   .ConfigureAwait(false));
        }
Example #7
0
        /// <summary>
        /// Add parameters to the method name if specified in the query string
        /// </summary>
        /// <param name="movieQueryParameters">movie query parameters</param>
        /// <param name="httpContext">HttpContext</param>
        /// <returns>method name</returns>
        public static string GetMethodText(this MovieQueryParameters movieQueryParameters, HttpContext httpContext)
        {
            if (movieQueryParameters == null)
            {
                throw new ArgumentNullException(nameof(movieQueryParameters));
            }

            if (httpContext == null)
            {
                throw new ArgumentNullException(nameof(httpContext));
            }

            string method = "GetMovies";

            if (httpContext?.Request?.Query == null)
            {
                return(method);
            }

            // add the query parameters to the method name if exists
            if (httpContext.Request.Query.ContainsKey("q"))
            {
                method = $"{method}:q:{movieQueryParameters.Q}";
            }

            if (httpContext.Request.Query.ContainsKey("genre"))
            {
                method = $"{method}:genre:{movieQueryParameters.Genre}";
            }

            if (httpContext.Request.Query.ContainsKey("year"))
            {
                method = $"{method}:year:{movieQueryParameters.Year}";
            }

            if (httpContext.Request.Query.ContainsKey("rating"))
            {
                method = $"{method}:rating:{movieQueryParameters.Rating}";
            }

            if (httpContext.Request.Query.ContainsKey("actorId"))
            {
                method = $"{method}:actorId:{movieQueryParameters.ActorId}";
            }

            if (httpContext.Request.Query.ContainsKey("pageNumber"))
            {
                method = $"{method}:pageNumber:{movieQueryParameters.PageNumber}";
            }

            if (httpContext.Request.Query.ContainsKey("pageSize"))
            {
                method = $"{method}:pageSize:{movieQueryParameters.PageSize}";
            }

            return(method);
        }
Example #8
0
        /// <summary>
        /// Get list of Movies based on query parameters
        /// </summary>
        /// <param name="movieQueryParameters">query params</param>
        /// <returns>List of Movie</returns>
        public Task <IEnumerable <Movie> > GetMoviesAsync(MovieQueryParameters movieQueryParameters)
        {
            // call the worker with the params
            if (movieQueryParameters == null)
            {
                return(GetMoviesAsync(string.Empty, string.Empty, offset: 0, limit: 100));
            }

            return(GetMoviesAsync(movieQueryParameters.Q, movieQueryParameters.Genre, movieQueryParameters.Year, movieQueryParameters.Rating, movieQueryParameters.ActorId, movieQueryParameters.GetOffset(), movieQueryParameters.PageSize));
        }
        public void YearInput_ValidateRegularExpression_ReturnsExpectedResult(int input, bool expectedResult)
        {
            // Arrange
            var yearValidation = new MovieQueryParameters();

            // Act
            var actualResult = IsValidProperty(yearValidation, input, "Year");

            // Assert
            Assert.Equal(expectedResult, actualResult);
        }
        public void RatingInput_ValidateModel_ReturnsExpectedResult(double input, bool expectedResult)
        {
            // Arrange
            var queryParameters = new MovieQueryParameters();

            // Act
            var actualValue = IsValidProperty(queryParameters, input, "Rating");

            // Assert
            Assert.Equal(expectedResult, actualValue);
        }
        public void ActorIdInMovieQueryParameters_ValidateRegularExpression_ReturnsExpectedResult(string input, bool expectedResult)
        {
            // Arrange
            var actorIdParameter = new MovieQueryParameters();

            // Act
            var isValid = IsValidProperty(actorIdParameter, input, "ActorId");

            // Assert
            Assert.Equal(expectedResult, isValid);
        }
Example #12
0
        public async Task <IActionResult> GetMoviesAsync([FromQuery] MovieQueryParameters movieQueryParameters)
        {
            if (movieQueryParameters == null)
            {
                throw new ArgumentNullException(nameof(movieQueryParameters));
            }

            return(await DataService.Read <List <Movie> >(Request).ConfigureAwait(false));

            //return await ResultHandler.Handle(
            //    dal.GetMoviesAsync(movieQueryParameters), movieQueryParameters.GetMethodText(HttpContext), Constants.MoviesControllerException, logger)
            //    .ConfigureAwait(false);
        }
Example #13
0
        public async Task <IActionResult> GetMoviesAsync([FromQuery] MovieQueryParameters movieQueryParameters)
        {
            if (movieQueryParameters == null)
            {
                throw new ArgumentNullException(nameof(movieQueryParameters));
            }

            // get the result
            IActionResult res = await ResultHandler.Handle(dal.GetMoviesAsync(movieQueryParameters), movieQueryParameters.GetMethodText(HttpContext), Constants.MoviesControllerException, logger).ConfigureAwait(false);

            // use cache dal on Cosmos 429 errors
            if (res is JsonResult jres && jres.StatusCode == 429)
            {
                res = await ResultHandler.Handle(App.CacheDal.GetMoviesAsync(movieQueryParameters), movieQueryParameters.GetMethodText(HttpContext), Constants.MoviesControllerException, logger).ConfigureAwait(false);
            }

            return(res);
        }
Example #14
0
        public async Task <IActionResult> GetMovieByIdAsync([FromRoute] string movieId)
        {
            Logger.LogInformation(nameof(GetMovieByIdAsync), "Web Request", HttpContext);

            if (string.IsNullOrWhiteSpace(movieId))
            {
                throw new ArgumentNullException(nameof(movieId));
            }

            List <Middleware.Validation.ValidationError> list = MovieQueryParameters.ValidateMovieId(movieId);

            if (list.Count > 0)
            {
                Logger.LogWarning(new EventId((int)HttpStatusCode.BadRequest, HttpStatusCode.BadRequest.ToString()), nameof(GetMovieByIdAsync), "Invalid Movie Id", HttpContext);

                return(ResultHandler.CreateResult(list, Request.Path.ToString() + (Request.QueryString.HasValue ? Request.QueryString.Value : string.Empty)));
            }

            return(await DataService.Read <Movie>(Request).ConfigureAwait(false));
        }
Example #15
0
        /// <summary>
        /// Get a list of Movies by search and/or filter terms
        /// </summary>
        /// <param name="movieQueryParameters">movie search parameters</param>
        /// <returns>List of Movies or an empty list</returns>
        public async Task<IEnumerable<Movie>> GetMoviesAsync(MovieQueryParameters movieQueryParameters)
        {
            if (movieQueryParameters == null)
            {
                throw new ArgumentNullException(nameof(movieQueryParameters));
            }

            string sql = MovieSelect;

            int offset = movieQueryParameters.GetOffset();
            int limit = movieQueryParameters.PageSize;

            string offsetLimit = string.Format(CultureInfo.InvariantCulture, MovieOffset, offset, limit);

            if (!string.IsNullOrWhiteSpace(movieQueryParameters.Q))
            {
                movieQueryParameters.Q = movieQueryParameters.Q.Trim();
                sql += " and contains(m.title, @q, true) ";
            }

            if (movieQueryParameters.Year > 0)
            {
                sql += " and m.year = @year ";
            }

            if (movieQueryParameters.Rating > 0)
            {
                sql += " and m.rating >= @rating ";
            }

            if (!string.IsNullOrWhiteSpace(movieQueryParameters.ActorId))
            {
                // convert to lower
                movieQueryParameters.ActorId = movieQueryParameters.ActorId.Trim().ToLowerInvariant();
                sql += " and array_contains(m.roles, { actorId: @actorId }, true) ";
            }

            if (!string.IsNullOrWhiteSpace(movieQueryParameters.Genre))
            {
                movieQueryParameters.Genre = movieQueryParameters.Genre.Trim();
                sql += " and contains(m.genreSearch, @genre, true) ";
            }

            sql += MovieOrderBy + offsetLimit;

            // Parameterize fields
            QueryDefinition queryDefinition = new QueryDefinition(sql);

            if (!string.IsNullOrWhiteSpace(movieQueryParameters.Q))
            {
                queryDefinition.WithParameter("@q", movieQueryParameters.Q);
            }

            if (!string.IsNullOrWhiteSpace(movieQueryParameters.ActorId))
            {
                queryDefinition.WithParameter("@actorId", movieQueryParameters.ActorId);
            }

            if (!string.IsNullOrWhiteSpace(movieQueryParameters.Genre))
            {
                // genreSearch is stored delimited with :
                queryDefinition.WithParameter("@genre", "|" + movieQueryParameters.Genre + "|");
            }

            if (movieQueryParameters.Year > 0)
            {
                queryDefinition.WithParameter("@year", movieQueryParameters.Year);
            }

            if (movieQueryParameters.Rating > 0)
            {
                queryDefinition.WithParameter("@rating", movieQueryParameters.Rating);
            }

            return await InternalCosmosDBSqlQuery<Movie>(queryDefinition).ConfigureAwait(false);
        }
        public void GivenMovieParameter_ValidateString_ReturnsValidMethodName(string queryProperty, string queryValue, MovieQueryParameters parameterObject)
        {
            // Arrange
            var logger   = new Mock <ILogger <MoviesController> >();
            var mockIDAL = new Mock <IDAL>();

            var controller = new MoviesController(logger.Object, mockIDAL.Object)
            {
                ControllerContext = new ControllerContext()
            };

            var request = new Dictionary <string, StringValues>
            {
                { queryProperty, queryValue }
            };

            var queryCollection = new QueryCollection(request);
            var query           = new QueryFeature(queryCollection);
            var features        = new FeatureCollection();

            features.Set <IQueryFeature>(query);
            controller.ControllerContext.HttpContext = new DefaultHttpContext(features);

            // Act
            var expectedResult = $"GetMovies:{queryProperty}:{queryValue}";
            var actualResult   = parameterObject.GetMethodText(controller.HttpContext);

            // Assert
            Assert.Equal(expectedResult, actualResult);
        }