Cache Mechanism

Product: PowerShell Universal
Version: 1.4.6

Hi, i’m still using an old UD Version, but i would like to switch to PSU.
I’m only using the REST Endpoints parts . ( no dashboards at all ! )

In UD i was using Scheduled Endpoint to populate some Cache variables, and fetch data in my REST endpoints.

I’m struggling to reproduce the same behavior with PSU.

if i create a basic script $cache:test = 1..1000 | get-random and the schedule it with the admin console, i’m not able to retrieve the content of $cache:test in my REST endpoint.

So maybe i’m missing something, or not understanding someething correctly :frowning:

thanks in advance for the help :slight_smile:

At least for newer versions… If you are looking to utilize the cache, I’d say use Set-PSUCache and Get-PSUCache. They function in a similar manner and I can confirm they work.

I don’t know if the Cache scope is tied to those functions but I have not had much luck using that scope in my personal testing.

ok so in your experience, you can define a cache variable in a scheduled endpoint and use it in a rest endpoint ?

From my understanding of the Documentation, the PSUCache is available throughout the product. But there is no reference to the $Cache: variable scope in the docs for this functionality. They may not be directly related.

The $Cache scope only works in dashboards. The *-PSUCache cmdlets work throughout the product. The difference is that the PSUCache stores items are CliXml rather than live objects like the $Cache scope.

You can create a scheduled job in PSU to set the variables and then use them in your endpoint as the cmdlets will be available in both places.

2 Likes

Arf ok ! thanks for the reply @adam
thats settle it … i wont be able to migrate to PSU at the moment :frowning:

I was using the cache variable to store Exchange Online pssession (live object) and use these sessions in my REST endpoints… !

If you are persisting exchange online sessions for performance reasons, I’d suggest using a persistent runspace for your API environment.

Module.psm1

function Get-EOSession {
    if ($Global:EOSession  -eq $null)
    {
           $Global:EOSession = Connect-EOSession 
    }
   $Global:EOSession
}

Environments.ps1

New-PSUEnvironment -Name 'Persistent' -Path 'pwsh' -PersistentRunspace -Module @('Module.psm1')

Settings.ps1

Set-PSUSetting -ApiEnvironment 'Persistent'

What this will do is not flush the runspace state after every execution. You will be able to store your PSSession in a global variable. The module will be automatically loaded into each runspace and you will have access to the Get-EOSession function so you can retrieve your session in your endpoints.

2 Likes

omg … i have to test that … !!! thank you @adam !

1 Like

I actually just realized how useful this is for Azure as well. I hadn’t really considered it (I have a script that runs every so often to maintain the connection, since it seems to persist across the system regardless) but this seems like it could be very useful :thinking:

yes it’s super useful … i can tell you exactly what i did, but you can guess … :wink:

1 Like

ok @adam i tried you solution and it kinds of work ^^

i’m saying this, because it’s not totaly what i was looking for …

when i mentionned that i had a cache variable holding pssession i meant more than one Exo session.
And even with one session i dont think i can use your example, because, when the session dies, i will be forced to recreate the session, when a user makes a call to the endpoint, by calling the function.
This will crumble the performance of the endpoint as i have to wait for the creation of the session.
(dunno if i’m clear … )

What i’m doing right now with UD (old version … ): I have a schedule route, that will manage the
Exo sessions for me … when a session dies, it will recreate a new one, and the user experience will be intact.

I had the same mechanism for refreshing some cache variable imported from big csv ( the csv were also generated using some scheduled endpoints.). For this, i think i can use the PSUCache cmdlet and a PSU Schedule + PSU Script. Or maybe switch to a real Database + a PSU Schedule.

If i’m not very clear (sorry english is not my primary language) i can show you some code sample of how i managing it with my old UD.

the question is: can we hope for a cache variable scope that is available through the whole product ? or maybe available for the Rest api part ??

the question is: can we hope for a cache variable scope that is available through the whole product ? or maybe available for the Rest api part ??

No because everything is in a separate process. The server-wide cache works by serializing everything across the process boundaries.

What you could do is store the sessions in global scope in your module. Then create an endpoint that is responsible for refreshing that cached global scope sessions. Then call that endpoint on a schedule.

2 Likes

@adam Is there a solution to manage session with Get-PSSession , because that returns an error.

Error getting value from ‘RunspaceConfiguration’ on ‘System.Management.Automation.RemoteRunspace’

When you call Get-PSSession you receive that error? Or when you are trying to use the cache?

@adam

When i use Get-PSsession to retrieve the different sessions that i get with Connect-ExchangeOnline
and after we can push them in $global:myvar

For example :
$Global:myvar = Get-PSSession

@adam we made a few tests
we really struggle with pssession and api endpoints …
i tried your solution to create a function to handle pssession (or exchange session). To make thinks easier, instead of using exchange online, i tried with a simple pssession to a remote server.

i have the following function that’s loaded in a persistend env:

function newsession {
    if ( $null -eq $global:session ) {
        return New-PSSession -HostName demoserver -UserName someusername
    }
}

i created a simple api endpoint wich does the following:

New-PSUEndpoint -Url "/test" -Endpoint {
   $global:session = newsession
}

i have another simple endpoint

New-PSUEndpoint -Url "/getsession" -Endpoint {
   #wait-debugger
   if ( $null -eq $global:session ) { 'no session...' } else { 'we have contact!' }
}

If i run the test endpoint and then run the getsession endpoint, it return ‘no session’ !

What i did next : I put a wait-debugger in the getsession endpoint.
I connect to the psu process, and do a get-runspace. I find my waiting runspace. And the remove PSSession to my server !!!
but if i enter in the runspace for the getsession endpoint ( i’ve put the wait-debugger at the first line) and fetch the $global:session variable… it is empty… !

i could do a Get-Pssession, but it find it strange that the global var is empty … ! is this normal ???

I know you sent me a video that I still need to look at but it is normal in that we use a runspace pool so that global variable may not be shared between those runspaces. You make more API requests it will open up more sessions and runspaces. Each runspace would then have a PSSession but the PSSessions would not be shared between the runspaces. Once you make a certain amount of requests, it will stop creating new runspaces and will start reusing the runspaces that were already created.

erf… thanks @adam
i guess we will have to stay on the old UD at the moment… or there is something i’m missing … !

With PSU v2, you can now use the $Cache scope in all places. If you use the integrated environment, you can share cache variables across APIs, Scripts and Dashboards: Cache - PowerShell Universal

1 Like

w00t ??? !!!
ok i’m testing this tomorrow… !