Cross posted on mathematica.stackexchange
TLDR
There is a pool of kernels/sessions available for each user, you don't have control over the pool, only over specific kernel you currently evaluate in. Re-upload of a package should be followed by quit on every kernel where previous version of a package was used. I failed to find tools for that.
Background
I'm developing a package which I want to deploy to my Wolfram Public Cloud's account and I want a set of APIFunctions
/FormFunctions
/etc to be able to use it.
PacletManager
has limited functionality so I'm just uploading package's archive and extracting it to WPC's $UserBaseDirectory / Applications /
.
APIFunctions
and friends have form:
APIFunction[{}, (Needs["TestPackage`"];Symbol["TestPackage`api2"][...]) &]
I use Symbol
because otherwise TestPackage`
definitions are uploaded and I want to avoid that. There should be one code source, the package in $UserBaseDirectory
.
Problem
The problem is that kernels' management on WPC is a closed black box. If you call the api twice, each time it uses one of the kernels in the pool. It also applies to CloudEvaluate
etc.
$UserBaseDirectory
is shared but Get
will find the current version ony for current kernel.
If in another kernel TestPackage`
was loaded earlier, Needs
will not load the current version there :-/ I don't wan't to Get
in my APIFunctions, a proper way is to call Needs
.
And there is no way to Quit
every available kernel.
Example
is worth of 10^3 words:
First we will mimic a package upload, 10 times. So it was uploaded, something was fixed it was uploaded again etc:
packageTemplate = StringTemplate["
BeginPackage[\"TestPackage<*\"`\"*>\"];
myValue = \"``\"
EndPackage[];
"];
Do[
CloudExport[packageTemplate@RandomReal[], "Text", "TestPackage.m"]
; CloudEvaluate[
CopyFile[
"TestPackage.m"
, StringRiffle[
{$UserBaseDirectory, "Applications", "TestPackage.m"}
, "/"
]
, OverwriteTarget -> True
]
; Get @ "TestPackage`"
]
, {10}
]
Now let's call code based on the package 25 times:
Table[
CloudEvaluate[
Needs["TestPackage`"]
; {$SessionID, Symbol["TestPackage`myValue"]}
]
, {25}
] // CountBy[Last] // Normal // Column
7 different results, I expect only one variant, from the last deployment.
The question
How to upload a package and clean properly, as we can see Get
after the upload only affects one particular kernel/sessopm. CloudEvaluate@Quit[]
won't help either.
How to reset them all?
Requirements
APIFunction[{}, (Get["TestPackage`"];Symbol["TestPackage`api2"][...]) &]
could solve it but if the package contains Protected
/Locked
symbols you will get a flood of errors. And because of the same reason you can't ClearAll
symbols. And obviously you can't Quit
in ApiFunction
.