77using System . Threading ;
88using System . Threading . Tasks ;
99using JetBrains . Annotations ;
10+ using JsonApiDotNetCore . AtomicOperations ;
1011using JsonApiDotNetCore . Configuration ;
1112using JsonApiDotNetCore . Diagnostics ;
1213using JsonApiDotNetCore . Errors ;
@@ -35,11 +36,12 @@ public class JsonApiResourceService<TResource, TId> : IResourceService<TResource
3536 private readonly TraceLogWriter < JsonApiResourceService < TResource , TId > > _traceWriter ;
3637 private readonly IJsonApiRequest _request ;
3738 private readonly IResourceChangeTracker < TResource > _resourceChangeTracker ;
39+ private readonly IVersionTracker _versionTracker ;
3840 private readonly IResourceDefinitionAccessor _resourceDefinitionAccessor ;
3941
4042 public JsonApiResourceService ( IResourceRepositoryAccessor repositoryAccessor , IQueryLayerComposer queryLayerComposer ,
4143 IPaginationContext paginationContext , IJsonApiOptions options , ILoggerFactory loggerFactory , IJsonApiRequest request ,
42- IResourceChangeTracker < TResource > resourceChangeTracker , IResourceDefinitionAccessor resourceDefinitionAccessor )
44+ IResourceChangeTracker < TResource > resourceChangeTracker , IVersionTracker versionTracker , IResourceDefinitionAccessor resourceDefinitionAccessor )
4345 {
4446 ArgumentGuard . NotNull ( repositoryAccessor , nameof ( repositoryAccessor ) ) ;
4547 ArgumentGuard . NotNull ( queryLayerComposer , nameof ( queryLayerComposer ) ) ;
@@ -48,6 +50,7 @@ public JsonApiResourceService(IResourceRepositoryAccessor repositoryAccessor, IQ
4850 ArgumentGuard . NotNull ( loggerFactory , nameof ( loggerFactory ) ) ;
4951 ArgumentGuard . NotNull ( request , nameof ( request ) ) ;
5052 ArgumentGuard . NotNull ( resourceChangeTracker , nameof ( resourceChangeTracker ) ) ;
53+ ArgumentGuard . NotNull ( versionTracker , nameof ( versionTracker ) ) ;
5154 ArgumentGuard . NotNull ( resourceDefinitionAccessor , nameof ( resourceDefinitionAccessor ) ) ;
5255
5356 _repositoryAccessor = repositoryAccessor ;
@@ -56,6 +59,7 @@ public JsonApiResourceService(IResourceRepositoryAccessor repositoryAccessor, IQ
5659 _options = options ;
5760 _request = request ;
5861 _resourceChangeTracker = resourceChangeTracker ;
62+ _versionTracker = versionTracker ;
5963 _resourceDefinitionAccessor = resourceDefinitionAccessor ;
6064 _traceWriter = new TraceLogWriter < JsonApiResourceService < TResource , TId > > ( loggerFactory ) ;
6165 }
@@ -234,7 +238,8 @@ private async Task RetrieveResourceCountForNonPrimaryEndpointAsync(TId id, HasMa
234238 throw ;
235239 }
236240
237- TResource resourceFromDatabase = await GetPrimaryResourceByIdAsync ( resourceForDatabase . Id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
241+ TResource resourceFromDatabase =
242+ await GetPrimaryResourceAfterWriteAsync ( resourceForDatabase . Id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
238243
239244 _resourceChangeTracker . SetFinallyStoredAttributeValues ( resourceFromDatabase ) ;
240245
@@ -413,7 +418,7 @@ protected async Task AssertRightResourcesExistAsync(object? rightValue, Cancella
413418 throw ;
414419 }
415420
416- TResource afterResourceFromDatabase = await GetPrimaryResourceByIdAsync ( id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
421+ TResource afterResourceFromDatabase = await GetPrimaryResourceAfterWriteAsync ( id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
417422
418423 _resourceChangeTracker . SetFinallyStoredAttributeValues ( afterResourceFromDatabase ) ;
419424
@@ -451,6 +456,11 @@ public virtual async Task SetRelationshipAsync(TId leftId, string relationshipNa
451456 AssertIsNotResourceVersionMismatch ( exception ) ;
452457 throw ;
453458 }
459+
460+ if ( _versionTracker . RequiresVersionTracking ( ) )
461+ {
462+ await GetPrimaryResourceAfterWriteAsync ( leftId , TopFieldSelection . OnlyIdAttribute , cancellationToken ) ;
463+ }
454464 }
455465
456466 /// <inheritdoc />
@@ -527,6 +537,24 @@ protected async Task<TResource> GetPrimaryResourceByIdAsync(TId id, TopFieldSele
527537 return primaryResources . SingleOrDefault ( ) ;
528538 }
529539
540+ private async Task < TResource > GetPrimaryResourceAfterWriteAsync ( TId id , TopFieldSelection fieldSelection , CancellationToken cancellationToken )
541+ {
542+ AssertPrimaryResourceTypeInJsonApiRequestIsNotNull ( _request . PrimaryResourceType ) ;
543+
544+ if ( _versionTracker . RequiresVersionTracking ( ) )
545+ {
546+ QueryLayer queryLayer = _queryLayerComposer . ComposeForGetVersionsAfterWrite ( id , _request . PrimaryResourceType , fieldSelection ) ;
547+ IReadOnlyCollection < TResource > primaryResources = await _repositoryAccessor . GetAsync < TResource > ( queryLayer , cancellationToken ) ;
548+ TResource ? primaryResource = primaryResources . SingleOrDefault ( ) ;
549+ AssertPrimaryResourceExists ( primaryResource ) ;
550+
551+ _versionTracker . CaptureVersions ( _request . PrimaryResourceType , primaryResource ) ;
552+ return primaryResource ;
553+ }
554+
555+ return await GetPrimaryResourceByIdAsync ( id , fieldSelection , cancellationToken ) ;
556+ }
557+
530558 protected async Task < TResource > GetPrimaryResourceForUpdateAsync ( TId id , CancellationToken cancellationToken )
531559 {
532560 AssertPrimaryResourceTypeInJsonApiRequestIsNotNull ( _request . PrimaryResourceType ) ;
0 commit comments