public async Task <ActionResult> Search([FromRoute] string serviceName, [FromQuery] string query) { // Check if parameters fulfill our basic requirements if (string.IsNullOrWhiteSpace(serviceName)) { return(NotFound()); } if (string.IsNullOrWhiteSpace(query)) { return(NotFound()); } logger.LogInformation($"{User.Identity.Name} @ {HttpContext.Connection.RemoteIpAddress} -> {Request.Path}{Request.QueryString}"); // Use the cache before contacting the requested service string cacheKey = GenerateCacheKey("search", serviceName, query); string cacheValue = null; try { var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(1)); cacheValue = await cache.GetStringAsync(cacheKey, cancellationTokenSource.Token); } catch (OperationCanceledException) { logger.LogError($"Search: Cache took too long to respond (> 1 second) [key: {cacheKey}]"); } catch (Exception exception) { logger.LogError($"Search: Cache threw an exception for data lookup: {exception} [key: {cacheKey}]"); } if (!string.IsNullOrWhiteSpace(cacheValue)) { try { var items = JsonConvert.DeserializeObject <RepeatedField <SearchResponseItem> >(cacheValue); return(new JsonResult(new { success = true, items, })); } catch (JsonReaderException readerException) { logger.LogError($"Service {serviceName} threw an exception during cache deserialization: {readerException}"); RemoveCacheString(cacheKey); } } // Use the respective service client to fetch data from a remote api or remote service WebradioService service = services.GetService(serviceName); if (service == null) { return(SearchFailure("service is not supported")); } SearchResponse response; try { var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(SearchRequestTimeoutInSeconds)); response = await service.Client.SearchAsync(new SearchRequest { Query = query }, cancellationToken : cancellationTokenSource.Token); } catch (OperationCanceledException) { logger.LogError($"Search: Service {serviceName} took too long to respond (> {SearchRequestTimeoutInSeconds} seconds)"); return(SearchFailure($"service timeout reached after {SearchRequestTimeoutInSeconds} seconds")); } catch (RpcException exception) { logger.LogError($"Service {serviceName} threw an exception: {exception}"); return(SearchFailure("service is out of order")); } // Check the response from the service if (response.Status == null || response.Items == null || !response.Status.Success) { return(SearchFailure(response.Status?.ErrorMessage)); } if (response.Items.Count > 0) { SetCacheString(cacheKey, JsonConvert.SerializeObject(response.Items), service.Configuration.SearchExpirationInSeconds); } return(new JsonResult(new { success = true, items = response.Items, })); }
public async Task <ActionResult> Stream([FromRoute] string serviceName, [FromRoute] string id) { // Check if parameters fulfill our basic requirements if (string.IsNullOrWhiteSpace(serviceName)) { return(NotFound()); } if (string.IsNullOrWhiteSpace(id)) { return(NotFound()); } logger.LogInformation($"{HttpContext.Connection.RemoteIpAddress} @ {User.Identity.Name} -> {Request.Path}{Request.QueryString}"); // Use the cache before contacting the requested service string cacheKey = GenerateCacheKey("stream", serviceName, id); string cacheValue = null; try { var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(1)); cacheValue = await cache.GetStringAsync(cacheKey, cancellationTokenSource.Token); } catch (OperationCanceledException) { logger.LogError($"Stream: Cache took too long to respond (> 1 second) [key: {cacheKey}]"); } catch (Exception exception) { logger.LogError($"Stream: Cache threw an exception for data lookup: {exception} [key: {cacheKey}]"); } if (!string.IsNullOrWhiteSpace(cacheValue)) { return(Redirect(cacheValue)); } // Use the respective service client to fetch data from a remote api or remote service WebradioService service = services.GetService(serviceName); if (service == null) { return(SearchFailure("service is not supported")); } StreamResponse response; try { var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(StreamRequestTimeoutInSeconds)); response = await service.Client.StreamAsync(new StreamRequest { Id = id }, cancellationToken : cancellationTokenSource.Token); } catch (OperationCanceledException) { logger.LogError($"Stream: Service {serviceName} took too long to respond (> {SearchRequestTimeoutInSeconds} seconds)"); return(NotFound()); } catch (RpcException exception) { logger.LogError($"Stream: Service {serviceName} threw an exception: {exception}"); return(NotFound()); } // Check the response from the service if (response.Status == null || !response.Status.Success || string.IsNullOrWhiteSpace(response.Url)) { return(NotFound()); } SetCacheString(cacheKey, response.Url, service.Configuration.StreamExpirationInSeconds); return(Redirect(response.Url)); }