modules/Session.psm1
using namespace System.Management.Automation using module '.\Enums.psm1' using module '.\FeedProcessor\AuditLog\Message.psm1' using module '.\Config.psm1' using module '.\SessionConfig.psm1' using module '.\AuditLog.psm1' using module '.\Downloader\DownloaderBase.psm1' using module '.\Downloader\DownloaderFactory.psm1' using module '.\FeedProcessor\ProcessorBase.psm1' using module '.\FeedProcessor\ProcessorFactory.psm1' Import-LocalizedData -BindingVariable LocalizedData -FileName Session.Resources.psd1 class Session{ #region Properties hidden [bool] $async [int] $sessionId [datetime] $createdAt [SessionConfig] $config [AuditLogFile] $auditLogFile [hashtable] $downloadJobs [int] $watcherId [bool] $convert [bool] $saveConverted #endregion #region Session static [Session[]] $activeSessions = @() static [int] $currentSessionId = 0 static [int] $nextSessionId = 1 hidden Session([OPERATOR] $operator, [ENVIRONMENT] $environment, [bool] $convert, [bool]$saveConverted){ $this.sessionId = [Session]::nextSessionId [Session]::activeSessions += $this [Session]::nextSessionId += 1 $this.Reset($operator, $environment, $convert, $saveConverted) } static [Session] getCurrent(){ foreach ($session in [Session]::activeSessions) { if ($session.sessionId -eq [Session]::currentSessionId) { return $session } } return $null } static [Session] getSession([int] $sessionId){ foreach ($session in [Session]::activeSessions) { if ($session.sessionId -eq $sessionId) { return $session } } return $null } static [Session] NewSession([OPERATOR] $operator, [ENVIRONMENT] $environment, [bool] $convert, [bool]$saveConverted){ $session = [Session]::new($operator, $environment, $convert, $saveConverted) return $session } [void] setAnalyzedScope([SOURCE[]] $sources, [long] $matchId, [string] $referentTime, [string] $timeSpan){ $this.createdAt = (Get-Date) $this.config.setAnalyzedScope($sources, $matchId, $referentTime, $timeSpan) } static [void] Recycle([int] $sessionId){ if ([Session]::activeSessions){ $remainingSessions = @() $lastId = 0 foreach ($session in [Session]::activeSessions) { if ($session.sessionId -ne $sessionId) { $remainingSessions += $session $lastId = $session.sessionId } else { $session.UnregisterFileWatcher() $session.UnregisterDownloadJobs() } } [Session]::activeSessions = $remainingSessions if ($sessionId -eq [Session]::currentSessionId) { [Session]::currentSessionId = $lastId } } } [void] Reset([OPERATOR] $operator, [ENVIRONMENT] $environment, [bool] $convert, [bool]$saveConverted){ $this.config = [SessionConfig]::new($operator, $environment) $this.convert = $convert $this.saveConverted = $saveConverted $this.downloadJobs = @{} $this.UnregisterFileWatcher() $this.UnregisterDownloadJobs() $this.auditLogFile = [AuditLogFile]::new($this.config, $this.convert, $this.saveConverted) } #endregion #region Session info static [PSCustomObject[]] AllSessionInfo(){ $retValue = @() foreach ($session in [Session]::activeSessions) { $retValue += $session.SessionInfo() } return $retValue } [PSCustomObject] SessionInfo(){ $currentIndicator = '' if ($this.auditLogFile.async) { $this.auditLogFile.ResumeJobs() } if ($this.sessionId -eq [Session]::currentSessionId) { $currentIndicator = '*' } $retValue = [PSCustomObject]@{ PSTypeName = 'DisplaySession'; Id = '{0}{1}' -f @($this.sessionId, $currentIndicator); CreatedAt = $this.createdAt; Endpoint = '{0} @ {1}' -f @($this.config.operator, $this.config.environment); MatchId = $this.config.matchId; From = $this.config.afterDateTime; To = $this.config.beforeDateTime; Download = $this.getJobStates($this.downloadJobs) Mount = $this.getJobStates($this.auditLogFile.jobs); Sources = @() } foreach ($sourceName in [Enum]::GetNames('SOURCE')) { $src = [Enum]::Parse('SOURCE', $sourceName) $size = '-' if ($this.auditLogFile.fileContent -and $this.auditLogFile.fileContent[$src]){ $size = $this.auditLogFile.fileContent[$src].Length $retValue.Sources += "{0}: {1:N0}" -f @($src, $size) } # elseif ($src -in $this.config.analyzedSources) { # $size = 0 # } } return $retValue } #endregion #region Jobs [bool] isAsync(){ return $this.async } [bool] canImport(){ if ($this.isAsync -and $this.downloadJobs.Count -gt 0 -and $this.auditLogFile.jobs.Count -gt 0) { return $false } else { return $true } } [bool] canRead([SOURCE] $source){ if ($this.isAsync -and ($this.downloadJobs[$source])) { return $false } else { if ($this.auditLogFile.async) { $this.auditLogFile.ResumeJobs() } if ($this.auditLogFile.jobs[$source]) { return $false } else { return $true } } } hidden [string] getJobStates([hashtable] $jobs){ $jobStates = @{} if ($jobs){ foreach ($job in (Get-Job | Where-Object { $jobs.ContainsValue($_.id) })){ if ($jobStates.Contains($job.State)){ $jobStates[$job.State] += 1 } else { $jobStates.Add($job.State, 1) } } } $retValue = '-' foreach ($item in $jobStates.Keys){ if ($retValue -eq '-'){ $retValue = ('{0}: {1}' -f @($item, $jobStates[$item])) } else { $retValue = $retValue + (', {0}: {1}' -f @($item, $jobStates[$item])) } } return $retValue } static [void] ResumeAllJobs(){ foreach ($session in [Session]::activeSessions) { if ($session.IsAsync()) { $session.ResumeJobs() $session.auditLogFile.ResumeJobs() } } } [void] ResumeJobs(){ foreach ($job in (Get-Job | Where-Object { $this.downloadJobs.ContainsValue($_.id) -and $_.State -eq [JobState]::Completed -and ([SOURCE]($_.name) -in $this.config.analyzedSources) })){ $this.auditLogFile.addJob([SOURCE]($job.name)) $this.downloadJobs.Remove([SOURCE]($job.name)) Stop-Job -id $job.id Remove-Job -id $job.id } } hidden [void] UnregisterDownloadJobs(){ foreach ($job in (Get-Job | Where-Object { $this.downloadJobs.ContainsValue($_.id) -and ([SOURCE]($_.name) -in $this.config.analyzedSources) })){ $this.auditLogFile.RemoveJob([SOURCE]($job.name)) $this.downloadJobs.Remove([SOURCE]($job.name)) Stop-Job -id $job.id Remove-Job -id $job.id } } hidden [int] RegisterFileWatcher([string] $file, [long] $matchId){ $filePath = (Resolve-Path (Split-Path $file -Parent)) $fileName = ('{0}-*.*' -f $matchId) $watcher = New-Object IO.FileSystemWatcher $filePath.Path, $fileName -Property @{ IncludeSubdirectories = $false EnableRaisingEvents = $true } $onChange = (Register-ObjectEvent $watcher -EventName "Changed" -SourceIdentifier $matchId -Action { Resume-SessionJobs }) return $onChange.id } hidden [void] UnregisterFileWatcher(){ if ($this.watcherId) { # try { # Unregister-Event -SubscriptionId $this.watcherId # } # catch { # } Stop-Job -id $this.watcherId Remove-Job -id $this.watcherId $this.watcherId = 0 } } #endregion #region Register actors [void] RegisterDownloader([bool] $AsJob){ if ($this.downloadJobs.Count -eq 0){ $this.async = $AsJob [DownloaderFactory]::Init($this.config) $downloader = [DownloaderFactory]::current if ($global:DEBUG) { Write-Host "No async downloaders..." -ForegroundColor Yellow } foreach ($src in $this.config.analyzedSources) { if ($this.async){ if ($global:DEBUG) { Write-Host "Download initiated ($src)" -ForegroundColor Yellow } $this.downloadJobs += $downloader.Download($src, $this.async) if ($global:DEBUG) { Write-Host "File watcher active ($($downloader.fileName))" -ForegroundColor Yellow } } else { $downloader.Download($src, $false) } } if ($this.async) { Write-Host $script:LocalizedData.BackgroundJobsActivatedMessage $this.watcherId = $this.RegisterFileWatcher($downloader.fileName, $this.config.matchId) } } else { Write-Host $script:LocalizedData.ActiveDownloadInProgressMessage } } [void] RegisterLogFiles([bool] $AsJob, [bool] $AsDownload){ $this.auditLogFile.MountAllFiles($AsJob, $AsDownload) } [int] getMatchIdByExternal([string] $externalKey, [int] $matchId) { $uri = $this.config.UriFindExternalId($externalKey, $this.auditLogFile.getExternalByKey($externalKey), $matchId) try { $json = (Invoke-RestMethod -Uri $uri) $definitionMatchId = $json.id } catch { $definitionMatchId = $null } return $definitionMatchId } #endregion } #region Validators class ValidExternalKeys : IValidateSetValuesGenerator { [string[]] GetValidValues() { # TODO double check [ProcessorFactory]::Init([Config]::Load().processors) return ([ProcessorFactory]::mapExternalKeyPrefix.Keys) } } #endregion |