Javascript Hyperledger composer:在更新资产的事务中调用查询将返回旧结果

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

我对一个非常简单的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 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}'等