I'd expect rollback to be automatic if the transaction ends with an uncaught 
error. You should only have to worry about rollback and commit if the statement 
runs in MST update mode and completes successfully.

To test that take a look at the host-status page in the admin UI. The third 
table from the bottom shows active transactions on a host. It's normal to see 
one on the Security database: that's your request for the host status page. But 
if you see unexpected transaction entries and they hang around for minutes, 
then you might have a problem with rollback. You can get the same information 
from xdmp:host-status if you'd like to build tools around it.

In passing, transactions will be atomic by default whether you call 
xdmp:lock-for-update or not. You'd have to make an effort to avoid atomicity. 
The reason to call xdmp:lock-for-update is to explicitly write-lock a URI, 
either because you want to use a non-existent URI as a mutex or because you 
want to lock a URI as early as possible to reduce the potential for deadlocks.

-- Mike

On 29 Jul 2014, at 08:50 , Retter, Adam (RBI-UK) <[email protected]> wrote:

> 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
> 

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

Reply via email to