-
Notifications
You must be signed in to change notification settings - Fork 8
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
add installation truncation #192
Conversation
…ile_component to load complete status
…into user/johnfeng/add_assessment_truncation
… map for performance optimization
…or performance issue
Codecov Report
@@ Coverage Diff @@
## master #192 +/- ##
==========================================
+ Coverage 90.39% 91.11% +0.72%
==========================================
Files 90 90
Lines 14810 15941 +1131
==========================================
+ Hits 13387 14525 +1138
+ Misses 1423 1416 -7
Flags with carried forward coverage won't be shown. Click here to find out more.
|
a3e0028
to
6d6f8fa
Compare
…n map in 2.7 are randomize
fe0f93f
to
f34c848
Compare
@feng-j678 @rane-rajasi |
…nditional checker, and unit test
…into user/johnfeng/add_installation_truncation
checker condition code added. |
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.
Did a very short pass, so this is not my final review for the current iteration.
Please add a brief description on what this PR is trying to achieve with some details. For eg: how is it trying to truncate, when does it truncate, why is the skip by seconds logic added, etc.,
@@ -101,6 +101,7 @@ def __init__(self, argv): | |||
patch_installer.mark_installation_completed() | |||
overall_patch_installation_operation_successful = True | |||
self.update_patch_substatus_if_pending(patch_operation_requested, overall_patch_installation_operation_successful, patch_assessment_successful, configure_patching_successful, status_handler, composite_logger) | |||
status_handler.log_truncated_packages() | |||
|
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.
Note: to be raised and discussed between @kjohn-msft, @feng-j678 and me
self.env_layer.file_system.write_with_retry_using_temp_file(self.complete_status_file_path, '[{0}]'.format(status_file_payload_json_dumps), mode='w+') | ||
|
||
if Constants.StatusTruncationConfig.TURN_ON_TRUNCATION: | ||
status_file_payload_json_dumps = self.__check_file_byte_size_for_truncation(status_file_payload_json_dumps) |
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 function name __check_file_byte_size_for_truncation() indicates it only checks the size, however this function not only checks size but also applies truncation if needed. Please rename the function to convey it's actions
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.
method name updated -. __check_status_file_size_perform_truncation_if_needed(). at this point the method name is getting longer like paragraph. looking for suggestion for shorter name. done
curr_timestamp = datetime.datetime.now() | ||
return (curr_timestamp - track_truncation_timestamp).total_seconds() >= Constants.StatusTruncationConfig.SKIP_TRUNCATION_LOGIC_IN_X_SEC | ||
|
||
def __set_force_truncation_true(self, status): |
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.
Rename to: __set_force_truncation_true_for_terminal_status()
This function is being called for all status values (Success, Error, Transitioning...), so it's important for the name to reflect the functionality
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.
done
# Write agent status file | ||
self.env_layer.file_system.write_with_retry_using_temp_file(self.status_file_path, '[{0}]'.format(json.dumps(complete_status_payload)), mode='w+') | ||
if Constants.StatusTruncationConfig.TURN_ON_TRUNCATION: | ||
truncated_status_file_json_dumps = self.__validate_status_file_for_truncation(status_file_payload_json_dumps) |
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.
__validate_status_file_for_truncation(): Is this just validating or is this performing truncation also? The name indicates it will simply validate
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.
done, see above comment
track_truncation_timestamp = datetime.datetime.now() | ||
|
||
curr_timestamp = datetime.datetime.now() | ||
return (curr_timestamp - track_truncation_timestamp).total_seconds() >= Constants.StatusTruncationConfig.SKIP_TRUNCATION_LOGIC_IN_X_SEC |
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 is this skip truncation by secs added?
Also, the function name again does not clearly state what is happening within
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 description, done.
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.
Not a blocker for the first validation round: But the description, within function or in PR, does not explain "why" this skip truncation logic is added.
Also, based on my assumption, of this logic, truncation should be skipped if the remaining time (i.e. current - track_tuncation) <= Constants.StatusTruncationConfig.SKIP_TRUNCATION_LOGIC_IN_X_SEC. Is this correct?
So the last statement should be:
return (curr_timestamp - track_truncation_timestamp).total_seconds() > Constants.StatusTruncationConfig.SKIP_TRUNCATION_LOGIC_IN_X_SEC
PR description can be made further descriptive: PR description should briefly state the issue we see today and our solution. See the previous comment on "Please add a brief description on what this PR is trying to achieve with some details. For eg: how is it trying to truncate, when does it truncate, why is the skip by seconds logic added, etc.," |
if status_file_size_in_bytes > self.__internal_file_capacity: # perform truncation complete_status_file byte size > 126kb | ||
is_delay_truncation_by_x_sec = self.__check_truncation_time_passed_by_x_sec(self.__track_truncation_timestamp) | ||
|
||
if is_delay_truncation_by_x_sec or self.__force_truncation_on: |
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.
Should this condition read as:
If there is no delay required for truncation OR force truncation is on?
If so, the check should be:
if not is_delay_truncation_by_x_sec or self.__force_truncation_on:
This is why a description conveying the intent/ desired functionality of the code is important, either in function description or PR description
Also, the function and variable names need to be modified to reflect the intent, but leaving that for the next review
…rm_truncation_if_needed
5882b0d
to
2521e8a
Compare
# Map['classification', count] | ||
for package in packages_removed_from_assessment: | ||
classifications = package['classifications'][0] | ||
assessment_tombstone_map[classifications] = assessment_tombstone_map.get(classifications, 0) + 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.
assessment_tombstone_map.get()
Wouldn't this throw an error on empty list?
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.
done. if that's the case, this code is unreachable:
line 1000
if len(packages_removed_from_assessment) > 0:
self.__assessment_packages_removed = packages_removed_from_assessment
assessment_tombstone_records = self.__create_assessment_tombstone_list(self.__assessment_packages_removed)
packages_retained_in_assessment.extend(assessment_tombstone_records)
assessment_tombstone_map[classifications] = assessment_tombstone_map.get(classifications, 0) + 1 | ||
|
||
# Add assessment tombstone record per classifications except unclassified | ||
for tombstone_classification, tombstone_package_count in assessment_tombstone_map.items(): |
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.
Where are things being written into assessment_tombstone_map?
Line 1188 initializes it to an empty value, line 1194 does a .get() on an empty list. Don't see any values being set in it
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.
done. if that's the case, this code is unreachable:
line 1000
if len(packages_removed_from_assessment) > 0:
self.__assessment_packages_removed = packages_removed_from_assessment
assessment_tombstone_records = self.__create_assessment_tombstone_list(self.__assessment_packages_removed)
packages_retained_in_assessment.extend(assessment_tombstone_records)
# Add assessment tombstone record per classifications except unclassified | ||
for tombstone_classification, tombstone_package_count in assessment_tombstone_map.items(): | ||
if not tombstone_classification == Constants.PackageClassification.UNCLASSIFIED: | ||
tombstone_record_list.append(self.__create_assessment_tombstone(tombstone_package_count, tombstone_classification)) |
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.
Are we adding 1 tombstone record for every classification type? I don't remember what was discussed on this previously but I have doubts on the usefulness of this.
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.
done. yes, this was a one of the requirements.
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.
Left some comments inline, but my overall review is:
- Need a description of the current functionality and why each change is being introduced (i.e. what is the desired outcome)
- The changes are there but due to the enormity of this PR and the number of things being added, it is difficult to ensure that all intended changes are implemented and everything works together as desired.
- we should consider splitting this PR into parts for easier review.
The parts can be: (1 PR for each)
- Basic truncation of assessment and installation patches (Simply removing additional patches with No tombstone or error details). This will also include re-composing the status file post truncation. TBD if this can be further split
- Adding tombstone records on truncation
- Adding error details on truncation
- Adding delay on truncation
- Any other changes not covered so far
108eb27
to
2d411e1
Compare
What is in this PR:
[X] Compressed assessment and installation patches
[X] Add tombstone record for compressed assessment per classifications.
[X] Add tombstone record for compressed installation.
[X] Add error details for compressed assessment.
[X] Add error details for compressed installation.
[X] set status as warning when compression applied.
[X] Clean up multi-line formatting.
[X] Test assessment and installation compression.
[X] Unit test coverage...
[x] delay truncation logic - add condition to check current time vs truncation timestamp if 60 secs have passed. when timestamp is below 60 secs, truncation logic will not apply during application process unless the terminal state has reached (success or error)