From cea97485fd8ba2ea142fe4cf9ac235cf6bb2f5e1 Mon Sep 17 00:00:00 2001 From: Leefrost Date: Sat, 1 Apr 2023 21:44:12 +0300 Subject: [PATCH 1/2] Update docs --- README.md | 63 ++++++++++++-------- samples/ConsoleApp/Program.cs | 19 +++--- src/HttpClient.Cache/HttpClient.Cache.csproj | 7 +-- src/HttpClient.Cache/README.md | 63 ++++++++++++-------- 4 files changed, 86 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index bf9d77d..a0cd128 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,33 @@ -# HttpClient.Cache +## HttpClient.Cache -A caching wrapper around HttpClient to cache responses +A lightweight in-memory cache for HttpClient. ### The Purpose -Working with some high load systems or with system where is important to have good response time -cache is a first one citizen. +Working with high-load systems or with a system where it is important to have a good response time - the cache is a first citizen. This package contains lightweight, self-written, in-memory cache implementation to catch and store responses based on their status code. The configuration is pretty flexible and gives opportynity to set pair between cache time and response code. -### Install - -//TODO Nuget deployment +### How to install ```shell -foo@bar:~$ Install-Package HttpClient.Cache +dotnet add package Leefrost.HttpClient.Cache ``` -### Examples +### Plans and TODOs: + +- [x] in-memory caching support +- [ ] distributed caching support + +### How to use + +The code below caches 3 top-kind responses (OK, BadRequest, and InternalServerError) for a different time - 60/10/5 seconds. +HttpClient will do 5 requests to the `https://randomuser.me/api/` and do cache the responses for us. + +The cache report will show us 1 miss (initial request) and 4 hits (so the response time will be 0) ```csharp -const string url = "http://worldclockapi.com/api/json/utc/now"; +const string url = "https://randomuser.me/api/"; -//Set the cache time for each required status +//Setting the cache time for each required status var cacheExpiration = new Dictionary { {HttpStatusCode.OK, TimeSpan.FromSeconds(60)}, @@ -28,15 +35,14 @@ var cacheExpiration = new Dictionary {HttpStatusCode.InternalServerError, TimeSpan.FromSeconds(5)} }; -//Client calls API and caches it -//Report will show 1 Miss (initial) and 4 Hits. -var innerHandler = new HttpClientHandler(); -var cacheHandler = new InMemoryCacheHandler(innerHandler, cacheExpiration); -using (var httpClient = new System.Net.Http.HttpClient(cacheHandler)) +//Calling the API and cache the responses +var requestHandler = new HttpClientHandler(); +var cacheHandler = new InMemoryCacheHandler(requestHandler, cacheExpiration); +using (var httpClient = new HttpClient(cacheHandler)) { for (int i = 1; i <= 5; ++i) { - Console.Write($"Try: {i}: {url} "); + Console.Write($"Attempt {i}: {url}"); var stopwatch = Stopwatch.StartNew(); var result = await httpClient.GetAsync(url); @@ -46,23 +52,28 @@ using (var httpClient = new System.Net.Http.HttpClient(cacheHandler)) Console.WriteLine($"Done in: {stopwatch.ElapsedMilliseconds} ms"); await Task.Delay(TimeSpan.FromSeconds(1)); } + Console.WriteLine(); } +//Checking cache stats var stats = cacheHandler.StatsProvider.GetReport(); Console.WriteLine($"Cache stats - total requests: {stats.Total.TotalRequests}"); Console.WriteLine($"--> Hit: {stats.Total.CacheHit} [{stats.Total.TotalHitsPercent}]"); Console.WriteLine($"--> Miss: {stats.Total.CacheMiss} [{stats.Total.TotalMissPercent}]"); Console.ReadLine(); ``` -Will generate next output: -```console -Try: 1: http://worldclockapi.com/api/json/utc/now --> OK Done in: 450 ms -Try: 2: http://worldclockapi.com/api/json/utc/now --> OK Done in: 57 ms -Try: 3: http://worldclockapi.com/api/json/utc/now --> OK Done in: 0 ms -Try: 4: http://worldclockapi.com/api/json/utc/now --> OK Done in: 0 ms -Try: 5: http://worldclockapi.com/api/json/utc/now --> OK Done in: 0 ms + +Console will show next output: + +```shell +Attempt 1: https://randomuser.me/api/ --> OK Done in: 681 ms +Attempt 2: https://randomuser.me/api/ --> OK Done in: 75 ms +Attempt 3: https://randomuser.me/api/ --> OK Done in: 0 ms +Attempt 4: https://randomuser.me/api/ --> OK Done in: 0 ms +Attempt 5: https://randomuser.me/api/ --> OK Done in: 0 ms + Cache stats - total requests: 5 ---> Hit: 4 [0,8] ---> Miss: 1 [0,2] +--> Hits: 4 [0,8] +--> Misses: 1 [0,2] ``` \ No newline at end of file diff --git a/samples/ConsoleApp/Program.cs b/samples/ConsoleApp/Program.cs index 7fde19e..d6ad359 100644 --- a/samples/ConsoleApp/Program.cs +++ b/samples/ConsoleApp/Program.cs @@ -2,9 +2,9 @@ using System.Net; using HttpClient.Cache.InMemory; -const string url = "http://worldclockapi.com/api/json/utc/now"; +const string url = "https://randomuser.me/api/"; -//Set the cache time for each required status +//Setting the cache time for each required status var cacheExpiration = new Dictionary { {HttpStatusCode.OK, TimeSpan.FromSeconds(60)}, @@ -12,15 +12,14 @@ {HttpStatusCode.InternalServerError, TimeSpan.FromSeconds(5)} }; -//Client calls API and caches it -//Report will show 1 Miss (initial) and 4 Hits. -var innerHandler = new HttpClientHandler(); -var cacheHandler = new InMemoryCacheHandler(innerHandler, cacheExpiration); +//Calling the API and cache the responses +var requestHandler = new HttpClientHandler(); +var cacheHandler = new InMemoryCacheHandler(requestHandler, cacheExpiration); using (var httpClient = new System.Net.Http.HttpClient(cacheHandler)) { for (int i = 1; i <= 5; ++i) { - Console.Write($"Attempt: {i}: {url} "); + Console.Write($"Attempt {i}: {url}"); var stopwatch = Stopwatch.StartNew(); var result = await httpClient.GetAsync(url); @@ -30,10 +29,12 @@ Console.WriteLine($"Done in: {stopwatch.ElapsedMilliseconds} ms"); await Task.Delay(TimeSpan.FromSeconds(1)); } + Console.WriteLine(); } +//Checking cache stats var stats = cacheHandler.StatsProvider.GetReport(); Console.WriteLine($"Cache stats - total requests: {stats.Total.TotalRequests}"); -Console.WriteLine($"--> Hit: {stats.Total.CacheHit} [{stats.Total.TotalHitsPercent}]"); -Console.WriteLine($"--> Miss: {stats.Total.CacheMiss} [{stats.Total.TotalMissPercent}]"); +Console.WriteLine($"--> Hits: {stats.Total.CacheHit} [{stats.Total.TotalHitsPercent}]"); +Console.WriteLine($"--> Misses: {stats.Total.CacheMiss} [{stats.Total.TotalMissPercent}]"); Console.ReadLine(); diff --git a/src/HttpClient.Cache/HttpClient.Cache.csproj b/src/HttpClient.Cache/HttpClient.Cache.csproj index 3de1ae0..240a9a0 100644 --- a/src/HttpClient.Cache/HttpClient.Cache.csproj +++ b/src/HttpClient.Cache/HttpClient.Cache.csproj @@ -24,12 +24,9 @@ Leefrost.HttpClient.Cache Sergii Lischuk A simple and easy cache for HttpClient - - + Github + https://github.com/Leefrost/HttpClient.Cache https://codestory.me - - cache, httpclient, library diff --git a/src/HttpClient.Cache/README.md b/src/HttpClient.Cache/README.md index bf9d77d..91fb237 100644 --- a/src/HttpClient.Cache/README.md +++ b/src/HttpClient.Cache/README.md @@ -1,26 +1,33 @@ -# HttpClient.Cache +## HttpClient.Cache -A caching wrapper around HttpClient to cache responses +A lightweight in-memory cache for HttpClient. ### The Purpose -Working with some high load systems or with system where is important to have good response time -cache is a first one citizen. +Working with high-load systems or with a system where it is important to have a good response time - the cache is a first citizen. This package contains lightweight, self-written, in-memory cache implementation to catch and store responses based on their status code. The configuration is pretty flexible and gives opportynity to set pair between cache time and response code. -### Install - -//TODO Nuget deployment +### How to install ```shell -foo@bar:~$ Install-Package HttpClient.Cache +dotnet add package Leefrost.HttpClient.Cache ``` -### Examples +### Plans and TODOs: + +- [x] in-memory caching support +- [ ] distributed caching support + +### How to use + +The code below caches 3 top-kind responses (OK, BadRequest, and InternalServerError) for a different time - 60/10/5 seconds. +HttpClient will do 5 requests to the `https://randomuser.me/api/` and do cache the responses for us. + +The cache report will show us 1 miss (initial request) and 4 hits (so the response time will be 0) ```csharp -const string url = "http://worldclockapi.com/api/json/utc/now"; +const string url = "https://randomuser.me/api/"; -//Set the cache time for each required status +//Setting the cache time for each required status var cacheExpiration = new Dictionary { {HttpStatusCode.OK, TimeSpan.FromSeconds(60)}, @@ -28,15 +35,14 @@ var cacheExpiration = new Dictionary {HttpStatusCode.InternalServerError, TimeSpan.FromSeconds(5)} }; -//Client calls API and caches it -//Report will show 1 Miss (initial) and 4 Hits. -var innerHandler = new HttpClientHandler(); -var cacheHandler = new InMemoryCacheHandler(innerHandler, cacheExpiration); -using (var httpClient = new System.Net.Http.HttpClient(cacheHandler)) +//Calling the API and cache the responses +var requestHandler = new HttpClientHandler(); +var cacheHandler = new InMemoryCacheHandler(requestHandler, cacheExpiration); +using (var httpClient = new HttpClient(cacheHandler)) { for (int i = 1; i <= 5; ++i) { - Console.Write($"Try: {i}: {url} "); + Console.Write($"Attempt {i}: {url}"); var stopwatch = Stopwatch.StartNew(); var result = await httpClient.GetAsync(url); @@ -46,23 +52,28 @@ using (var httpClient = new System.Net.Http.HttpClient(cacheHandler)) Console.WriteLine($"Done in: {stopwatch.ElapsedMilliseconds} ms"); await Task.Delay(TimeSpan.FromSeconds(1)); } + Console.WriteLine(); } +//Checking cache stats var stats = cacheHandler.StatsProvider.GetReport(); Console.WriteLine($"Cache stats - total requests: {stats.Total.TotalRequests}"); Console.WriteLine($"--> Hit: {stats.Total.CacheHit} [{stats.Total.TotalHitsPercent}]"); Console.WriteLine($"--> Miss: {stats.Total.CacheMiss} [{stats.Total.TotalMissPercent}]"); Console.ReadLine(); ``` -Will generate next output: -```console -Try: 1: http://worldclockapi.com/api/json/utc/now --> OK Done in: 450 ms -Try: 2: http://worldclockapi.com/api/json/utc/now --> OK Done in: 57 ms -Try: 3: http://worldclockapi.com/api/json/utc/now --> OK Done in: 0 ms -Try: 4: http://worldclockapi.com/api/json/utc/now --> OK Done in: 0 ms -Try: 5: http://worldclockapi.com/api/json/utc/now --> OK Done in: 0 ms + +Console will show next output: + +```shell +Attempt 1: https://randomuser.me/api/ --> OK Done in: 681 ms +Attempt 2: https://randomuser.me/api/ --> OK Done in: 75 ms +Attempt 3: https://randomuser.me/api/ --> OK Done in: 0 ms +Attempt 4: https://randomuser.me/api/ --> OK Done in: 0 ms +Attempt 5: https://randomuser.me/api/ --> OK Done in: 0 ms + Cache stats - total requests: 5 ---> Hit: 4 [0,8] ---> Miss: 1 [0,2] +--> Hits: 4 [0,8] +--> Misses: 1 [0,2] ``` \ No newline at end of file From 3bf54e7f9e6f3e5f69429f6efd0f989cc7f2de2e Mon Sep 17 00:00:00 2001 From: Leefrost Date: Sat, 1 Apr 2023 21:45:23 +0300 Subject: [PATCH 2/2] Fixed code blocks --- README.md | 4 ++-- src/HttpClient.Cache/README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a0cd128..5a7d57e 100644 --- a/README.md +++ b/README.md @@ -58,8 +58,8 @@ using (var httpClient = new HttpClient(cacheHandler)) //Checking cache stats var stats = cacheHandler.StatsProvider.GetReport(); Console.WriteLine($"Cache stats - total requests: {stats.Total.TotalRequests}"); -Console.WriteLine($"--> Hit: {stats.Total.CacheHit} [{stats.Total.TotalHitsPercent}]"); -Console.WriteLine($"--> Miss: {stats.Total.CacheMiss} [{stats.Total.TotalMissPercent}]"); +Console.WriteLine($"--> Hits: {stats.Total.CacheHit} [{stats.Total.TotalHitsPercent}]"); +Console.WriteLine($"--> Misses: {stats.Total.CacheMiss} [{stats.Total.TotalMissPercent}]"); Console.ReadLine(); ``` diff --git a/src/HttpClient.Cache/README.md b/src/HttpClient.Cache/README.md index 91fb237..c40bf63 100644 --- a/src/HttpClient.Cache/README.md +++ b/src/HttpClient.Cache/README.md @@ -58,8 +58,8 @@ using (var httpClient = new HttpClient(cacheHandler)) //Checking cache stats var stats = cacheHandler.StatsProvider.GetReport(); Console.WriteLine($"Cache stats - total requests: {stats.Total.TotalRequests}"); -Console.WriteLine($"--> Hit: {stats.Total.CacheHit} [{stats.Total.TotalHitsPercent}]"); -Console.WriteLine($"--> Miss: {stats.Total.CacheMiss} [{stats.Total.TotalMissPercent}]"); +Console.WriteLine($"--> Hits: {stats.Total.CacheHit} [{stats.Total.TotalHitsPercent}]"); +Console.WriteLine($"--> Misses: {stats.Total.CacheMiss} [{stats.Total.TotalMissPercent}]"); Console.ReadLine(); ```