Skip to content

Introduce soft deleted list option for soft deletable entities#3093

Open
strailov wants to merge 5 commits into
eclipse-hawkbit:masterfrom
boschglobal:feature/soft_deletion_mode_listing_option
Open

Introduce soft deleted list option for soft deletable entities#3093
strailov wants to merge 5 commits into
eclipse-hawkbit:masterfrom
boschglobal:feature/soft_deletion_mode_listing_option

Conversation

@strailov
Copy link
Copy Markdown
Contributor

@strailov strailov commented May 19, 2026

Add soft_deleted_mode query parameter to listing REST endpoints

Summary

Introduces a soft_deleted_mode filter parameter to all soft-deletable entity listing endpoints, allowing API consumers to query soft-deleted entities that were previously hidden from listing results.

Motivation

Soft-deleted entities (Distribution Sets, Software Modules, their Types, and Rollouts) were previously only accessible by direct ID lookup. There was no way to list or search them via the REST API, making it difficult for UI and integrations to display or manage deleted resources.

Changes

New API contract:

  • SoftDeletedFilter enum (soft_deleted, not_soft_deleted, all) with safe fromValue() parsing
  • SoftDeletableRepositoryManagement interface extending RepositoryManagement with findAll(SoftDeletedFilter, Pageable) and findByRsql(String, SoftDeletedFilter, Pageable)
  • count(SoftDeletedFilter) added to RepositoryManagement with fallback for non-soft-deletable entities
  • sort option extended to support DELETED field for each soft-deletable entity

Affected REST endpoints:

  • GET /rest/v1/distributionsets
  • GET /rest/v1/distributionsettypes
  • GET /rest/v1/softwaremodules
  • GET /rest/v1/softwaremoduletypes
  • GET /rest/v1/rollouts (compact mode only; full mode intentionally excluded)

Mutation guards:

  • update, lock, unlock, invalidate, assignTag, unassignTag now reject operations on soft-deleted entities with DeletedException

Implementations:

  • JpaDistributionSetManagement — refactored findByRsql to support deleted filter while preserving legacy complete field handling
  • JpaSoftwareModuleManagement, JpaSoftwareModuleTypeManagement, JpaDistributionSetTypeManagement — added findAll/findByRsql with soft-delete filtering and update guards
  • JpaRolloutManagement — added findAll/findByRsql with SoftDeletedFilter
  • Chosen that approach instead of introducing this logic in AbstractJpaRepositoryManagement due to that some entities are not soft-deletable by definition. So the current approach may have some duplications with findAll or findByRsql implementations but seems with more clear architecture approach and distinguish those entities.
  • Soft-delete mutation guards - Soft-deleted entities must reject mutation operations (like Rollout already does). Users can stumble into "Entity exists" errors due to unique key constraint violations on soft-deleted entities they cannot see. Here I rejected the approach with intermediate class due to AbstractJpaRepositoryManagementAbstractJpaRepositoryWithMetadataManagement - Would need two variants (with/without metadata) or force unrelated coupling. Not worth the complexity. Decided to override the updates for each entity which is easy to review, no risk for other entities and straightforward .
  • Reject all for bulk updates - to be still considered ...

strailov added 5 commits May 19, 2026 17:54
Signed-off-by: strailov <Stanislav.Trailov@bosch.io>
Signed-off-by: strailov <Stanislav.Trailov@bosch.io>
Signed-off-by: strailov <Stanislav.Trailov@bosch.io>
Signed-off-by: strailov <Stanislav.Trailov@bosch.io>
Signed-off-by: strailov <Stanislav.Trailov@bosch.io>
* The request parameter for specifying the soft deletion listing of entities. The value of this parameter
* can be soft_deleted, not_soft_deleted or all
*/
public static final String REQUEST_PARAMETER_LIST_SOFT_DELETED_MODE = "soft_deleted_mode";
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.

The naming of the 3 modes maybe should be reconsidered. What about:
SOFT_DELETED: INCLUDE (all), ONLY (only soft deleted), EXCLUDE (only not deleted)?

"'soft_deleted' - returns only soft-deleted rollouts; " +
"'all' - returns both active and soft-deleted rollouts.",
allowableValues = { "not_soft_deleted", "soft_deleted", "all" })
String softDeletedMode);
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.

why string? It should be enumeration, e.g. SoftDeltedMode:
INCLUDE, EXCLUDE, ALL/ANY, or (with current naming)
SOFT_DELETED, NOT_SOFT_DELETED, ALL/ANY

LogUtility.logDeprecated("Usage of MgmtDistributionSetResource.getActions with 'complete': 'complete' distribution set search field is limited and may be removed.");
}
final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeDistributionSetSortParam(sortParam));
final SoftDeletedFilter softDeletedFilter = SoftDeletedFilter.fromValue(softDeletedModeParam)
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.

Maybe SoftDeltedMode? "Filter" implies something like RSQL in scope of hawkbit

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I am open for discussion for the names ... I left it softDeletedMode on the Rest API side, but on the implementation side it is still a filter though which goes directly to the db ... So that's why currently I left it that way.

METADATA("metadata"),
VALID("valid");
VALID("valid"),
DELETED("deleted");
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.

do we want to add deleted field? if we add deleted field we could query with RSQL deleted=true and soft deleted mode "not deleted"? which will take prefernce? or will let user to be responsible for collisions?

Copy link
Copy Markdown
Contributor Author

@strailov strailov May 26, 2026

Choose a reason for hiding this comment

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

I guess this is the price if we want sort option by deleted if ALL is applied ... Personally I would not include that and not include sort at all.

return filter(JpaManagementHelper.findAllWithCountBySpec(jpaRepository, specList, pageable), completed);
}
}
return findByRsqlAndDeleted(rsql, SoftDeletedFilter.NOT_SOFT_DELETED, pageable);
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.

just idea - what about if we don't add rest soft deleted mode, but just DELETED filter fields?
And here just check - if RSQL contains (parse the filter) deleted=** - we dont add in specification deleted=false.
if don't - like now - we add deleted = false?
This could keep the changes and the api expansion really small as keeping all new features.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think it will be almost the same change - it won't be that small - we still have to filter the entities through the database (which currently is the biggest change), so we will skip maybe 50% of the Controller layer which i don't think is that big now... Also the solution won't be that clean, it feels like a stitch. Idk ...

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.

2 participants