22using System . Net ;
33using System . Runtime . CompilerServices ;
44using JetBrains . Annotations ;
5+ using JsonApiDotNetCore . AtomicOperations ;
56using JsonApiDotNetCore . Configuration ;
67using JsonApiDotNetCore . Diagnostics ;
78using JsonApiDotNetCore . Errors ;
@@ -30,11 +31,12 @@ public class JsonApiResourceService<TResource, TId> : IResourceService<TResource
3031 private readonly TraceLogWriter < JsonApiResourceService < TResource , TId > > _traceWriter ;
3132 private readonly IJsonApiRequest _request ;
3233 private readonly IResourceChangeTracker < TResource > _resourceChangeTracker ;
34+ private readonly IVersionTracker _versionTracker ;
3335 private readonly IResourceDefinitionAccessor _resourceDefinitionAccessor ;
3436
3537 public JsonApiResourceService ( IResourceRepositoryAccessor repositoryAccessor , IQueryLayerComposer queryLayerComposer , IPaginationContext paginationContext ,
3638 IJsonApiOptions options , ILoggerFactory loggerFactory , IJsonApiRequest request , IResourceChangeTracker < TResource > resourceChangeTracker ,
37- IResourceDefinitionAccessor resourceDefinitionAccessor )
39+ IVersionTracker versionTracker , IResourceDefinitionAccessor resourceDefinitionAccessor )
3840 {
3941 ArgumentGuard . NotNull ( repositoryAccessor ) ;
4042 ArgumentGuard . NotNull ( queryLayerComposer ) ;
@@ -43,6 +45,7 @@ public JsonApiResourceService(IResourceRepositoryAccessor repositoryAccessor, IQ
4345 ArgumentGuard . NotNull ( loggerFactory ) ;
4446 ArgumentGuard . NotNull ( request ) ;
4547 ArgumentGuard . NotNull ( resourceChangeTracker ) ;
48+ ArgumentGuard . NotNull ( versionTracker ) ;
4649 ArgumentGuard . NotNull ( resourceDefinitionAccessor ) ;
4750
4851 _repositoryAccessor = repositoryAccessor ;
@@ -51,6 +54,7 @@ public JsonApiResourceService(IResourceRepositoryAccessor repositoryAccessor, IQ
5154 _options = options ;
5255 _request = request ;
5356 _resourceChangeTracker = resourceChangeTracker ;
57+ _versionTracker = versionTracker ;
5458 _resourceDefinitionAccessor = resourceDefinitionAccessor ;
5559 _traceWriter = new TraceLogWriter < JsonApiResourceService < TResource , TId > > ( loggerFactory ) ;
5660 }
@@ -226,7 +230,8 @@ private async Task RetrieveResourceCountForNonPrimaryEndpointAsync(TId id, HasMa
226230 throw ;
227231 }
228232
229- TResource resourceFromDatabase = await GetPrimaryResourceByIdAsync ( resourceForDatabase . Id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
233+ TResource resourceFromDatabase =
234+ await GetPrimaryResourceAfterWriteAsync ( resourceForDatabase . Id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
230235
231236 _resourceChangeTracker . SetFinallyStoredAttributeValues ( resourceFromDatabase ) ;
232237
@@ -477,7 +482,7 @@ private async Task<TResource> GetForHasManyUpdateAsync(HasManyAttribute hasManyR
477482 throw ;
478483 }
479484
480- TResource afterResourceFromDatabase = await GetPrimaryResourceByIdAsync ( id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
485+ TResource afterResourceFromDatabase = await GetPrimaryResourceAfterWriteAsync ( id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
481486
482487 _resourceChangeTracker . SetFinallyStoredAttributeValues ( afterResourceFromDatabase ) ;
483488
@@ -522,6 +527,11 @@ public virtual async Task SetRelationshipAsync(TId leftId, string relationshipNa
522527 AssertIsNotResourceVersionMismatch ( exception ) ;
523528 throw ;
524529 }
530+
531+ if ( _versionTracker . RequiresVersionTracking ( ) )
532+ {
533+ await GetPrimaryResourceAfterWriteAsync ( leftId , TopFieldSelection . OnlyIdAttribute , cancellationToken ) ;
534+ }
525535 }
526536
527537 /// <inheritdoc />
@@ -614,6 +624,24 @@ protected async Task<TResource> GetPrimaryResourceByIdAsync(TId id, TopFieldSele
614624 return primaryResources . SingleOrDefault ( ) ;
615625 }
616626
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+
617645 protected async Task < TResource > GetPrimaryResourceForUpdateAsync ( TId id , CancellationToken cancellationToken )
618646 {
619647 AssertPrimaryResourceTypeInJsonApiRequestIsNotNull ( _request . PrimaryResourceType ) ;
0 commit comments