Javascript Hyperledger composer:在更新资产的事务中调用查询将返回旧结果
我对一个非常简单的Hyperledger Composer应用程序名称空间com.softwaremill.drivernetwork有一个问题Javascript Hyperledger composer:在更新资产的事务中调用查询将返回旧结果,javascript,hyperledger-fabric,blockchain,hyperledger-composer,Javascript,Hyperledger Fabric,Blockchain,Hyperledger Composer,我对一个非常简单的Hyperledger Composer应用程序名称空间com.softwaremill.drivernetwork有一个问题 participant Driver identified by licenseId { o String licenseId o String firstName o String lastName o Boolean licenseValid default =true } enum LaweEnforcerType { o
participant Driver identified by licenseId {
o String licenseId
o String firstName
o String lastName
o Boolean licenseValid default =true
}
enum LaweEnforcerType {
o POLICE
o CUSTOMS
o BORDER_GUARDS
}
participant LawEnforcer identified by lawEnforcerId {
o String lawEnforcerId
o LaweEnforcerType lawEnforcerType
}
participant Court identified by courtId {
o String courtId
o String description
}
enum FineState {
o ISSUED
o REJECTED
o ACCEPTED
}
asset Fine identified by fineId {
o String fineId
o Integer penaltyPoints
o DateTime date
o FineState fineState default ="ISSUED"
--> Driver driver
--> LawEnforcer lawEnforcer
}
asset CourtCase identified by caseId {
o String caseId
--> Court court optional
--> Fine fine
}
transaction AcceptedFine {
--> Fine fine
}
transaction RejectedFine {
--> Fine fine
}
执法者可以处以罚款。罚款可以被接受,也可以被拒绝,然后由司机上法庭
我想做的是,如果他接受的罚款总额超过20分,驾驶执照就会自动失效
因此,我创建了一个事务处理器
/**
* Accept fine
* @param {com.softwaremill.drivernetwork.AcceptedFine} acceptedFine
* @transaction
*/
async function acceptedFine(acceptedFine) {
console.log(`Accepting fine ${acceptedFine}`);
const fineRegistry = await getAssetRegistry('com.softwaremill.drivernetwork.Fine');
acceptedFine.fine.fineState = 'ACCEPTED';
await fineRegistry.update(acceptedFine.fine); // [1]
const allFines = await query('selectAcceptedFinesByDriver',
{driver: `resource:com.softwaremill.drivernetwork.Driver#${acceptedFine.fine.driver.licenseId}`}); // [2]
if (allFines.reduce((acc, val) => {return acc + val.penaltyPoints;}, 0) > 20) {
console.log('Driver excceded 20 points, blocking license');
const driverRegistry = await getParticipantRegistry('com.softwaremill.drivernetwork.Driver');
acceptedFine.fine.driver.licenseValid = false;
await driverRegistry.update(acceptedFine.fine.driver);
}
}
以及查询代码
query selectAcceptedFinesByDriver {
description: "Select all accepted fines for a given driver"
statement:
SELECT com.softwaremill.drivernetwork.Fine
WHERE (driver == _$driver AND fineState == "ACCEPTED")
}
现在,代码应该将Fine状态设置为[1]处的ACCEPTED。这是有效的-在处理事务后,我可以看到属性发生了变化
但问题是,在[2]执行查询时,刚刚在[1]更新的罚款仍处于发出状态,我已删除查询中where的正确部分以进行调试
我错过了什么?区块链的形状是否为交易冻结?发生了什么事?问题是你不能阅读自己写的东西。事务是原子的,因此在一个事务中更改的所有状态都将从当前状态提交为一个事务,或者-整个事务被拒绝 因此,您在查询中读取的“状态”是上次提交的状态中的已知状态,而当前事务尚未提交,因此[2]此时不可能获取“已接受”状态。Composer中的这种行为与您从基础Hyperledger结构区块链中获得的行为完全相同;GetStatequery将只读取提交的状态更改,而不读取由同一事务中先前PutState Pre update写入的当前事务中的数据。只有在该事务已经提交的情况下,查询才会起作用,即组织的对等方认可/提交事务原子事务到块和世界状态
您可以在此处阅读有关事务处理器的更多信息->您没有更新资产的精细状态,您只是在提交的事务上进行更新
您需要在资产上进行更新,更新方式与您更新licenseValid状态的方式类似。谢谢!这正是我所期望的。在SQL世界中,我的想法可能太多了:在这个非常简单的例子中,做什么比较容易——只需从事务中查询并添加处理后的罚款处罚点——但您是否有任何建议,在更大范围内处理类似情况的犹太方式是什么?您是否需要单独更新驱动程序,在罚款被记入分类账之后?我的建议是使用您的查询创建一个单独的事务,以查找所有超过阈值的驱动程序-并且您可以-作为一个原子事务-在同一注册表中“批处理”所有“驱动程序”更新-作为一个显然更具伸缩性的事务。这里有一个使用查询的示例,在示例网络中执行“批量”删除->如果您需要一些示例代码,请告诉我。基本上,您将创建一个类似的for或forEach循环,然后执行一个更新etc及其所有一个原子事务单元,因此您建议从cronjob或类似的东西调用另一个事务?您可以这样做,您将知道这些更新的紧迫性。使用composer事务提交,例如composer事务提交-ctaskadmin@driver-网络-d'{$class:com.softwaremill.drivernetwork.AcceptedFine}'等