-
Notifications
You must be signed in to change notification settings - Fork 191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove unlimited collections from the repository API #496
Conversation
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Conflicts: hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignScheduler.java hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/RolloutScheduler.java hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java
Conflicts: hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTagRepository.java hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetTagRepository.java hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/JpaTestRepositoryManagement.java
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Conflicts: hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java Signed-off-by: SirWayne <dennis.melzer@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Conflicts: hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetRepository.java
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Conflicts: hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java
@@ -110,9 +120,14 @@ | |||
public static final String TARGET_FILTER_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/targetfilters"; | |||
|
|||
/** | |||
* The deprecated tag URL mapping rest resource. | |||
*/ | |||
public static final String DEPRECATED_DISTRIBUTIONSET_REQUEST_MAPPING = "/{distributionsetTagId}/distributionsets"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add @Deprecated
static Sort sanitizeTagSortParam(final String sortParam) { | ||
if (sortParam == null) { | ||
// default | ||
return new Sort(Direction.ASC, TargetFields.NAME.getFieldName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use TageFields.Name
instead of Target
|
||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties; | ||
|
||
public class StaticQuotaManagement implements QuotaManagement { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Add javadoc
- I would rename the class to
PropertiesQuotaManagement
, because you use properties for the quota
*/ | ||
public static void verifyRolloutGroupParameter(final int amountGroup) { | ||
public static void verifyRolloutGroupParameter(final int amountGroup, final int maxGroups) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion it's better to make a real bean and inject the QuotaManagement
here. Because now every developer can set another maxGroups
constraint for every call.
if (!tag.isPresent()) { | ||
return Collections.emptyList(); | ||
public Page<Target> findTargetsByTag(final Pageable pageable, final Long tagId) { | ||
if (!targetTagRepository.exists(tagId)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
create a private method to avoid duplicate code
Conflicts: hawkbit-dmf-parent/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
@sirwayne I like your ideas. All implemented. |
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Conflicts: hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
@@ -316,31 +316,38 @@ private void waitUntilRolloutIsReady(final Long id) { | |||
|
|||
private void createDistributionSets(final Scenario scenario) { | |||
LOGGER.info("Creating {} distribution sets", scenario.getDistributionSets()); | |||
final int pages = (scenario.getDistributionSets() / PAGE_SIZE) >= 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The page calculation is broken when you slightly exceed the page size. For example: 506 or 501 distribution sets will result in a page size of 1 so in the end this code creates only 500 entities and not the expected amount.
Same happens to the other entities e.g. targets so I won't comment it there as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid it is still broken. Use BigDecimal
instead if int or float for the calculation.
Example:
new BigDecimal(1002).divide(new BigDecimal(500), BigDecimal.ROUND_UP)
=> 3
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
.withRel("assignedTargets")); | ||
response.add(linkTo(methodOn(MgmtTargetTagRestApi.class).getAssignedTargets(targetTag.getId(), | ||
Integer.parseInt(MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET), | ||
Integer.parseInt(MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT), null, null)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an int value already available: Use MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE
instead of parsing the string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. I did not know that we have this value constant. I fixed this on all the mappers and created one for the offset as well.
methodOn(MgmtDistributionSetTagRestApi.class).getAssignedDistributionSets(distributionSetTag.getId())) | ||
response.add(linkTo(methodOn(MgmtDistributionSetTagRestApi.class).getAssignedDistributionSets( | ||
distributionSetTag.getId(), Integer.parseInt(MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET), | ||
Integer.parseInt(MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT), null, null)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
// OK | ||
} | ||
|
||
assertThatExceptionOfType(EntityAlreadyExistsException.class) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool 👍
|
||
public class JpaTestRepositoryManagement implements TestRepositoryManagement { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(JpaTestRepositoryManagement.class); | ||
private static final Pageable pageReq = new PageRequest(0, 400, new Sort(Direction.ASC, "id")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use CAPITAL LETTERS for variable pageReq
=> it is a constant
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copied from abstract integration test :) I will fix this in both classes.
*/ | ||
public List<DistributionSet> createDistributionSetsWithoutModules(final int number) { | ||
|
||
final List<DistributionSet> sets = new ArrayList<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set size of list => new ArrayList<>(number)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That does not help much. Lists.newArrayListWithExpectedSize(number) is the right one. But you are generally right of course.
try { | ||
createTagLine(builder, tag); | ||
} catch (final Exception e) { | ||
e.printStackTrace(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not throwing an exception here? It's obviously wrong JSON. It might be easier to find when you stop processing the tags here instead of waiting for the test to fail due to missing tags later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the code is copied from the other builders but I actually don't know why the exception is catched. I will fix this in the entire class.
Conflicts: hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTable.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/DefineGroupsLayout.java
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
Remove unlimited collections from the repository API (eclipse-hawkbit#496)
…#496) * Started to get rid of unlimited collections Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Align API usage. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * fix compile issues. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix tests. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Remove comments Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Performance optimizations. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Remove dead code. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Allign method names Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Wait until the action update event is processed Conflicts: hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java Signed-off-by: SirWayne <dennis.melzer@bosch-si.com> * Started new tag APIs Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Quotas into central interface. Tag tests added. Event names fixed. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Simplified consumer run for every tenant. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * remove unused fields. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Alligned beans. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Deprecated client methods for old resources. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix new foreach method. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix transaction for foreach. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Extended DS creating to handle larger volumes. Fix on Readme. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fixed simulator bug and cleaned up tests. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix in sorting. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Remove configuration processor. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix wrong usage of sanitize. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Missing brackets. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix README API compatability. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix misinterpretation of pessimistic locking exceptions. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix stability sentence. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Code cleanup. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fixed page calculation Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
hawkBit in many areas of the repository returns unpaged and unlimited collections. This has a risk as the system will be asked to query huge collections of data in certain scenarios. Query 500k entities in one query for sure will have negative impact on the overall system. I can't even say what will explode first (persistence, Java Heap, APIs...).
Examples on the entity APIs itself are:
Examples on repository APIs:
Well, the risk is different depending on the use case. While active actions on a target should in most cases be a two digit number max it is not actually guaranteed. All targets assigned to a tag however might easily go in the 6 digit direction.
I fixed most scenarios by means of providing or using repository APIs with limits. There are some left. Here, however I believe we should introduce configurable quotas (e.g. how many software modules can be in a distribution set). Until then the risk stays in the system.
However, unfortunately on the public APIs we are propagating unpaged access as well (targets or DS assigned to a tag):
On the way I fixed a few typos in events and provided a proper API for the quotas we already have in the system. Should be quite easy to extend those in the future.
Note: this is another task of #197
Reviewers: @schabdo @sirwayne