2
2
using System . Net ;
3
3
using System . Runtime . CompilerServices ;
4
4
using JetBrains . Annotations ;
5
+ using JsonApiDotNetCore . AtomicOperations ;
5
6
using JsonApiDotNetCore . Configuration ;
6
7
using JsonApiDotNetCore . Diagnostics ;
7
8
using JsonApiDotNetCore . Errors ;
@@ -30,11 +31,12 @@ public class JsonApiResourceService<TResource, TId> : IResourceService<TResource
30
31
private readonly TraceLogWriter < JsonApiResourceService < TResource , TId > > _traceWriter ;
31
32
private readonly IJsonApiRequest _request ;
32
33
private readonly IResourceChangeTracker < TResource > _resourceChangeTracker ;
34
+ private readonly IVersionTracker _versionTracker ;
33
35
private readonly IResourceDefinitionAccessor _resourceDefinitionAccessor ;
34
36
35
37
public JsonApiResourceService ( IResourceRepositoryAccessor repositoryAccessor , IQueryLayerComposer queryLayerComposer , IPaginationContext paginationContext ,
36
38
IJsonApiOptions options , ILoggerFactory loggerFactory , IJsonApiRequest request , IResourceChangeTracker < TResource > resourceChangeTracker ,
37
- IResourceDefinitionAccessor resourceDefinitionAccessor )
39
+ IVersionTracker versionTracker , IResourceDefinitionAccessor resourceDefinitionAccessor )
38
40
{
39
41
ArgumentGuard . NotNull ( repositoryAccessor , nameof ( repositoryAccessor ) ) ;
40
42
ArgumentGuard . NotNull ( queryLayerComposer , nameof ( queryLayerComposer ) ) ;
@@ -43,6 +45,7 @@ public JsonApiResourceService(IResourceRepositoryAccessor repositoryAccessor, IQ
43
45
ArgumentGuard . NotNull ( loggerFactory , nameof ( loggerFactory ) ) ;
44
46
ArgumentGuard . NotNull ( request , nameof ( request ) ) ;
45
47
ArgumentGuard . NotNull ( resourceChangeTracker , nameof ( resourceChangeTracker ) ) ;
48
+ ArgumentGuard . NotNull ( versionTracker , nameof ( versionTracker ) ) ;
46
49
ArgumentGuard . NotNull ( resourceDefinitionAccessor , nameof ( resourceDefinitionAccessor ) ) ;
47
50
48
51
_repositoryAccessor = repositoryAccessor ;
@@ -51,6 +54,7 @@ public JsonApiResourceService(IResourceRepositoryAccessor repositoryAccessor, IQ
51
54
_options = options ;
52
55
_request = request ;
53
56
_resourceChangeTracker = resourceChangeTracker ;
57
+ _versionTracker = versionTracker ;
54
58
_resourceDefinitionAccessor = resourceDefinitionAccessor ;
55
59
_traceWriter = new TraceLogWriter < JsonApiResourceService < TResource , TId > > ( loggerFactory ) ;
56
60
}
@@ -226,7 +230,8 @@ private async Task RetrieveResourceCountForNonPrimaryEndpointAsync(TId id, HasMa
226
230
throw ;
227
231
}
228
232
229
- TResource resourceFromDatabase = await GetPrimaryResourceByIdAsync ( resourceForDatabase . Id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
233
+ TResource resourceFromDatabase =
234
+ await GetPrimaryResourceAfterWriteAsync ( resourceForDatabase . Id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
230
235
231
236
_resourceChangeTracker . SetFinallyStoredAttributeValues ( resourceFromDatabase ) ;
232
237
@@ -477,7 +482,7 @@ private async Task<TResource> GetForHasManyUpdateAsync(HasManyAttribute hasManyR
477
482
throw ;
478
483
}
479
484
480
- TResource afterResourceFromDatabase = await GetPrimaryResourceByIdAsync ( id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
485
+ TResource afterResourceFromDatabase = await GetPrimaryResourceAfterWriteAsync ( id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
481
486
482
487
_resourceChangeTracker . SetFinallyStoredAttributeValues ( afterResourceFromDatabase ) ;
483
488
@@ -522,6 +527,11 @@ public virtual async Task SetRelationshipAsync(TId leftId, string relationshipNa
522
527
AssertIsNotResourceVersionMismatch ( exception ) ;
523
528
throw ;
524
529
}
530
+
531
+ if ( _versionTracker . RequiresVersionTracking ( ) )
532
+ {
533
+ await GetPrimaryResourceAfterWriteAsync ( leftId , TopFieldSelection . OnlyIdAttribute , cancellationToken ) ;
534
+ }
525
535
}
526
536
527
537
/// <inheritdoc />
@@ -614,6 +624,24 @@ protected async Task<TResource> GetPrimaryResourceByIdAsync(TId id, TopFieldSele
614
624
return primaryResources . SingleOrDefault ( ) ;
615
625
}
616
626
627
+ private async Task < TResource > GetPrimaryResourceAfterWriteAsync ( TId id , TopFieldSelection fieldSelection , CancellationToken cancellationToken )
628
+ {
629
+ AssertPrimaryResourceTypeInJsonApiRequestIsNotNull ( _request . PrimaryResourceType ) ;
630
+
631
+ if ( _versionTracker . RequiresVersionTracking ( ) )
632
+ {
633
+ QueryLayer queryLayer = _queryLayerComposer . ComposeForGetVersionsAfterWrite ( id , _request . PrimaryResourceType , fieldSelection ) ;
634
+ IReadOnlyCollection < TResource > primaryResources = await _repositoryAccessor . GetAsync < TResource > ( queryLayer , cancellationToken ) ;
635
+ TResource ? primaryResource = primaryResources . SingleOrDefault ( ) ;
636
+ AssertPrimaryResourceExists ( primaryResource ) ;
637
+
638
+ _versionTracker . CaptureVersions ( _request . PrimaryResourceType , primaryResource ) ;
639
+ return primaryResource ;
640
+ }
641
+
642
+ return await GetPrimaryResourceByIdAsync ( id , fieldSelection , cancellationToken ) ;
643
+ }
644
+
617
645
protected async Task < TResource > GetPrimaryResourceForUpdateAsync ( TId id , CancellationToken cancellationToken )
618
646
{
619
647
AssertPrimaryResourceTypeInJsonApiRequestIsNotNull ( _request . PrimaryResourceType ) ;
0 commit comments