Skip to content

Enhance Pagination Logic for Get All Submodels and Submodel Descriptors - #204

Closed
mm-kgi wants to merge 32 commits into
developfrom
pagination-tests
Closed

Enhance Pagination Logic for Get All Submodels and Submodel Descriptors#204
mm-kgi wants to merge 32 commits into
developfrom
pagination-tests

Conversation

@mm-kgi

@mm-kgi mm-kgi commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Overview

This PR enhances the pagination flow for the following endpoints:

  • GET /submodels
  • GET /submodel-descriptors

The current implementation retrieves all Shell metadata from the Plugin, generates all Submodels/Submodel Descriptors, and only then applies pagination. This can result in unnecessary metadata retrieval and Submodel generation for large datasets.

This change introduces an improved pagination flow that performs pagination earlier in the processing pipeline while preserving the existing logical ordering and ensuring that no Submodels are skipped or duplicated.

Endpoints Covered

The same pagination approach is applied consistently to:

  • GET /submodels
  • GET /submodel-descriptors

This ensures both endpoints follow the same cursor and ordering semantics.

Edge Cases

The implementation considers:

  • Cursor pointing to a Submodel in the middle of a Shell.
  • Shells containing different numbers of Submodels.
  • Partially processed Shells.
  • Multiple Shell Templates.
  • Cursor pointing to the last Submodel of a Shell.
  • Transition from one Shell to the next.
  • Ensuring no duplicate or skipped Submodels across pages.

Validation

The implementation should be validated against scenarios including:

  • Cursor within the first Shell.
  • Cursor at the last Submodel of a Shell.
  • Cursor across multiple Shells.
  • Multiple Shell Templates.
  • Different numbers of Submodels per Shell.
  • Small and large page sizes.
  • First page without a cursor.
  • Subsequent pages using the returned cursor.
  • Ensuring consecutive pages contain no duplicates or missing Submodels.

Summary

This PR improves pagination by moving pagination closer to the metadata retrieval stage while retaining Submodel-level pagination semantics.

The solution ensures that:

  • Plugin metadata retrieval is paginated.
  • submodelId and aasId cursor handling is supported.
  • Ordering is preserved.
  • Submodels are neither skipped nor duplicated.
  • Multiple Shell Templates are supported.
  • Both /submodels and /submodel-descriptors follow consistent pagination behavior.
  • Large datasets can be processed more efficiently.

mm-kgi and others added 24 commits July 23, 2026 12:53
…hell descriptors with template mapping support
…th user-context aware caching and automated error mapping
…ion support

- Updated SubmodelRepositoryService to implement pagination for submodel retrieval, including cursor handling.
- Introduced SubmodelPageCursor to manage state across paginated requests.
- Modified IPluginDataHandler and IPluginDataProvider interfaces to include pagination parameters.
- Adjusted PluginDataHandler and PluginDataProvider implementations to support new pagination logic.
- Enhanced unit tests for SubmodelRepositoryService to cover new pagination scenarios.
- Added new tests for SubmodelPageCursor to ensure correct encoding and decoding behavior.
- Updated existing tests in PluginDataHandler and PluginDataProvider to accommodate changes in method signatures.
…ion support

Updated SubmodelRepositoryService to implement pagination for submodel retrieval, including cursor handling.

Introduced SubmodelPageCursor to manage state across paginated requests.

Modified IPluginDataHandler and IPluginDataProvider interfaces to include pagination parameters.

Adjusted PluginDataHandler and PluginDataProvider implementations to support new pagination logic.

Enhanced unit tests for SubmodelRepositoryService to cover new pagination scenarios.

Added new tests for SubmodelPageCursor to ensure correct encoding and decoding behavior.

Updated existing tests in PluginDataHandler and PluginDataProvider to accommodate changes in method signatures.
Refactored `SubmodelDescriptorService` to introduce a two-field composite cursor pagination algorithm for efficient data retrieval. Updated `GetAllSubmodelDescriptorsAsync` to use the new pagination logic and include cursor metadata.

Added helper methods `CollectSubmodelDescriptorPageAsync`, `ProcessShellBatch`, and `GetSubmodelIdsForShell` to support the new pagination mechanism. Introduced `PaginationState` and `SubmodelDescriptorPageResult` to manage pagination state.

