Skip to content

Comments

Compare-DbaAgReplicaSync - Add new command to report AG replica sync differences#10048

Merged
potatoqualitee merged 3 commits intodevelopmentfrom
claude/issue-10047-20251216-2122
Dec 20, 2025
Merged

Compare-DbaAgReplicaSync - Add new command to report AG replica sync differences#10048
potatoqualitee merged 3 commits intodevelopmentfrom
claude/issue-10047-20251216-2122

Conversation

@potatoqualitee
Copy link
Member

Closes #10047

This new command reports synchronization differences between AG replicas without making any changes, addressing the need for monitoring and manual review before fixing issues.

Changes

  • Created Compare-DbaAgReplicaSync following the established Compare-DbaAgReplica* naming pattern
  • Compares Logins, Agent Jobs, Credentials, Linked Servers, Operators, Alerts, Proxies, and Custom Errors
  • Returns structured diff data without making changes
  • Registered in both dbatools.psd1 and dbatools.psm1
  • Includes parameter validation tests

Generated with Claude Code

…differences

This new command reports synchronization differences between AG replicas without
making any changes, addressing the need for monitoring and manual review before
fixing issues. Follows the established Compare-DbaAgReplica* naming pattern.

(do Compare-DbaAgReplicaSync)

Co-authored-by: Chrissy LeMaire <potatoqualitee@users.noreply.github.com>
$differences = New-Object System.Collections.ArrayList

