7
7
using System . Threading ;
8
8
using System . Threading . Tasks ;
9
9
using JetBrains . Annotations ;
10
+ using JsonApiDotNetCore . AtomicOperations ;
10
11
using JsonApiDotNetCore . Configuration ;
11
12
using JsonApiDotNetCore . Diagnostics ;
12
13
using JsonApiDotNetCore . Errors ;
@@ -35,11 +36,12 @@ public class JsonApiResourceService<TResource, TId> : IResourceService<TResource
35
36
private readonly TraceLogWriter < JsonApiResourceService < TResource , TId > > _traceWriter ;
36
37
private readonly IJsonApiRequest _request ;
37
38
private readonly IResourceChangeTracker < TResource > _resourceChangeTracker ;
39
+ private readonly IVersionTracker _versionTracker ;
38
40
private readonly IResourceDefinitionAccessor _resourceDefinitionAccessor ;
39
41
40
42
public JsonApiResourceService ( IResourceRepositoryAccessor repositoryAccessor , IQueryLayerComposer queryLayerComposer ,
41
43
IPaginationContext paginationContext , IJsonApiOptions options , ILoggerFactory loggerFactory , IJsonApiRequest request ,
42
- IResourceChangeTracker < TResource > resourceChangeTracker , IResourceDefinitionAccessor resourceDefinitionAccessor )
44
+ IResourceChangeTracker < TResource > resourceChangeTracker , IVersionTracker versionTracker , IResourceDefinitionAccessor resourceDefinitionAccessor )
43
45
{
44
46
ArgumentGuard . NotNull ( repositoryAccessor , nameof ( repositoryAccessor ) ) ;
45
47
ArgumentGuard . NotNull ( queryLayerComposer , nameof ( queryLayerComposer ) ) ;
@@ -48,6 +50,7 @@ public JsonApiResourceService(IResourceRepositoryAccessor repositoryAccessor, IQ
48
50
ArgumentGuard . NotNull ( loggerFactory , nameof ( loggerFactory ) ) ;
49
51
ArgumentGuard . NotNull ( request , nameof ( request ) ) ;
50
52
ArgumentGuard . NotNull ( resourceChangeTracker , nameof ( resourceChangeTracker ) ) ;
53
+ ArgumentGuard . NotNull ( versionTracker , nameof ( versionTracker ) ) ;
51
54
ArgumentGuard . NotNull ( resourceDefinitionAccessor , nameof ( resourceDefinitionAccessor ) ) ;
52
55
53
56
_repositoryAccessor = repositoryAccessor ;
@@ -56,6 +59,7 @@ public JsonApiResourceService(IResourceRepositoryAccessor repositoryAccessor, IQ
56
59
_options = options ;
57
60
_request = request ;
58
61
_resourceChangeTracker = resourceChangeTracker ;
62
+ _versionTracker = versionTracker ;
59
63
_resourceDefinitionAccessor = resourceDefinitionAccessor ;
60
64
_traceWriter = new TraceLogWriter < JsonApiResourceService < TResource , TId > > ( loggerFactory ) ;
61
65
}
@@ -234,7 +238,8 @@ private async Task RetrieveResourceCountForNonPrimaryEndpointAsync(TId id, HasMa
234
238
throw ;
235
239
}
236
240
237
- TResource resourceFromDatabase = await GetPrimaryResourceByIdAsync ( resourceForDatabase . Id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
241
+ TResource resourceFromDatabase =
242
+ await GetPrimaryResourceAfterWriteAsync ( resourceForDatabase . Id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
238
243
239
244
_resourceChangeTracker . SetFinallyStoredAttributeValues ( resourceFromDatabase ) ;
240
245
@@ -413,7 +418,7 @@ protected async Task AssertRightResourcesExistAsync(object? rightValue, Cancella
413
418
throw ;
414
419
}
415
420
416
- TResource afterResourceFromDatabase = await GetPrimaryResourceByIdAsync ( id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
421
+ TResource afterResourceFromDatabase = await GetPrimaryResourceAfterWriteAsync ( id , TopFieldSelection . WithAllAttributes , cancellationToken ) ;
417
422
418
423
_resourceChangeTracker . SetFinallyStoredAttributeValues ( afterResourceFromDatabase ) ;
419
424
@@ -451,6 +456,11 @@ public virtual async Task SetRelationshipAsync(TId leftId, string relationshipNa
451
456
AssertIsNotResourceVersionMismatch ( exception ) ;
452
457
throw ;
453
458
}
459
+
460
+ if ( _versionTracker . RequiresVersionTracking ( ) )
461
+ {
462
+ await GetPrimaryResourceAfterWriteAsync ( leftId , TopFieldSelection . OnlyIdAttribute , cancellationToken ) ;
463
+ }
454
464
}
455
465
456
466
/// <inheritdoc />
@@ -527,6 +537,24 @@ protected async Task<TResource> GetPrimaryResourceByIdAsync(TId id, TopFieldSele
527
537
return primaryResources . SingleOrDefault ( ) ;
528
538
}
529
539
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
+
530
558
protected async Task < TResource > GetPrimaryResourceForUpdateAsync ( TId id , CancellationToken cancellationToken )
531
559
{
532
560
AssertPrimaryResourceTypeInJsonApiRequestIsNotNull ( _request . PrimaryResourceType ) ;
0 commit comments