1
1
using System . Text . Json ;
2
2
using AutoMapper ;
3
- using EventDriven . DDD . Abstractions . Repositories ;
4
3
using EventDriven . Sagas . Persistence . Abstractions ;
5
4
using EventDriven . Sagas . Persistence . Abstractions . DTO ;
6
5
using EventDriven . Sagas . Persistence . Abstractions . Repositories ;
@@ -15,11 +14,23 @@ namespace EventDriven.Sagas.Persistence.Redis.Repositories;
15
14
public class RedisPersistableSagaRepository < TSaga > : IPersistableSagaRepository < TSaga >
16
15
where TSaga : PersistableSaga
17
16
{
18
- private readonly IDistributedCache _cache ;
19
- private readonly DistributedCacheEntryOptions _cacheOptions ;
20
- private readonly IMapper _mapper ;
21
17
private readonly AsyncLock _syncRoot = new ( ) ;
22
18
19
+ /// <summary>
20
+ /// Distributed cache.
21
+ /// </summary>
22
+ protected readonly IDistributedCache Cache ;
23
+
24
+ /// <summary>
25
+ /// Distributed cache entry options.
26
+ /// </summary>
27
+ protected readonly DistributedCacheEntryOptions CacheOptions ;
28
+
29
+ /// <summary>
30
+ /// Auto mapper.
31
+ /// </summary>
32
+ protected readonly IMapper Mapper ;
33
+
23
34
/// <summary>
24
35
/// PersistableSagaRepository constructor.
25
36
/// </summary>
@@ -30,37 +41,40 @@ public RedisPersistableSagaRepository(IDistributedCache cache,
30
41
DistributedCacheEntryOptions cacheOptions ,
31
42
IMapper mapper )
32
43
{
33
- _cache = cache ;
34
- _cacheOptions = cacheOptions ;
35
- _mapper = mapper ;
44
+ Cache = cache ;
45
+ CacheOptions = cacheOptions ;
46
+ Mapper = mapper ;
36
47
}
37
48
38
49
/// <inheritdoc />
39
- public async Task < TSaga ? > GetAsync ( Guid id , TSaga newEntity )
50
+ public virtual async Task < TSaga ? > GetAsync ( Guid id , TSaga newEntity )
40
51
{
41
- var json = await _cache . GetStringAsync ( id . ToString ( ) ) ;
42
- if ( json is null ) return null ;
43
- var dto = JsonSerializer . Deserialize < PersistableSagaDto > ( json ) ;
44
- _mapper . Map ( dto , newEntity ) ;
45
- return newEntity ;
52
+ using ( await _syncRoot . LockAsync ( ) )
53
+ {
54
+ var json = await Cache . GetStringAsync ( id . ToString ( ) ) ;
55
+ if ( json is null ) return null ;
56
+ var dto = JsonSerializer . Deserialize < PersistableSagaDto > ( json ) ;
57
+ Mapper . Map ( dto , newEntity ) ;
58
+ return newEntity ;
59
+ }
46
60
}
47
61
48
62
/// <inheritdoc />
49
- public async Task < TSaga > CreateAsync ( TSaga newEntity )
63
+ public virtual async Task < TSaga > CreateAsync ( TSaga newEntity )
50
64
{
51
65
using ( await _syncRoot . LockAsync ( ) )
52
66
{
53
67
newEntity . ETag = Guid . NewGuid ( ) . ToString ( ) ;
54
- var dto = _mapper . Map < PersistableSagaDto > ( newEntity ) ;
68
+ var dto = Mapper . Map < PersistableSagaDto > ( newEntity ) ;
55
69
dto . Id = Guid . NewGuid ( ) ;
56
70
await InsertAsync ( dto ) ;
57
- _mapper . Map ( dto , newEntity ) ;
71
+ Mapper . Map ( dto , newEntity ) ;
58
72
return newEntity ;
59
73
}
60
74
}
61
75
62
76
/// <inheritdoc />
63
- public async Task < TSaga > SaveAsync ( TSaga existingEntity , TSaga newEntity )
77
+ public virtual async Task < TSaga > SaveAsync ( TSaga existingEntity , TSaga newEntity )
64
78
{
65
79
using ( await _syncRoot . LockAsync ( ) )
66
80
{
@@ -69,23 +83,23 @@ public async Task<TSaga> SaveAsync(TSaga existingEntity, TSaga newEntity)
69
83
return await CreateAsync ( newEntity ) ;
70
84
71
85
existingEntity . ETag = Guid . NewGuid ( ) . ToString ( ) ;
72
- var dto = _mapper . Map < PersistableSagaDto > ( existingEntity ) ;
86
+ var dto = Mapper . Map < PersistableSagaDto > ( existingEntity ) ;
73
87
dto . Id = Guid . NewGuid ( ) ;
74
88
await RemoveAsync ( existingEntity . Id ) ;
75
89
await InsertAsync ( dto ) ;
76
- _mapper . Map ( dto , newEntity ) ;
90
+ Mapper . Map ( dto , newEntity ) ;
77
91
return newEntity ;
78
92
}
79
93
}
80
94
81
95
/// <inheritdoc />
82
- public async Task RemoveAsync ( Guid id ) =>
83
- await _cache . RemoveAsync ( id . ToString ( ) ) ;
96
+ public virtual Task RemoveAsync ( Guid id ) =>
97
+ Cache . RemoveAsync ( id . ToString ( ) ) ;
84
98
85
- private async Task InsertAsync ( PersistableSagaDto dto )
99
+ private Task InsertAsync ( PersistableSagaDto dto )
86
100
{
87
101
var json = JsonSerializer . Serialize ( dto ) ;
88
- await _cache . SetStringAsync ( dto . SagaId . ToString ( ) , json , _cacheOptions ) ;
102
+ return Cache . SetStringAsync ( dto . SagaId . ToString ( ) , json , CacheOptions ) ;
89
103
}
90
104
}
91
105
@@ -100,10 +114,67 @@ public class RedisPersistableSagaRepository<TSaga, TMetaData> :
100
114
where TSaga : PersistableSaga < TMetaData >
101
115
where TMetaData : class
102
116
{
117
+ private readonly AsyncLock _syncRoot = new ( ) ;
118
+
103
119
/// <inheritdoc />
104
120
public RedisPersistableSagaRepository ( IDistributedCache cache ,
105
121
DistributedCacheEntryOptions cacheOptions , IMapper mapper ) :
106
122
base ( cache , cacheOptions , mapper )
107
123
{
108
124
}
125
+
126
+ /// <inheritdoc />
127
+ public override async Task < TSaga ? > GetAsync ( Guid id , TSaga newEntity )
128
+ {
129
+ using ( await _syncRoot . LockAsync ( ) )
130
+ {
131
+ var json = await Cache . GetStringAsync ( id . ToString ( ) ) ;
132
+ if ( json is null ) return null ;
133
+ var dto = JsonSerializer . Deserialize < PersistableSagaMetadataDto > ( json ) ;
134
+ if ( dto is null ) return null ;
135
+ Mapper . Map ( dto , newEntity ) ;
136
+ var metadata = JsonSerializer . Deserialize < TMetaData > ( dto . Metadata ) ;
137
+ newEntity . Metadata = metadata ;
138
+ return newEntity ;
139
+ }
140
+ }
141
+
142
+ /// <inheritdoc />
143
+ public override async Task < TSaga > CreateAsync ( TSaga newEntity )
144
+ {
145
+ using ( await _syncRoot . LockAsync ( ) )
146
+ {
147
+ newEntity . ETag = Guid . NewGuid ( ) . ToString ( ) ;
148
+ var dto = Mapper . Map < PersistableSagaMetadataDto > ( newEntity ) ;
149
+ dto . Id = Guid . NewGuid ( ) ;
150
+ await InsertAsync ( dto ) ;
151
+ Mapper . Map ( dto , newEntity ) ;
152
+ return newEntity ;
153
+ }
154
+ }
155
+
156
+ /// <inheritdoc />
157
+ public override async Task < TSaga > SaveAsync ( TSaga existingEntity , TSaga newEntity )
158
+ {
159
+ using ( await _syncRoot . LockAsync ( ) )
160
+ {
161
+ var existing = await GetAsync ( existingEntity . Id , newEntity ) ;
162
+ if ( existing is null )
163
+ return await CreateAsync ( newEntity ) ;
164
+
165
+ existingEntity . ETag = Guid . NewGuid ( ) . ToString ( ) ;
166
+ var dto = Mapper . Map < PersistableSagaMetadataDto > ( existingEntity ) ;
167
+ dto . Id = Guid . NewGuid ( ) ;
168
+ await RemoveAsync ( existingEntity . Id ) ;
169
+ await InsertAsync ( dto ) ;
170
+ Mapper . Map ( dto , newEntity ) ;
171
+ return newEntity ;
172
+ }
173
+ }
174
+
175
+ private Task InsertAsync ( PersistableSagaMetadataDto dto )
176
+ {
177
+ var json = JsonSerializer . Serialize ( dto ) ;
178
+ return Cache . SetStringAsync ( dto . SagaId . ToString ( ) , json , CacheOptions ) ;
179
+ }
109
180
}
0 commit comments