Il problema è come i processi di MarkLogic aggiornano le transazioni. Invece di modificare effettivamente i dati con ciascuna chiamata xdmp.docuentInsert(…)
, MarkLogic mette in coda tutti gli aggiornamenti e li applica atomicamente alla fine della richiesta. (Questo è anche il motivo per cui non è possibile visualizzare gli aggiornamenti del database all'interno della stessa transazione.) Pertanto, l'errore non viene generato fino a quando il ciclo non viene eseguito e il database tenta di eseguire il commit delle transazioni in coda. Questo comportamento è lo stesso in XQuery (leggermente semplificata):
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)
}
Per raggiungere gli errori in modo sincrono, avresti bisogno di mettere ogni aggiornamento nella propria transazione. In generale, questo approccio sarà molto più lento e dispendioso in termini di risorse rispetto alla gestione predefinita delle transazioni di MarkLogic. Tuttavia, è illustrativo qui per dimostrare cosa sta succedendo sotto le copertine e può tornare utile per casi d'uso specifici, come questo.
Nell'esempio seguente, utilizzo xdmp.invokeFunction()
per "chiamare" una funzione in una transazione separata dalla richiesta padre. (Funzioni di prima classe per la vittoria!) Ciò consente agli aggiornamenti di essere completamente applicati (o ripristinati con un errore) e al modulo di chiamata di vedere gli aggiornamenti (o errori). Ho spostato il livello basso xdmp.invokeFunction()
nella mia funzione applyAs()
per fornire alcune sottigliezze, come passare correttamente gli argomenti della funzione alla funzione al curry.
'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;
}
}
}
Ora è necessario accettare la tua risposta;) – joemfb
immagino per evitare brogli elettorali, non potete accettare la propria risposta per due giorni. –