Skip to content

Commit 5f84d22

Browse files
committed
feat: refactor pagination logic and introduce SubmodelPaginationState for improved data handling
1 parent 5383bea commit 5f84d22

3 files changed

Lines changed: 66 additions & 90 deletions

File tree

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using AAS.TwinEngine.DataEngine.DomainModel.SubmodelRepository;
2+
3+
namespace AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Shared;
4+
5+
internal sealed record SubmodelPageResult(List<string> SubmodelIds, string? NextCursor);
6+
7+
internal sealed class SubmodelPaginationState(SubmodelPaginationCursor? cursor, int capacity = 0)
8+
{
9+
public List<string> CollectedIds { get; } = capacity > 0 ? new(capacity) : [];
10+
public string? TrackingAasId { get; set; } = cursor?.AasId;
11+
public string? LastCollectedSubmodelId { get; set; }
12+
public string? ResumeAfterSubmodelId { get; set; } = cursor?.SubmodelId;
13+
14+
public bool CollectSubmodelIds(IList<string> submodelIds, string shellId, int pageSize)
15+
{
16+
if (submodelIds.Count == 0)
17+
{
18+
TrackingAasId = shellId;
19+
ResumeAfterSubmodelId = null;
20+
return false;
21+
}
22+
23+
var startIndex = 0;
24+
25+
if (ResumeAfterSubmodelId is not null)
26+
{
27+
startIndex = submodelIds.IndexOf(ResumeAfterSubmodelId) + 1;
28+
ResumeAfterSubmodelId = null;
29+
}
30+
31+
for (var i = startIndex; i < submodelIds.Count; i++)
32+
{
33+
CollectedIds.Add(submodelIds[i]);
34+
LastCollectedSubmodelId = submodelIds[i];
35+
36+
if (CollectedIds.Count >= pageSize)
37+
{
38+
if (submodelIds[^1] == LastCollectedSubmodelId)
39+
{
40+
TrackingAasId = shellId;
41+
}
42+
43+
return true;
44+
}
45+
}
46+
47+
TrackingAasId = shellId;
48+
return false;
49+
}
50+
51+
public string? BuildNextCursor(int pageSize) =>
52+
CollectedIds.Count >= pageSize ? SubmodelPaginationCursor.Encode(LastCollectedSubmodelId, TrackingAasId) : null;
53+
}

source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/SubmodelRegistry/SubmodelDescriptorService.cs

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using AAS.TwinEngine.DataEngine.ApplicationLogic.Extensions;
44
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.AasEnvironment.Providers;
55
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.AasRepository;
6+
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Shared;
67
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.SubmodelRegistry.Providers;
78
using AAS.TwinEngine.DataEngine.DomainModel.Shared;
89
using AAS.TwinEngine.DataEngine.DomainModel.SubmodelRegistry;
@@ -136,10 +137,10 @@ private static void SetHref(EndpointData endpoint, string href)
136137
endpoint.ProtocolInformation.Href = href;
137138
}
138139

139-
private async Task<SubmodelDescriptorPageResult> CollectSubmodelDescriptorPageAsync(int pageSize, string? encodedCursor, CancellationToken cancellationToken)
140+
private async Task<SubmodelPageResult> CollectSubmodelDescriptorPageAsync(int pageSize, string? encodedCursor, CancellationToken cancellationToken)
140141
{
141142
var incomingCursor = SubmodelPaginationCursor.Decode(encodedCursor);
142-
var state = new PaginationState(incomingCursor);
143+
var state = new SubmodelPaginationState(incomingCursor);
143144
var pluginCursor = state.TrackingAasId;
144145

145146
while (state.CollectedIds.Count < pageSize)
@@ -168,49 +169,19 @@ private async Task<SubmodelDescriptorPageResult> CollectSubmodelDescriptorPageAs
168169
pluginCursor = state.TrackingAasId;
169170
}
170171

171-
var nextCursor = state.CollectedIds.Count >= pageSize ? SubmodelPaginationCursor.Encode(state.LastCollectedSubmodelId, state.TrackingAasId) : null;
172-
173-
return new SubmodelDescriptorPageResult(state.CollectedIds, nextCursor);
172+
return new SubmodelPageResult(state.CollectedIds, state.BuildNextCursor(pageSize));
174173
}
175174

176-
private static bool ProcessShellBatch(List<AasCore.Aas3_1.IAssetAdministrationShell> shellList, int pageSize, PaginationState state)
175+
private static bool ProcessShellBatch(List<AasCore.Aas3_1.IAssetAdministrationShell> shellList, int pageSize, SubmodelPaginationState state)
177176
{
178177
foreach (var shell in shellList)
179178
{
180179
var submodelIds = GetSubmodelIdsForShell(shell);
181180

182-
if (submodelIds.Count == 0)
183-
{
184-
state.TrackingAasId = shell.Id;
185-
state.ResumeAfterSubmodelId = null;
186-
continue;
187-
}
188-
189-
var startIndex = 0;
190-
191-
if (state.ResumeAfterSubmodelId is not null)
181+
if (state.CollectSubmodelIds(submodelIds, shell.Id!, pageSize))
192182
{
193-
startIndex = submodelIds.IndexOf(state.ResumeAfterSubmodelId) + 1;
194-
state.ResumeAfterSubmodelId = null;
183+
return true;
195184
}
196-
197-
for (var i = startIndex; i < submodelIds.Count; i++)
198-
{
199-
state.CollectedIds.Add(submodelIds[i]);
200-
state.LastCollectedSubmodelId = submodelIds[i];
201-
202-
if (state.CollectedIds.Count >= pageSize)
203-
{
204-
if (submodelIds[^1] == state.LastCollectedSubmodelId)
205-
{
206-
state.TrackingAasId = shell.Id;
207-
}
208-
209-
return true;
210-
}
211-
}
212-
213-
state.TrackingAasId = shell.Id;
214185
}
215186

216187
return false;
@@ -226,15 +197,5 @@ private static List<string> GetSubmodelIdsForShell(AasCore.Aas3_1.IAssetAdminist
226197
.ToList() ?? [];
227198
}
228199

229-
private sealed record SubmodelDescriptorPageResult(List<string> SubmodelIds, string? NextCursor);
230-
231-
private sealed class PaginationState(SubmodelPaginationCursor? cursor)
232-
{
233-
public List<string> CollectedIds { get; } = [];
234-
public string? TrackingAasId { get; set; } = cursor?.AasId;
235-
public string? LastCollectedSubmodelId { get; set; }
236-
public string? ResumeAfterSubmodelId { get; set; } = cursor?.SubmodelId;
237-
}
238-
239200
private string GenerateHref(string encodedId) => $"{_baseUrl}{ApiPaths.Submodels}/{encodedId}";
240201
}

