https://github.com/mblakele/presta is now available. This library started when 
I noticed the new 'result' option for xdmp:spawn in MarkLogic 5.0. That looked 
handy, but xdmp:spawn still wanted me to supply a module path. I wanted to 
write XQuery tasks with arbitrary code strings, like this:

    for $i in 1 to 4
    return xdmp:spawn-eval(
      'xdmp:sleep(1000)', (),
      <options xmlns="xdmp:eval">
        <result>true</result>
      </options>),
    xdmp:elapsed-time()

...and have all four tasks execute in parallel, using all my CPUs and returning 
the results. Here's what I ended up with:

    import module namespace presta="com.blakeley.presta"
      at "presta.xqy";

    let $presta-id := presta:prepare('xdmp:sleep(1000)')
    for $i in 1 to 4
    return presta:spawn(
      $presta-id, (),
      <options xmlns="xdmp:eval">
        <result>true</result>
      </options>),
    xdmp:elapsed-time()

The presta:spawn function works just like xdmp:spawn, and takes the same 
arguments - except that the first parameter is a presta id not a module path. 
We get that id by calling presta:prepare, which takes the XQuery string and 
stores it the Modules database.

The id for a Presta module is based on xdmp:hash64, so preparing the same 
XQuery twice will return the same id. Presta tries not to update the Modules 
database any more than necessary - but it's still best to stash these ids 
somewhere if you can.

Once prepared, we can also use a presta id with presta:invoke. This is handy 
for apps that eval the same strings frequently,  because the Presta module 
works with the module cache. And we don't have to keep the XQuery around after 
it has been registered. This could be a way for developers using Java to get 
some of the performance benefits of invoke, without having to write every 
XQuery module in advance.

But there's more to MarkLogic than XQuery. We can also call presta:prepare with 
XSLT, and then call presta:xslt-invoke.

We need libraries, too. So you can call presta:import to install a library 
module where other Presta functions can find it.

    presta:import(
      'lib-test.xqy',
        'module namespace t="com.blakeley.presta.test";
         declare function t:now() { fn:current-dateTime() };')

    presta:invoke(
      p:prepare(
        'import module namespace t="com.blakeley.presta.test"
           at "lib-test.xqy";
         t:now()

I almost forgot about environments with multiple applications. Every app-server 
automatically gets its own Presta environment, based on the appserver id from 
xdmp:server(). If you want multiple servers to share the same Presta modules, 
we can call presta:appkey-set('my-app-key'). If you want to keep modules 
somewhere other than the Modules database, set the app-server modules location 
to any database you like.

Of course I also wanted Presta to work with profiling. Presta supports cprof, 
and includes a copy of the cprof library. My plan is to discontinue cprof as a 
separate project, and include it as part of Presta.

Finally, Presta works with the security model. Presta installs a new role that 
you can grant to any user.

The code is at https://github.com/mblakele/presta - I hope it's useful.

-- Mike
_______________________________________________
General mailing list
[email protected]
http://community.marklogic.com/mailman/listinfo/general

Reply via email to