Updated test cases in `SubmodelDescriptorServiceTests` to validate the new pagination logic, including a new test method `GetAllSubmodelDescriptorsAsync_ResumesCorrectly_WithTwoFieldCompositeCursor`. Refactored `CreateShell` to support customizable test data.

Removed the obsolete `ExtractDistinctSubmodelIds` method and added necessary `using` directives for additional namespaces.
…ce with pagination and associated test data fixtures
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@mm-kgi mm-kgi changed the title Pagination tests Enhance Pagination Logic for Get All Submodels and Submodel Descriptors Aug 19, 2026
@mm-kgi
mm-kgi requested a balanced review from Copilot August 19, 2026 06:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Moves submodel pagination closer to shell metadata retrieval for repository and registry endpoints.

Changes:

  • Adds composite submodel/AAS cursors and shared pagination state.
  • Propagates pagination through plugin metadata APIs and parallelizes requests.
  • Updates configuration, tests, and expected responses.

Reviewed changes

Copilot reviewed 26 out of 26 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
SubmodelRepository/TestData/GetAllSubmodels_Expected.json Updates expected IDs and formatting.
SubmodelRepository/TestData/GetAllSubmodels_ByIdShort_Expected.json Updates filtered response IDs.
SubmodelRepository/TestData/GetAllSubmodels_By_SemanticId_Expected.json Updates semantic-filter response IDs.
SubmodelRegistry/TestData/GetAllSubmodelDescriptors_WithLimitOne_Expected.json Updates composite cursor.
SubmodelRegistry/TestData/GetAllSubmodelDescriptors_WithCursor_Expected.json Updates cursor-page expectations.
TemplateManagementConfig.cs Raises default concurrency limit.
PluginDataProvider.cs Adds paginated metadata requests and parallel data requests.
PluginDataHandler.cs Propagates metadata pagination.
CachedGetRequestClient.cs Adds framework imports.
SubmodelPaginationCursor.cs Defines composite cursor encoding.
appsettings.development.json Raises development concurrency limits.
SubmodelRepositoryService.cs Implements early submodel pagination.
SubmodelDescriptorService.cs Implements early descriptor pagination.
SubmodelPagination.cs Adds shared pagination state.
IPluginDataProvider.cs Extends provider pagination contract.
IPluginDataHandler.cs Extends handler pagination contract.
AssetIdSearchService.cs Adapts handler invocation.
AasRepositoryService.cs Adapts handler invocation.
PluginDataProviderTests.cs Updates provider tests.
PluginDataHandlerTests.cs Updates handler tests.
CachedGetRequestClientTests.cs Normalizes source encoding.
SubmodelRepositoryServiceTests.cs Adds pagination-boundary tests.
SubmodelDescriptorServiceTests.cs Adds composite-cursor tests.
AssetIdSearchServiceTests.cs Updates pagination arguments.
AasRepositoryServiceTests.cs Updates handler expectations.
SubmodelDescriptorControllerTests.cs Updates repository mocks.
Suppressed comments (1)

source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/Shared/SubmodelPagination.cs:34

  • This no longer preserves the previous global Distinct() behavior: a submodel referenced by multiple shells is appended once per shell, so /submodels and /submodel-descriptors can return duplicates within or across pages. The prior regression test for shared submodel IDs was removed rather than adapted. Track IDs already emitted across the shell stream (with cursor state that remains valid across pages) before adding them.
        for (var i = startIndex; i < submodelIds.Count; i++)
        {
            CollectedIds.Add(submodelIds[i]);
            LastCollectedSubmodelId = submodelIds[i];

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown

Test & Coverage Report

Test Results Summary

Metric Count
✅ Passed 1689
❌ Failed 0
⏭️ Skipped 0

View Detailed Test Results


Code Coverage

Unit Tests Coverage

Package Line Rate Branch Rate Complexity Health
AAS.TwinEngine.DataEngine 92% 78% 2402
Summary 92% (3816 / 4154) 78% (1580 / 2037) 2402

Minimum allowed line rate is 80%

Module Tests Coverage

Package Line Rate Branch Rate Complexity Health
AAS.TwinEngine.DataEngine 62% 42% 2402
Summary 62% (2584 / 4154) 42% (863 / 2037) 2402

@mm-kgi mm-kgi closed this Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants