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); }
/// <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));
/// <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; } }
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); }
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)); }
/// <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); }
/// <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); }
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); }
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); }
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)); }
/// <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); }