Skip to content

Commit 7f91af5

Browse files
andreasjordanclaude
andcommitted
Add-DbaRegServer - Close the store connection its verification call reopens
Every call leaked one connection: after Create(), the command verifies the registration with Get-DbaRegServer -SqlInstance $reggroup.ParentServer. That server object rides the store connection Get-DbaRegServerGroup had already closed, so SMO silently reconnects it - and because Connect-DbaInstance then rightly reports it did not open this connection, nothing ever closes it again. One sleeping session per call, held until the process exits. Import-DbaRegServer inherits the leak because it registers through this command. This is what the first -CheckSleepingConnections full run flagged as Export-DbaRegServer +33: that test file runs Add-DbaRegServer three times per test, eleven tests, 33 leaked sessions. Measured in the lab: five calls grew the session count from 1 to 6; the isolated Export-DbaRegServer file left 25 sessions behind. The fix mirrors what Add-DbaRegServerGroup already does after its own verification call: Disconnect-RegServer after the Get, which walks up to the store and closes only a connection this module opened. Measured after the fix: five calls stay at 1 session, and the Export file's count drops from 25 to 1. The new regression test counts sleeping dbatools sessions through a server object opened once (a per-call counting command would open connections of its own), takes a warm-up call so the pooled connection exists before the baseline, and asserts three more calls add nothing. Verified red on the unfixed command (expected 3, got 6) and green on the fix (9 tests, 0 failed). (do Add-DbaRegServer, Export-DbaRegServer, Import-DbaRegServer) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 0473789 commit 7f91af5

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

public/Add-DbaRegServer.ps1

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ function Add-DbaRegServer {
246246
$newserver.Create()
247247

248248
Get-DbaRegServer -SqlInstance $reggroup.ParentServer -Name $Name -ServerName $ServerName | Where-Object Source -ne 'Azure Data Studio'
249+
# The verification call above reconnects the store connection that Get-DbaRegServerGroup
250+
# already closed, and nothing closes it again - one session per call stayed open. Close it
251+
# like Add-DbaRegServerGroup does; only a connection this module opened is ever closed.
252+
Disconnect-RegServer -Server $newserver
249253
} catch {
250254
Stop-Function -Message "Failed to add $ServerName on $target" -ErrorRecord $_ -Continue
251255
}
@@ -262,6 +266,10 @@ function Add-DbaRegServer {
262266
$newserver.Create()
263267

264268
Get-DbaRegServer -SqlInstance $reggroup.ParentServer -Name $Name -ServerName $ServerName | Where-Object Source -ne 'Azure Data Studio'
269+
# The verification call above reconnects the store connection that Get-DbaRegServerGroup
270+
# already closed, and nothing closes it again - one session per call stayed open. Close it
271+
# like Add-DbaRegServerGroup does; only a connection this module opened is ever closed.
272+
Disconnect-RegServer -Server $newserver
265273
} catch {
266274
Stop-Function -Message "Failed to add $ServerName on $target" -ErrorRecord $_ -Continue
267275
}

tests/Add-DbaRegServer.Tests.ps1

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,46 @@ Describe $CommandName -Tag IntegrationTests {
102102
$results2.SqlInstance | Should -Not -BeNullOrEmpty
103103
}
104104
}
105+
106+
Context "When adding registered servers repeatedly" {
107+
BeforeAll {
108+
$PSDefaultParameterValues["*-Dba*:EnableException"] = $true
109+
110+
# The command used to reconnect the store connection for its verification call and never
111+
# close it again, one new sleeping session per call. Count sessions through a server object
112+
# opened once, because a per-call counting command would open connections of its own.
113+
$countServer = Connect-DbaInstance -SqlInstance $TestConfig.InstanceSingle -NonPooledConnection
114+
$countQuery = @"
115+
select count(*)
116+
from sys.dm_exec_sessions
117+
where program_name like 'dbatools%'
118+
and status = 'sleeping'
119+
and session_id <> @@spid
120+
"@
121+
122+
# One warm-up call so the shared pooled connection exists before the baseline is taken.
123+
$null = Add-DbaRegServer -SqlInstance $TestConfig.InstanceSingle -ServerName "dbatoolsci-leak0" -Name "dbatoolsci-leak0"
124+
$sleepingBefore = $countServer.ConnectionContext.ExecuteScalar($countQuery)
125+
126+
foreach ($i in 1..3) {
127+
$null = Add-DbaRegServer -SqlInstance $TestConfig.InstanceSingle -ServerName "dbatoolsci-leak$i" -Name "dbatoolsci-leak$i"
128+
}
129+
$sleepingAfter = $countServer.ConnectionContext.ExecuteScalar($countQuery)
130+
131+
$PSDefaultParameterValues.Remove("*-Dba*:EnableException")
132+
}
133+
134+
AfterAll {
135+
$PSDefaultParameterValues["*-Dba*:EnableException"] = $true
136+
137+
Get-DbaRegServer -SqlInstance $TestConfig.InstanceSingle | Where-Object Name -Like "dbatoolsci-leak*" | Remove-DbaRegServer
138+
$countServer.ConnectionContext.Disconnect()
139+
140+
$PSDefaultParameterValues.Remove("*-Dba*:EnableException")
141+
}
142+
143+
It "Leaves no sleeping session behind" {
144+
$sleepingAfter | Should -Be $sleepingBefore
145+
}
146+
}
105147
}

0 commit comments

Comments
 (0)