1616using System . Linq ;
1717using System . Threading . Tasks ;
1818using Grpc . Core ;
19- using StackExchange . Redis ;
19+ using Microsoft . Extensions . Caching . Distributed ;
2020using Google . Protobuf ;
2121
2222namespace cartservice . cartstore
2323{
2424 public class RedisCartStore : ICartStore
2525 {
26- private const string CART_FIELD_NAME = "cart" ;
27- private const int REDIS_RETRY_NUM = 30 ;
26+ private readonly IDistributedCache _cache ;
2827
29- private volatile ConnectionMultiplexer redis ;
30- private volatile bool isRedisConnectionOpened = false ;
31-
32- private readonly object locker = new object ( ) ;
33- private readonly byte [ ] emptyCartBytes ;
34- private readonly string connectionString ;
35-
36- private readonly ConfigurationOptions redisConnectionOptions ;
37-
38- public RedisCartStore ( string redisAddress )
39- {
40- // Serialize empty cart into byte array.
41- var cart = new Hipstershop . Cart ( ) ;
42- emptyCartBytes = cart . ToByteArray ( ) ;
43- connectionString = $ "{ redisAddress } ,ssl=false,allowAdmin=true,abortConnect=false";
44-
45- redisConnectionOptions = ConfigurationOptions . Parse ( connectionString ) ;
46-
47- // Try to reconnect multiple times if the first retry fails.
48- redisConnectionOptions . ConnectRetry = REDIS_RETRY_NUM ;
49- redisConnectionOptions . ReconnectRetryPolicy = new ExponentialRetry ( 1000 ) ;
50-
51- redisConnectionOptions . KeepAlive = 180 ;
52- }
53-
54- public Task InitializeAsync ( )
28+ public RedisCartStore ( IDistributedCache cache )
5529 {
56- EnsureRedisConnected ( ) ;
57- return Task . CompletedTask ;
58- }
59-
60- private void EnsureRedisConnected ( )
61- {
62- if ( isRedisConnectionOpened )
63- {
64- return ;
65- }
66-
67- // Connection is closed or failed - open a new one but only at the first thread
68- lock ( locker )
69- {
70- if ( isRedisConnectionOpened )
71- {
72- return ;
73- }
74-
75- Console . WriteLine ( "Connecting to Redis: " + connectionString ) ;
76- redis = ConnectionMultiplexer . Connect ( redisConnectionOptions ) ;
77-
78- if ( redis == null || ! redis . IsConnected )
79- {
80- Console . WriteLine ( "Wasn't able to connect to redis" ) ;
81-
82- // We weren't able to connect to Redis despite some retries with exponential backoff.
83- throw new ApplicationException ( "Wasn't able to connect to redis" ) ;
84- }
85-
86- Console . WriteLine ( "Successfully connected to Redis" ) ;
87- var cache = redis . GetDatabase ( ) ;
88-
89- Console . WriteLine ( "Performing small test" ) ;
90- cache . StringSet ( "cart" , "OK" ) ;
91- object res = cache . StringGet ( "cart" ) ;
92- Console . WriteLine ( $ "Small test result: { res } ") ;
93-
94- redis . InternalError += ( o , e ) => { Console . WriteLine ( e . Exception ) ; } ;
95- redis . ConnectionRestored += ( o , e ) =>
96- {
97- isRedisConnectionOpened = true ;
98- Console . WriteLine ( "Connection to redis was retored successfully" ) ;
99- } ;
100- redis . ConnectionFailed += ( o , e ) =>
101- {
102- Console . WriteLine ( "Connection failed. Disposing the object" ) ;
103- isRedisConnectionOpened = false ;
104- } ;
105-
106- isRedisConnectionOpened = true ;
107- }
30+ _cache = cache ;
10831 }
10932
11033 public async Task AddItemAsync ( string userId , string productId , int quantity )
@@ -113,15 +36,9 @@ public async Task AddItemAsync(string userId, string productId, int quantity)
11336
11437 try
11538 {
116- EnsureRedisConnected ( ) ;
117-
118- var db = redis . GetDatabase ( ) ;
119-
120- // Access the cart from the cache
121- var value = await db . HashGetAsync ( userId , CART_FIELD_NAME ) ;
122-
12339 Hipstershop . Cart cart ;
124- if ( value . IsNull )
40+ var value = await _cache . GetAsync ( userId ) ;
41+ if ( value == null )
12542 {
12643 cart = new Hipstershop . Cart ( ) ;
12744 cart . UserId = userId ;
@@ -140,8 +57,7 @@ public async Task AddItemAsync(string userId, string productId, int quantity)
14057 existingItem . Quantity += quantity ;
14158 }
14259 }
143-
144- await db . HashSetAsync ( userId , new [ ] { new HashEntry ( CART_FIELD_NAME , cart . ToByteArray ( ) ) } ) ;
60+ await _cache . SetAsync ( userId , cart . ToByteArray ( ) ) ;
14561 }
14662 catch ( Exception ex )
14763 {
@@ -155,11 +71,8 @@ public async Task EmptyCartAsync(string userId)
15571
15672 try
15773 {
158- EnsureRedisConnected ( ) ;
159- var db = redis . GetDatabase ( ) ;
160-
161- // Update the cache with empty cart for given user
162- await db . HashSetAsync ( userId , new [ ] { new HashEntry ( CART_FIELD_NAME , emptyCartBytes ) } ) ;
74+ var cart = new Hipstershop . Cart ( ) ;
75+ await _cache . SetAsync ( userId , cart . ToByteArray ( ) ) ;
16376 }
16477 catch ( Exception ex )
16578 {
@@ -173,14 +86,10 @@ public async Task EmptyCartAsync(string userId)
17386
17487 try
17588 {
176- EnsureRedisConnected ( ) ;
177-
178- var db = redis . GetDatabase ( ) ;
179-
18089 // Access the cart from the cache
181- var value = await db . HashGetAsync ( userId , CART_FIELD_NAME ) ;
90+ var value = await _cache . GetAsync ( userId ) ;
18291
183- if ( ! value . IsNull )
92+ if ( value != null )
18493 {
18594 return Hipstershop . Cart . Parser . ParseFrom ( value ) ;
18695 }
@@ -198,9 +107,7 @@ public bool Ping()
198107 {
199108 try
200109 {
201- var cache = redis . GetDatabase ( ) ;
202- var res = cache . Ping ( ) ;
203- return res != TimeSpan . Zero ;
110+ return true ;
204111 }
205112 catch ( Exception )
206113 {
0 commit comments