Hi there,

We have a function that reads a collection of documents in the database, and 
then inserts N new documents into the collection depending on the results of 
the first read. We need this behaviour to be atomic, and so we explicitly take 
locks using xdmp:lock-for-update. This effectively forces the entire read and 
then conditional insert into a single threaded operation (which is fine).

The problem is this, our function looks like this - 

declare private function load-entities(
    $entities as element()*,
        $etag-map as map:map,
        $entity-id as xs:string?,
        $is-orphaned-series-item-allowed as xs:boolean,
    $missing-etag-allowed as xs:boolean,
    $ignore-duplicate-updates as xs:boolean
) as element(store:etag-map) {

    let $_ := xdmp:set-transaction-mode("update")
    return
            let $entity-ids := fn:distinct-values($entities/c:id)
            let $_ := $entity-ids ! xdmp:lock-for-update(.)
            return
                let $etag-map := _load-entities($entities, $etag-map, 
$entity-id, $is-orphaned-series-item-allowed, $missing-etag-allowed, 
$ignore-duplicate-updates)
                return
                    let $_ := xdmp:commit()
                    return
                        $etag-map
};

This all appears to work fine... however reading the documentation 
http://docs.marklogic.com/6.0/xdmp:rollback it seems that we should explicitly 
rollback the transaction if we encounter an error. Our function is itself 
called from a REST function library which expects to capture errors (using 
catch) and then modify the http response code etc appropriately depending on 
the error. If we use xdmp:rollback in a try/catch within our function pasted 
above, this causes our REST API to break as there is no way to `bubble` the 
error up, because it appears that xdmp:rollback terminates the processing of 
the query immediately. For example we have tried this - 

declare private function load-entities(
    $entities as element()*,
        $etag-map as map:map,
        $entity-id as xs:string?,
        $is-orphaned-series-item-allowed as xs:boolean,
    $missing-etag-allowed as xs:boolean,
    $ignore-duplicate-updates as xs:boolean
) as element(store:etag-map) {
 
    let $_ := xdmp:set-transaction-mode("update")
    return
        try {
         
            let $entity-ids := fn:distinct-values($entities/c:id)
            let $_ := $entity-ids ! xdmp:lock-for-update(.)
            return
                let $etag-map := _load-entities($entities, $etag-map, 
$entity-id, $is-orphaned-series-item-allowed, $missing-etag-allowed, 
$ignore-duplicate-updates)
                return
                    let $_ := xdmp:commit()
                    return
                        $etag-map
        } catch($e) {
            (xdmp:rollback(),
                xdmp:rethrow()
            )
        }
};

The problem being if we call xdmp:rollback before xdmp:rethow, it appears that 
rethow is never called so our REST API fails to see the error and just returns 
HTTP 200. Likewise if we call xdmp:rethrow before xdmp:rollback, it seems that 
xdmp:rollback is never called. I guess I kinda expected that behaviour... but 
how do we actually solve our problem then?
How *bad* would it be to not actually call xdmp:rollback in terms of 
transactions being collected when they timeout?

Please keep in mind that this is a large code-base and whilst it has some 
design issues, refactoring everything at present is not really an option.

Cheers Adam.

DISCLAIMER
This message is intended only for the use of the person(s) ("Intended 
Recipient") to whom it is addressed. It may contain information, which is 
privileged and confidential. Accordingly any dissemination, distribution, 
copying or other use of this message or any of its content by any person other 
than the Intended Recipient may constitute a breach of civil or criminal law 
and is strictly prohibited. If you are not the Intended Recipient, please 
contact the sender as soon as possible.
Reed Business Information Limited. Registered Office: Quadrant House, The 
Quadrant, Sutton, Surrey, SM2 5AS, UK. 
Registered in England under Company No. 151537

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

Reply via email to