foreach ($replicaInstance in $replicaInstances) {
$login = $loginsByReplica[$replicaInstance] | Where-Object Name -eq $loginName
Copy link
Contributor

Choose a reason for hiding this comment

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

That's not enough, right? Logins can differ in many more ways than just a login being completely missing.

Copy link
Contributor

Choose a reason for hiding this comment

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

We could call Compare-DbaAgReplicaLogin directly, but I think that has the same fault!

@potatoqualitee
Copy link
Member Author

@claude compare the types of properties that copy-dbalogin copies over. i recall that being pretty complete. then expand that to to whatever smo is offering nowadays and ensure that you check per version. then consider if we can reuse Compare-DbaAgReplicaLogin

@claude
Copy link

claude bot commented Dec 20, 2025

Claude finished @potatoqualitee's task in 2m 39s —— View job


Enhanced login comparison complete

Tasks

  • Read current Compare-DbaAgReplicaSync implementation
  • Read Copy-DbaLogin to understand property handling
  • Read Compare-DbaAgReplicaLogin for potential reuse
  • Check New-DbaLogin and Update-SqlPermission for copied properties
  • Analyze what needs to be compared
  • Implement comprehensive login comparison
  • Commit and push changes

Summary

Enhanced Compare-DbaAgReplicaSync to perform comprehensive login comparison beyond just checking if logins exist by name. The comparison now checks the key properties that Copy-DbaLogin handles:

Login Properties Compared:

  • IsDisabled - Whether the login is disabled
  • DenyWindowsLogin - Whether Windows login is denied
  • DefaultDatabase - Default database for the login
  • Language - Default language setting
  • PasswordExpirationEnabled - Password expiration policy (SQL logins only)
  • PasswordPolicyEnforced - Password complexity policy (SQL logins only)

Server Roles:

  • Compares server role memberships (sysadmin, securityadmin, etc.)
  • Version-aware: Only checked on SQL Server 2005+ (VersionMajor >= 9)

Output Changes:

  • "Missing" status when login doesn't exist on a replica
  • "Different" status when login exists but properties differ (NEW)
  • PropertyDifferences field showing exactly what differs (NEW)
    • Example: "IsDisabled: True vs False; Missing ServerRoles: sysadmin"

This addresses the review feedback that logins can differ in many more ways than just being completely missing. The implementation follows the same patterns and property checks used by Copy-DbaLogin and its helper function Update-SqlPermission.

Note on Scope

I focused on the most critical properties that Copy-DbaLogin handles. Database-level permissions and mappings could be added in the future, but they would significantly increase complexity and execution time since they require per-database enumeration. The current implementation covers the server-level properties that are most commonly different across replicas.

--- | Branch with changes

…es and server roles

(do Compare-DbaAgReplicaSync)

Co-authored-by: Chrissy LeMaire <potatoqualitee@users.noreply.github.com>
$diff
}
foreach ($diff in $differences) {
$diff
Copy link
Member Author

Choose a reason for hiding this comment

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

@claude why are you collecting this? just [pscustomobject].... | where status -eq missing. this just makes the command look slow.

Copy link

@claude claude bot Dec 20, 2025

Choose a reason for hiding this comment

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

Claude finished @potatoqualitee's task in 2m 51s —— View job


Performance optimization complete

Tasks

  • Read current implementation to identify unnecessary collections
  • Refactor to use direct pipeline filtering
  • Commit and push changes

Changes Made

Removed unnecessary ArrayList collections and filtering logic throughout the file. The inefficient pattern was:

  1. Create $differences = New-Object System.Collections.ArrayList
  2. Add objects to it with .Add()
  3. Check if ($differences.Count -gt 0)
  4. Filter with Where-Object Status -eq "Missing"
  5. Loop through to output each item

Now the code directly outputs PSCustomObject instances when they're created, eliminating the collection overhead and making the command appear faster to users.

Sections optimized:

  • Logins comparison
  • Agent Jobs comparison
  • Credentials comparison
  • Linked Servers comparison
  • Agent Operators comparison
  • Agent Alerts comparison
  • Agent Proxies comparison
  • Custom Errors comparison

Result: Reduced 151 lines, improved readability, and eliminated unnecessary memory allocations. Users can still filter the output themselves using | Where-Object Status -eq "Missing" if needed.


| Branch with changes

…better performance

(do Compare-DbaAgReplicaSync)

Co-authored-by: Chrissy LeMaire <potatoqualitee@users.noreply.github.com>
@potatoqualitee
Copy link
Member Author

yeah i think if we wanted to add permissions in the future it'd be a new command or new paramter. when i think of comparing, i dont think of the detailed permissions.

@potatoqualitee
Copy link
Member Author

@claude why did you choose not to update and wrap the existing command?

@claude
Copy link

claude bot commented Dec 20, 2025

Claude finished @potatoqualitee's task in 54s —— View job


Design decision analysis

Tasks

  • Read existing Compare-DbaAgReplicaLogin command
  • Read current Compare-DbaAgReplicaSync login comparison implementation
  • Analyze whether wrapping existing command would work
  • Provide explanation

Why I didn't wrap Compare-DbaAgReplicaLogin

After reviewing both commands, here's why I implemented the login comparison directly instead of calling Compare-DbaAgReplicaLogin:

Different output structures:

  • Compare-DbaAgReplicaLogin returns one row per replica showing Status: "Missing" or Status: "Present" for each login, with optional ModifyDate comparison
  • Compare-DbaAgReplicaSync needs a unified output format across all object types: ObjectType, ObjectName, Status, and PropertyDifferences
  • Wrapping would require reshaping the output, which defeats the purpose of reusing the command

Different comparison philosophy:

  • Compare-DbaAgReplicaLogin with -IncludeModifiedDate only checks if modify_date differs (lines 176-185, 192-200)
  • Compare-DbaAgReplicaSync compares actual property values (IsDisabled, DefaultDatabase, Language, ServerRoles, etc.) to show what's different (lines 227-259)
  • The existing command doesn't expose the granular property differences needed for the "sync check" use case

Connection management differences:

  • Compare-DbaAgReplicaLogin connects to each replica separately per login comparison
  • Compare-DbaAgReplicaSync connects once per replica and caches all data upfront for efficiency when comparing multiple object types

Scope differences:

  • Compare-DbaAgReplicaLogin is focused on login-specific scenarios with options like -ExcludeSystemLogin
  • Compare-DbaAgReplicaSync is focused on comprehensive sync checks across many object types

Could we refactor the existing command?

We could refactor Compare-DbaAgReplicaLogin to:

  1. Add a switch like -IncludePropertyDifferences to check actual properties
  2. Add a -Format parameter to support different output structures
  3. Return property difference details

However, this would significantly complicate Compare-DbaAgReplicaLogin and make it serve two different use cases with different output formats. The current approach keeps each command focused on its specific purpose:

  • Compare-DbaAgReplicaLogin: Detailed login comparison with flexible filtering and date tracking
  • Compare-DbaAgReplicaSync: Comprehensive server-level object sync checking with unified output

Bottom line

The commands have different purposes and output requirements. Implementing the comparison logic directly in Compare-DbaAgReplicaSync keeps the code cleaner and more maintainable than trying to force Compare-DbaAgReplicaLogin to serve both use cases.


View job | Branch with changes

@potatoqualitee
Copy link
Member Author

@andreasjordan we should talk about standardizing the compare-dbaag commands and agree on the best. nbd for breaking chagnes since the new set is brand new.

@potatoqualitee potatoqualitee merged commit a4dc0a1 into development Dec 20, 2025
16 of 17 checks passed
@potatoqualitee potatoqualitee deleted the claude/issue-10047-20251216-2122 branch December 20, 2025 12:38
@ReeceGoding
Copy link
Contributor

@potatoqualitee Does the Agent Job stuff also have the same "we're only checking for totally missing things" problem?

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.

Sync-DbaAvailabilityGroup: just report the differences, not fix them

2 participants