source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/SubmodelRepository/SubmodelRepositoryService.cs

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using AAS.TwinEngine.DataEngine.ApplicationLogic.Extensions;
44
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.AasRepository;
55
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Plugin;
6+
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Shared;
67
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Shared.Providers;
78
using AAS.TwinEngine.DataEngine.DomainModel.AasRegistry;
89
using AAS.TwinEngine.DataEngine.DomainModel.AasRepository;
@@ -98,7 +99,7 @@ public async Task<SubmodelList> GetAllSubmodelsAsync(SubmodelSearchFilter? filte
9899
private async Task<SubmodelPageResult> CollectSubmodelPageAsync(ShellSearchFilter shellSearchFilter, int pageSize, string? encodedCursor, CancellationToken cancellationToken)
99100
{
100101
var incomingCursor = SubmodelPaginationCursor.Decode(encodedCursor);
101-
var state = new PaginationState(incomingCursor, pageSize);
102+
var state = new SubmodelPaginationState(incomingCursor, pageSize);
102103
var pluginCursor = state.TrackingAasId;
103104

104105
while (state.CollectedIds.Count < pageSize)
@@ -127,12 +128,10 @@ private async Task<SubmodelPageResult> CollectSubmodelPageAsync(ShellSearchFilte
127128
pluginCursor = state.TrackingAasId;
128129
}
129130

130-
var nextCursor = state.CollectedIds.Count >= pageSize ? SubmodelPaginationCursor.Encode(state.LastCollectedSubmodelId, state.TrackingAasId) : null;
131-
132-
return new SubmodelPageResult(state.CollectedIds, nextCursor);
131+
return new SubmodelPageResult(state.CollectedIds, state.BuildNextCursor(pageSize));
133132
}
134133

135-
private async Task<bool> ProcessShellBatchAsync(IReadOnlyList<ShellDescriptorMetaData> shellDescriptors, int pageSize, PaginationState state, CancellationToken cancellationToken)
134+
private async Task<bool> ProcessShellBatchAsync(IReadOnlyList<ShellDescriptorMetaData> shellDescriptors, int pageSize, SubmodelPaginationState state, CancellationToken cancellationToken)
136135
{
137136
var prefetchTasks = new Task<List<string>>[shellDescriptors.Count];
138137
using var semaphore = new SemaphoreSlim(_concurrentOperationsLimit, _concurrentOperationsLimit);
@@ -161,38 +160,10 @@ private async Task<bool> ProcessShellBatchAsync(IReadOnlyList<ShellDescriptorMet
161160

162161
var submodelIds = allSubmodelIds[idx];
163162

164-
if (submodelIds.Count == 0)
163+
if (state.CollectSubmodelIds(submodelIds, shellId, pageSize))
165164
{
166-
state.TrackingAasId = shellId;
167-
state.ResumeAfterSubmodelId = null;
168-
continue;
165+
return true;
169166
}
170-
171-
var startIndex = 0;
172-
173-
if (state.ResumeAfterSubmodelId is not null)
174-
{
175-
startIndex = submodelIds.IndexOf(state.ResumeAfterSubmodelId) + 1;
176-
state.ResumeAfterSubmodelId = null;
177-
}
178-
179-
for (var i = startIndex; i < submodelIds.Count; i++)
180-
{
181-
state.CollectedIds.Add(submodelIds[i]);
182-
state.LastCollectedSubmodelId = submodelIds[i];
183-
184-
if (state.CollectedIds.Count >= pageSize)
185-
{
186-
if (submodelIds[^1] == state.LastCollectedSubmodelId)
187-
{
188-
state.TrackingAasId = shellId;
189-
}
190-
191-
return true;
192-
}
193-
}
194-
195-
state.TrackingAasId = shellId;
196167
}
197168

198169
return false;
@@ -226,15 +197,6 @@ private async Task<List<string>> GetSubmodelIdsForShellAsync(string shellId, Can
226197
}
227198
}
228199

229-
private sealed record SubmodelPageResult(List<string> SubmodelIds, string? NextCursor);
230-
231-
private sealed class PaginationState(SubmodelPaginationCursor? cursor, int capacity)
232-
{
233-
public List<string> CollectedIds { get; } = new(capacity);
234-
public string? TrackingAasId { get; set; } = cursor?.AasId;
235-
public string? LastCollectedSubmodelId { get; set; }
236-
public string? ResumeAfterSubmodelId { get; set; } = cursor?.SubmodelId;
237-
}
238200

239201
private async Task<List<ISubmodel>> BuildSubmodelsAsync(List<string> submodelIds, string? filteredTemplateId, SubmodelQueryOptions? queryOptions, CancellationToken cancellationToken)
240202
{

0 commit comments

Comments
 (0)