首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么不能捕获MarkLogic请求中的某些异常?

为什么不能捕获MarkLogic请求中的某些异常?
EN

Stack Overflow用户
提问于 2016-03-01 19:19:06
回答 1查看 401关注 0票数 8

我有一些练习“invalid values” setting on an element range index的代码。在本例中,我已经为我的数据库中的dateTime元素配置了一个onDate元素范围索引(这将同时适用于onDate元素和JSON属性)。我已将该索引设置为拒绝无效值。这种设置意味着,如果我试图设置onDate元素的值,并且它不能转换为dateTime,或者为null ( JSON中的文本null或XML中的xsi:nil="true" ),那么我的更新将失败。(相反的行为是完全忽略无效值。)

我在服务器端JavaScript中尝试了MarkLogic 8.0-4中的以下代码:

代码语言:javascript
复制
'use strict';
declareUpdate();
var errors = [];
var inputs = {
 '/37107-valid.json': (new Date()).toISOString(),
 '/37107-invalid.json': 'asdf',  // Should throw an error
 '/37107-null.json': null  
};

for(var uri in inputs) {
 try {
   xdmp.documentInsert(
     uri,
     { 'onDate': inputs[uri] },
     xdmp.defaultPermissions(),
     ['37107'] // Collections
   );
 } catch(err) {
   errors.push(err);
 }
}
errors.length;

我本以为我的请求会成功,并以1 === errors.length结束,因为只有第二个插入会失败,因为'asdf'不能作为dateTime转换,而且它不是null。然而,相反,我得到一个XDMP-RANGEINDEX错误,我的事务失败。为什么我的try/catch在这里不起作用?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-01 19:19:06

问题是MarkLogic进程如何更新事务。与使用每个xdmp.docuentInsert(…)调用实际更改数据不同,MarkLogic对所有更新进行排队,并在请求结束时原子地应用它们。(这也是为什么您无法在同一事务中看到数据库更新的原因。)因此,直到循环执行并数据库尝试提交排队的事务之后,才会引发错误。这种行为在XQuery中是相同的(稍微简化了一些):

代码语言:javascript
复制
let $uris := (
 '/37107-valid.xml',
 '/37107-invalid.xml',
 '/37107-null.xml'
)
let $docs := (
 <onDate>{fn:current-dateTime()}</onDate>,
 <onDate>asdf</onDate>,
 <onDate xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
)
return
 for $uri at $i in $uris
 return 
   try {
     xdmp:document-insert($uri, $docs[$i], (), ('37107'))
   } catch($err) {
     xdmp:log($err)
   }

为了同步捕获错误,需要将每个更新都放入自己的事务中。一般来说,这种方法要比MarkLogic的默认事务处理要慢得多,而且需要耗费资源。但是,这里说明了在幕后所发生的事情,并且可以为特定的用例提供方便,比如这个用例。

在下面的示例中,我使用xdmp.invokeFunction()在一个与父请求分离的事务中“调用”一个函数。(赢得比赛的一流功能!)这允许完全应用更新(或带错误回滚)和调用模块查看更新(或错误)。我已经在我自己的xdmp.invokeFunction()函数中封装了低级别的applyAs(),以提供一些细节,比如正确地将函数参数传递给咖喱函数。

代码语言:javascript
复制
'use strict';

var errors = [];
var inputs = {
 '/37107-valid.json': (new Date()).toISOString(),
 '/37107-invalid.json': 'asdf',
 '/37107-null.json': null
};

var insert = applyAs(
 function(uri, value) {
   return xdmp.documentInsert(
     uri,
     { 'onDate': inputs[uri] },
     xdmp.defaultPermissions(),
     ['37107']
   );
 },
 { isolation: 'different-transaction', transactionMode: 'update' },
 'one'
);

for(var uri in inputs) {
 try {
   insert(uri, inputs[uri]);
 } catch(err) {
   errors.push(err);
 }
}
errors.length; // Correctly returns 1


// <https://gist.github.com/jmakeig/0a331823ad9a458167f6>
function applyAs(fct, options, returnType /* 'many', 'one', 'iterable' (default) */) {
  options = options || {};
  return function() {
    var params = Array.prototype.slice.call(arguments); 
    // Curry the function to include the params by closure.
    // xdmp.invokeFunction requires that invoked functions have
    // an arity of zero.
    var f = (function() {
       return fct.apply(null, params);
    }).bind(this);
    // Allow passing in user name, rather than id
    if(options.user) { options.userId = xdmp.user(options.user); delete options.user; }
    // Allow the functions themselves to declare their transaction mode
    if(fct.transactionMode && !(options.transactionMode)) { options.transactionMode = fct.transactionMode; }
    var result = xdmp.invokeFunction(f, options); // xdmp.invokeFunction returns a ValueIterator
    switch(returnType) {
      case 'one':
        // return fn.head(result); // 8.0-5
        return result.next().value;
      case 'many':
        return result.toArray();
      case 'iterable':
      default:
        return result;
    }
  }
}
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35731564

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档