Skip to content

perf: cache ExtendedProperty parse in subcategory filter (#28)#53

Open
cocallaw wants to merge 5 commits into
v3.0.0from
perf/28-cache-extendedproperty-parse
Open

perf: cache ExtendedProperty parse in subcategory filter (#28)#53
cocallaw wants to merge 5 commits into
v3.0.0from
perf/28-cache-extendedproperty-parse

Conversation

@cocallaw

Copy link
Copy Markdown
Owner

Description

Eliminates redundant ConvertFrom-Json call by caching the parsed ExtendedProperty during the subcategory filter step.

Changes

  • Parse JSON once in the Where-Object filter and attach result as ExtendedPropertyObject via Add-Member
  • Downstream code already checks for ExtendedPropertyObject before re-parsing, so this completes the optimization

Related Issue

Fixes #28

Parse ExtendedProperty JSON once during the Where-Object filter and
cache the result via Add-Member. The downstream code already checks
for ExtendedPropertyObject before re-parsing, so this eliminates
the redundant ConvertFrom-Json call per matching recommendation.

Fixes #28

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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

This PR optimizes the Az.Advisor path in Get-AzRetirementRecommendation by caching the parsed ExtendedProperty JSON during the subcategory filtering step, preventing redundant parsing later in the pipeline.

Changes:

  • Parse ExtendedProperty JSON once inside the subcategory Where-Object filter.
  • Attach the parsed object to each matching recommendation as ExtendedPropertyObject for downstream reuse.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Public/Get-AzRetirementRecommendation.ps1 Outdated
Comment thread Public/Get-AzRetirementRecommendation.ps1 Outdated
The subcategory filter now handles ExtendedProperty as string (JSON),
hashtable, or PSCustomObject gracefully. Parse failures are caught
silently and the item is filtered out rather than throwing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@cocallaw

Copy link
Copy Markdown
Owner Author

Addressed the type checking feedback:

  1. Type-safe filter — The subcategory filter now checks ExtendedProperty type: strings are parsed with ConvertFrom-Json (with try/catch), hashtables and PSCustomObjects are used directly. Parse failures silently filter out the item.

  2. Test coverage — The existing tests for Get-AzRetirementRecommendation exercise both the API path and the Az.Advisor path (which both use this filter). Adding a unit test for the filter scriptblock in isolation would require exposing internal implementation details. The current integration-level coverage validates that recommendations with valid ExtendedProperty are processed correctly.

All 59 tests pass.

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

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Public/Get-AzRetirementRecommendation.ps1 Outdated
Addresses review feedback on PR #53 by adding Pester tests that validate:
- JSON string ExtendedProperty is parsed and cached as ExtendedPropertyObject
- Hashtable ExtendedProperty is used directly and cached
- Non-matching subcategories are filtered out
- Invalid JSON is handled gracefully without throwing
- Null ExtendedProperty is filtered out

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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

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

Comment thread Public/Get-AzRetirementRecommendation.ps1 Outdated
Comment thread Tests/AzRetirementMonitor.Tests.ps1
Comment thread Tests/AzRetirementMonitor.Tests.ps1 Outdated
- Replace empty catch {} with explicit $extProps = $null assignment
  to satisfy PSScriptAnalyzer PSAvoidUsingEmptyCatchBlock rule
- Add function definition assertions to validate the production code
  contains Add-Member caching and type checks
- Remove unused $functionDef that was assigned but never referenced
- Update test catch blocks to match production code pattern

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

Comment on lines +159 to +173
# Common filter for ServiceUpgradeAndRetirement subcategory
$subcategoryFilter = {
# Parse extended properties to check subcategory
if ($_.ExtendedProperty) {
$extProps = $_.ExtendedProperty | ConvertFrom-Json
$extProps.recommendationSubCategory -eq 'ServiceUpgradeAndRetirement'
$extProps = $null
if ($_.ExtendedProperty -is [string]) {
try { $extProps = $_.ExtendedProperty | ConvertFrom-Json }
catch { $extProps = $null }
}
elseif ($_.ExtendedProperty -is [hashtable] -or $_.ExtendedProperty -is [pscustomobject]) {
$extProps = $_.ExtendedProperty
}
if ($extProps -and $extProps.recommendationSubCategory -eq 'ServiceUpgradeAndRetirement') {
$_ | Add-Member -NotePropertyName ExtendedPropertyObject -NotePropertyValue $extProps -Force
$true
} else { $false }
Comment thread Tests/AzRetirementMonitor.Tests.ps1 Outdated
Comment thread Tests/AzRetirementMonitor.Tests.ps1 Outdated
Comment thread Tests/AzRetirementMonitor.Tests.ps1 Outdated
Addresses review feedback:
- Extract shared Resolve-ExtendedProperty private helper used by both
  the subcategory filter and output construction (eliminates duplication)
- Tests now use InModuleScope to exercise the real helper function
  rather than duplicating filter logic inline
- Remove unused mock of Get-AzAdvisorRecommendation from tests
- Add function definition assertions scoped to the actual call sites

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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

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

Comment on lines +29 to +36
$extProps = $Recommendation.ExtendedProperty | ConvertFrom-Json
}
elseif ($Recommendation.ExtendedProperty -is [hashtable] -or $Recommendation.ExtendedProperty -is [pscustomobject]) {
$extProps = $Recommendation.ExtendedProperty
}

if ($extProps) {
$Recommendation | Add-Member -NotePropertyName ExtendedPropertyObject -NotePropertyValue $extProps -Force
Comment on lines +377 to +387
BeforeAll {
$functionDef = (Get-Command Get-AzRetirementRecommendation).Definition
}

It "Should use Resolve-ExtendedProperty helper in the subcategory filter" {
$functionDef | Should -Match 'subcategoryFilter\s*=\s*\{[^}]*Resolve-ExtendedProperty'
}

It "Should use Resolve-ExtendedProperty helper in the output construction" {
# Verify the helper is also used outside the filter (in the foreach loop)
$functionDef | Should -Match 'Resolve-ExtendedProperty -Recommendation \$rec'
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