問題はMarkLogicが更新トランザクションを処理する方法です。各xdmp.docuentInsert(…)
コールで実際にデータを変更するのではなく、MarkLogicはすべての更新をキューに入れ、要求の最後にアトミックに適用します。これは、同じトランザクション内でデータベースの更新を見ることができない理由です。したがって、ループが実行され、データベースがキューに入れられたトランザクションをコミットしようとするまで、エラーはスローされません。この動作は、XQuery(やや簡略化)に同じです。
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()
を使用して、親要求とは別のトランザクションで関数を "呼び出し"ます。 (優勝のためのファーストクラスの機能!)これにより、アップデートが完全に適用される(またはエラーでロールバックされる)ことと、呼び出しモジュールが更新(またはエラー)を見ることができます。私は自分のapplyAs()
関数で低レベルのxdmp.invokeFunction()
をラップしました。関数の引数をカルトした関数に正しく渡すような細かさを提供しています。
'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;
}
}
}
今、あなたはあなたの答えを受け入れる必要があります;)私は投票詰め物を避けるために想像 – joemfb
、あなたは2日間、あなた自身の答えを受け入れることはできません。 –