Skip to content

Commit 23f064d

Browse files
andreasjordanclaude
andcommitted
Get-DbaXESession - Close the cloned connection behind the XEStore
Every call cloned the SqlConnection for its XEStore and never closed the clone: one sleeping session per call, held until the process exits. Because the whole Extended Events family funnels through this command - Start-DbaXESession even re-queries through it after every start - the leak multiplied across Start, Stop, Remove, ConvertTo, Watch and the Export commands. The first -CheckSleepingConnections full run flagged Start-DbaXESession at +15, ConvertTo at +7 and Remove at +6. The store connection is now disconnected after the sessions are enumerated and emitted. The emitted objects keep their Store note property working: SFC transparently reconnects from the pool when a downstream command uses the store again, which the lab probe confirmed for piped Start and Stop and a test now pins. Measured on SQL03\SQL2019: three Get calls used to add three sessions (regression test red on the unfixed command: expected 4, got 7), now add none. Runner measurements of the family files: Start-DbaXESession 15 -> 7, Remove-DbaXESession 6 -> 2, ConvertTo-DbaXESession 7 -> 3. The residue in Start comes from a different, smaller mechanism (the reopened store of a piped object stays checked out once per pipeline) and is left for a follow-up. (do *XESession*) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 0473789 commit 23f064d

2 files changed

Lines changed: 48 additions & 0 deletions

File tree

public/Get-DbaXESession.ps1

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@ function Get-DbaXESession {
142142
Add-Member -Force -InputObject $x -MemberType NoteProperty -Name Store -Value $XEStore
143143
Select-DefaultView -InputObject $x -Property ComputerName, InstanceName, SqlInstance, Name, Status, StartTime, AutoStart, State, Targets, TargetFile, Events, MaxMemory, MaxEventSize
144144
}
145+
146+
# The store rides a cloned connection that nothing ever closed, so every call parked one
147+
# more session on the instance until the process ended. Close it here; when a consumer of
148+
# the emitted objects uses the store again, SFC transparently reconnects from the pool.
149+
$XEStore.SfcConnection.Disconnect()
145150
}
146151
}
147152
}

tests/Get-DbaXESession.Tests.ps1

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,47 @@ Describe $CommandName -Tag IntegrationTests {
3333
$results.Name -eq "system_health" | Should -Be $true
3434
}
3535
}
36+
37+
Context "When querying sessions repeatedly" {
38+
BeforeAll {
39+
$PSDefaultParameterValues["*-Dba*:EnableException"] = $true
40+
41+
# The command used to leave the cloned connection of its XEStore open, one new sleeping
42+
# session per call. Count sessions through a server object opened once, because a per-call
43+
# counting command would open connections of its own.
44+
$countServer = Connect-DbaInstance -SqlInstance $TestConfig.InstanceSingle -NonPooledConnection
45+
$countQuery = @"
46+
select count(*)
47+
from sys.dm_exec_sessions
48+
where program_name like 'dbatools%'
49+
and status = 'sleeping'
50+
and session_id <> @@spid
51+
"@
52+
53+
# One warm-up call so the shared pooled connection exists before the baseline is taken.
54+
$null = Get-DbaXESession -SqlInstance $TestConfig.InstanceSingle -Session system_health
55+
$sleepingBefore = $countServer.ConnectionContext.ExecuteScalar($countQuery)
56+
57+
foreach ($i in 1..3) {
58+
$null = Get-DbaXESession -SqlInstance $TestConfig.InstanceSingle -Session system_health
59+
}
60+
$sleepingAfter = $countServer.ConnectionContext.ExecuteScalar($countQuery)
61+
62+
$PSDefaultParameterValues.Remove("*-Dba*:EnableException")
63+
}
64+
65+
AfterAll {
66+
$countServer.ConnectionContext.Disconnect()
67+
}
68+
69+
It "Leaves no sleeping session behind" {
70+
$sleepingAfter | Should -Be $sleepingBefore
71+
}
72+
73+
It "Emits objects whose store still works after the connection is returned" {
74+
$result = Get-DbaXESession -SqlInstance $TestConfig.InstanceSingle -Session system_health
75+
# The store must transparently reconnect for downstream commands like Start or Stop.
76+
$result.Store.Sessions.Name | Should -Contain "system_health"
77+
}
78+
}
3679
}

0 commit comments

Comments
 (0)