Как получить / вычислить CommitDigest при фиксации транзакции в AWS QLDB?
Я читал документы, пытаясь понять, как совершить транзакцию в QLDB, и для этого CommitDigest
требуется, и в документации это описывается как:
Задает дайджест фиксации транзакции для фиксации. Для каждой активной транзакции должен быть передан дайджест фиксации. QLDB проверяет CommitDigest и отклоняет фиксацию с ошибкой, если дайджест, вычисленный на клиенте, не совпадает с дайджестом, вычисленным QLDB.
Итак, CommitDigest необходимо вычислить, но я не совсем уверен, что требуется для его вычисления, учитывая этот пример:
// ** Start Session **
const startSessionResult = await qldbSession.sendCommand({
StartSession: {
LedgerName: ledgerName
}
}).promise(),
sessionToken = startSessionResult.StartSession!.SessionToken!;
// ** Start Transaction **
const startTransactionResult = await qldbSession.sendCommand({
StartTransaction: {},
SessionToken: sessionToken
}).promise(),
transactionId = startTransactionResult.StartTransaction!.TransactionId!;
// ** Insert Document **
const executeStatementResult = await qldbSession.sendCommand({
ExecuteStatement: {
TransactionId: transactionId,
Statement: `INSERT INTO sometable { 'id': 'abc123', 'userId': '123abc' }`
},
SessionToken: sessionToken
}).promise(),
documentId = getDocumentIdFromExecuteStateResult(executeStatementResult)
// ** Get Ledger Digest
const getDigestResult = await qldb.getDigest({
Name: ledgerName
}).promise(),
ledgerDigest = getDigestResult.Digest;
// ** Commit Transaction **
// ** **The API call in question** **
const commitTransactionResult = await qldbSession.sendCommand({
CommitTransaction: {
TransactionId: transactionId,
CommitDigest: `${commitDigest}` // <-- How to compute?
},
SessionToken: sessionToken
}).promise();
// *******************************
// ** End Session **
const endSession = await qldbSession.sendCommand({
EndSession: {},
SessionToken: sessionToken
}).promise();
Что мне нужно для хеширования CommitDigest
в CommitTransaction
вызов api?
2 ответа
Обновление: теперь доступен драйвер Node.js. Взгляните на https://github.com/awslabs/amazon-qldb-driver-nodejs/.
На момент написания драйвер QLDB Node.js все еще находится в разработке. Будет довольно сложно, если вы попытаетесь создать его самостоятельно, поэтому я бы предостерегал от этого. Тем не менее, я могу объяснить как цель, так и алгоритм CommitDigest.
Цель довольно проста: гарантировать, что транзакции фиксируются только в том случае, если сервер обработал точный набор операторов, отправленных клиентом (все по порядку, без дубликатов). HTTP - это запрос-ответ, поэтому запросы могут быть отброшены, обработаны не по порядку или дублированы. Драйверы QLDB правильно управляют обменом данными с QLDB, но наличие дайджеста фиксации в протоколе делает невозможным для реализации некорректно повторять запросы и при этом фиксировать транзакцию. Например, рассмотрите возможность увеличения баланса банка дважды, потому что HTTP-сообщение повторяется, даже если первый запрос был успешным.
Алгоритм также довольно прост: хеш-значение заполняется идентификатором транзакции, а затем обновляется с помощью оператора QLDB "точка". Каждое обновление "точки" в хэше оператора (sha256 строки PartiQL), а также IonHash всех значений привязки. Оператор точки - это способ, которым QLDB объединяет хеш-значения (это тот же оператор, который используется в API проверки.) и определяется как хэш конкатенации двух хешей, упорядоченный побайтным сравнением (со знаком, с прямым порядком байтов) между двумя хешами. Клиент и сервер запускают этот алгоритм в режиме блокировки, и сервер будет обрабатывать команду фиксации только в том случае, если значение, передаваемое клиентом, совпадает с вычисленным сервером. Таким образом, сервер никогда не совершит транзакцию, которая не совсем то, что запросил клиент.
У меня недостаточно репутации, чтобы добавить комментарий, но я обнаружил, что эта библиотека может помочь: https://github.com/amzn/ion-hash-js
Я сейчас здесь:
const ionHashJS = require("ion-hash-js/dist/commonjs/es5/src/IonHash");
const ionStr =
"INSERT INTO Vehicle { 'VIN': '12345', 'Type': 'Semi', 'Year': '2020', 'Make': 'Frank', 'Model': '313373', 'Color': 'Blue' }";
const hashReader = ionHashJS.makeHashReader(
ionJs.makeReader(ionStr),
ionHashJS.cryptoIonHasherProvider("sha256")
);
hashReader.next();
hashReader.next();
const digest = hashReader.digest();