Here is the problem:
I have one substantial app that will not run on exist instances with default minimum memory configuration. Now despite this figuring prominently on the installation instructions. User's keep trying to install and consequently crashing their instances. To avoid frustrating users of the app, and to try to maintain a sunshiny attitude beyond and above "RTM!"
Solution (so far)
I modified the pre-install.xql like this to abort if either cacheSize or memory is below required minimum.
xquery version "3.0";
import module namespace xdb = "http://exist-db.org/xquery/xmldb";
import module namespace file = "http://exist-db.org/xquery/file" at "java:org.exist.xquery.modules.file.FileModule";
(: The following external variables are set by the repo:deploy function :)
(: file path pointing to the exist installation directory :)
declare variable $home external;
(: path to the directory containing the unpacked .xar package :)
declare variable $dir external;
(: the target collection into which the app is deployed :)
declare variable $target external;
(: the path to the exist-db installation :)
declare variable $exist_home as xs:string := system:get-exist-home();
(:check available memory:)
declare variable $mem-max := system:get-memory-max();
(: minimum memory requirements :)
declare variable $mem-req := 2000000000;
(: minimum cache Size:)
declare variable $cache-req := 500;
declare function local:mkcol-recursive($collection, $components) {
if (exists($components)) then
let $newColl := concat($collection, "/", $components[1])
return
(
xdb:create-collection($collection, $components[1]),
local:mkcol-recursive($newColl, subsequence($components, 2))
)
else
()
};
(: Helper function to recursively create a collection hierarchy. :)
declare function local:mkcol($collection, $path) {
local:mkcol-recursive($collection, tokenize($path, "/"))
};
(: Helper function to check the instance's chacheSize. :)
declare function local:check-cache-size($path as xs:string) as xs:boolean {
if (file:is-readable($path || "/conf.xml"))
then
(
let $doc := fn:parse-xml(file:read($path || "/conf.xml"))
return
if (number(substring-before($doc//exist/db-connection/@cacheSize/string(), "M")) > $cache-req)
then
(fn:true())
else
(fn:error(fn:QName('https://github.com/duncdrum/cbdb-data', 'err:cache-low'), 'Your configured cacheSize is too low')))
else
(fn:true())
};
(: Helper function to check the instance's memory. :)
declare function local:check-mem-size($memory as xs:integer) as xs:boolean {
if ($memory > $mem-req)
then
(fn:true())
else
(fn:error(fn:QName('https://github.com/duncdrum/cbdb-data', 'err:memory-low'), 'Your configured -xmx memory is too low'))
};
if (local:check-mem-size($mem-max) and local:check-cache-size($exist_home))
then
(
(: store the collection configuration :)
local:mkcol("/db/system/config", $target),
xdb:store-files-from-pattern(concat("/db/system/config", $target), $dir, "*.xconf"))
else
(fn:error(fn:QName('https://github.com/duncdrum/cbdb-data', 'err:pre-crash'), 'An unknown error occured during pre-install'))
The good
The app produces a visible error inside package-manager when expected, User no longer have to wait 20min just to see a generic error and a crashed instances.
The meh
The app is still fully registered to the package-manager, where it can be uninstalled after a partial install. It also appears on the dashboard, although since it aborted it is not functional. App contents are partially written into db/apps/myapp
.
Question
Is there a better way to abort (and undo) an install? Provided that installing has to happen via the dashboard's package-manager. I like that users now see custom errors telling them whats wrong, should these be sent to console:log
? Must failed installs be cleaned up in post-install.xql, or can I do a better job in pre-install.xql already? Any other obvious oversights in this pre-install.xql.
To test
You can simply create an empty exist app via eXide and replace the default pre-install.xql with the one above. Change the $mem-req
to either succeed or error out on your instance. Download app and attempt to install.
Edit 1
According to the docs "[pre-install.xql] will be executed before any package data is uploaded to the database." This is not what I am seeing. Data is uploaded, which is why cleanup is currently required. So this might actually be a bug.
Edit 2
I tried different combinations of util:log
or fn:trace
which then allow my to call repo-undeploy(), repo-remove()
to clean up. But I need fn:error
to actually abort to prevent crashing, and to report to package-manager. So yeah feature request seems TWTG. Is there a way to log a message to where error message appear in the package-manager without using fn:error
?