コード例 #1
0
        private async Task <IReadOnlyCollection <ObjectVersionRecord> > GetObjectVersions(long id, string initialVersionId, bool fetchElements)
        {
            await _distributedLockManager.EnsureLockNotExistsAsync(id);

            var query = _context.Objects
                        .AsNoTracking()
                        .Where(x => x.Id == id)
                        .OrderByDescending(x => x.VersionIndex)
                        .AsQueryable();

            if (fetchElements)
            {
                query = query.Include(x => x.ElementLinks)
                        .ThenInclude(x => x.Element);
            }

            var allVersions = await query.ToListAsync();

            if (allVersions.Count == 0)
            {
                throw new ObjectNotFoundException($"Object '{id}' not found.");
            }

            var versions = allVersions.TakeWhile(x => x.VersionId != initialVersionId);
            var records  = new List <ObjectVersionRecord>(allVersions.Count);

            foreach (var version in versions)
            {
                var elements   = fetchElements ? version.ElementLinks.Select(x => x.Element) : Array.Empty <ObjectElement>();
                var descriptor = GetObjectDescriptorFromEntity(version, elements);
                records.Add(new ObjectVersionRecord(
                                version.Id,
                                version.VersionId,
                                version.VersionIndex,
                                version.TemplateId,
                                version.TemplateVersionId,
                                DateTime.SpecifyKind(version.LastModified, DateTimeKind.Utc),
                                new AuthorInfo(version.Author, version.AuthorLogin, version.AuthorName),
                                descriptor.Properties,
                                descriptor.Elements
                                .Select(x => new ObjectVersionRecord.ElementRecord(x.TemplateCode, x.Value))
                                .ToList(),
                                version.ModifiedElements));
            }

            return(records);
        }
コード例 #2
0
        private async Task <IReadOnlyCollection <ObjectVersionRecord> > GetObjectVersions(long id, string initialVersionId, bool fetchElements)
        {
            var objectDescriptors = new List <ObjectDescriptor>();

            async Task <(bool IsTruncated, int NextVersionIndex, string NextVersionIdMarker)> ListVersions(int nextVersionIndex, string nextVersionIdMarker)
            {
                await _distributedLockManager.EnsureLockNotExistsAsync(id);

                var response = await _s3Client.ListVersionsAsync(
                    new ListVersionsRequest
                {
                    BucketName      = _bucketName,
                    Prefix          = id.AsS3ObjectKey(Tokens.ObjectPostfix),
                    VersionIdMarker = nextVersionIdMarker
                });

                var nonDeletedVersions = response.Versions.FindAll(x => !x.IsDeleteMarker);

                nextVersionIndex += nonDeletedVersions.Count;

                var initialVersionIdReached = false;
                var versionInfos            = nonDeletedVersions
                                              .Aggregate(
                    new List <(string VersionId, DateTime LastModified)>(),
                    (list, next) =>
                {
                    initialVersionIdReached = initialVersionIdReached ||
                                              (!string.IsNullOrEmpty(initialVersionId) &&
                                               initialVersionId.Equals(next.VersionId, StringComparison.OrdinalIgnoreCase));

                    if (!initialVersionIdReached)
                    {
                        list.Add((next.VersionId, next.LastModified));
                    }

                    return(list);
                });

                var descriptors = new ObjectDescriptor[versionInfos.Count];
                var partitioner = Partitioner.Create(versionInfos);
                var tasks       = partitioner.GetOrderablePartitions(_degreeOfParallelism)
                                  .Select(async partition =>
                {
                    while (partition.MoveNext())
                    {
                        var index       = partition.Current.Key;
                        var versionInfo = partition.Current.Value;

                        descriptors[index] = await GetObjectDescriptor(id, versionInfo.VersionId, CancellationToken.None, fetchElements);
                    }
                });
                await Task.WhenAll(tasks);

                objectDescriptors.AddRange(descriptors);

                return(!initialVersionIdReached && response.IsTruncated, nextVersionIndex, response.NextVersionIdMarker);
            }

            var result = await ListVersions(0, null);

            if (objectDescriptors.Count == 0)
            {
                if (!await IsObjectExists(id))
                {
                    throw new ObjectNotFoundException($"Object '{id}' not found.");
                }

                return(Array.Empty <ObjectVersionRecord>());
            }

            while (result.IsTruncated)
            {
                result = await ListVersions(result.NextVersionIndex, result.NextVersionIdMarker);
            }

            var maxVersionIndex = result.NextVersionIndex;
            var records         = new ObjectVersionRecord[objectDescriptors.Count];

            for (var index = 0; index < objectDescriptors.Count; ++index)
            {
                var descriptor = objectDescriptors[index];
                records[index] = new ObjectVersionRecord(
                    descriptor.Id,
                    descriptor.VersionId,
                    --maxVersionIndex,
                    descriptor.LastModified,
                    new AuthorInfo(descriptor.Metadata.Author, descriptor.Metadata.AuthorLogin, descriptor.Metadata.AuthorName),
                    descriptor.Properties,
                    descriptor.Elements.Select(x => new ObjectVersionRecord.ElementRecord(x.TemplateCode, x.Value)).ToList(),
                    descriptor.Metadata.ModifiedElements);
            }

            return(records);
        }