Private/Timing/New-TimingSpanNode.ps1
|
<# .NOTES Module-internal. Dot-sourced by the psm1 before the other Private\Timing\ helpers and the Public\Timing\ verbs. Not exported. #> # --------------------------------------------------------------------------- # New-TimingSpanNode # The single constructor for a span node. Every node in the framework - the # root (New-TimingSpanTree), a lazily-minted child (Resolve-TimingSpanChild- # Node), and a node rebuilt from a JSON export (ConvertFrom-TimingSpanImport- # Node) - is created here, so the node shape and its field defaults have # exactly one authority. Adding or renaming a field is a one-file change # that cannot silently miss a call site. # # Node shape: # { Order; Name; Status; ElapsedMs; Source; Children } # Defaults centralise the two rules the call sites otherwise each repeated: # * Source is normalised so an empty/absent tag is stored as $null. # * Children defaults to a fresh List[object] when the caller has none; # the import path passes its already-rebuilt child list through. # --------------------------------------------------------------------------- function New-TimingSpanNode { [CmdletBinding()] param( # First-contact declaration order; assigned by the caller that owns # the context's monotonic counter (or 0 for the root, or the value # read back from an export). [Parameter(Mandatory)] [int] $Order, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $Name, # Lifecycle state. Defaults to NotStarted - the state of a node the # moment it is minted but before any span runs against it. [string] $Status = 'NotStarted', # Untyped so the un-run/null distinction survives: $null until timed, # an int64 total once a span accumulates into it. $ElapsedMs = $null, # Optional provenance tag; empty is normalised to $null below. [string] $Source, # Existing child list to adopt (the import path). Untyped so the # List[object] passes through without being enumerated on binding; # $null means "give me a fresh empty list". $Children = $null ) # Default the child list with a plain statement, NOT an inline `if` # expression: a statement-as-expression pipes its output, and an empty # List enumerates to nothing, which would silently store $null here. if ($null -eq $Children) { $Children = [System.Collections.Generic.List[object]]::new() } [pscustomobject]@{ Order = $Order Name = $Name Status = $Status ElapsedMs = $ElapsedMs Source = if ([string]::IsNullOrEmpty($Source)) { $null } else { $Source } Children = $Children } } |