有没有一种方法可以尝试通过ID来获取合同,并且在合同处于非活动状态时不会失败?

时间:2019-09-24 07:41:10

标签: daml

使用合同密钥,有两个功能fetchByKeylookupByKey,其中两个功能使我可以处理否定查询。我没有看到lookup : (Template t) => ContractId t -> Update (Optional t)函数对合同ID的作用相同。 我也没有看到尝试捕获机制,该机制可以让我处理失败的fetch调用。

如何避免在不重新实现整个DAML逻辑客户端的情况下失败交易?

1 个答案:

答案 0 :(得分:4)

这个问题有很多需要解决的地方:

  1. 为什么没有lookup
  2. 为什么没有try-catch块?
  3. 交易失败是否可以避免?
  4. 如何在不复制合同逻辑的情况下编写分类账客户?

lookupByKey和建议的lookup函数允许事务提交者对合同进行不存在的断言。来自None的{​​{1}}结果断言特定键不存在,来自lookupByKey的{​​{1}}将断言特定None不存在。最大的区别在于,合同的合同密钥包括密钥维护者,验证查询的各方。因此很明显,谁必须授权lookup,谁可以验证否定结果。使用ContractId时,没有与lookupByKey关联的各方,因此也没有明智的授权或验证规则。

一个较弱的版本是lookup,如果id未知,它将失败,如果已归档合同ID,则返回ContractId。 DAML事务取决于当前分类帐状态,该状态当前是所有活动合同的集合。诸如fetchIfNotArchived : (Template t) => ContractId t -> Update (Optional t)之类的功能会在DAML分类帐模型中引入不存在的合同和已存档合同之间的区别,因此分类帐状态将从一开始就从所有活动合同更改为整个分类帐。 DAML分类帐不再能被截断并随时间线性增长,这是不可取的。

使用try-catch块会遇到非常相似的问题。假设我进行了一些尝试。我可以编写此函数:

None

如上所述,没有人可以合理地授权或确认提交者遵循正确的道路。因此,这样的try-catch必须被“取消选中”,这意味着提交者可以自由选择是沿着fetchIfNotArchived还是lookup : (Template t) => ContractId t -> Update (Optional t) lookup cid = do try do c <- fetch cid return (Some c) catch return None 路径前进。您可以通过以下方式传递存在的内容:

try

这需要您从外界传入catch,这很烦人。可以想象“未经检查的查询”可以在这里提供帮助。例如。可以引入一个函数maybeLookup : (Template t) => ContractId t -> Bool -> Update (Optional t) maybeLookup cid cidIsKnown = if cidIsKnown then do c <- fetch cid return (Some c) else return None ,该函数检查合同在提交者端是否有效,然后仅将cidIsKnown包括在交易中。显然,是否像cid存在一样运行事务是提交者的自由选择,或者相反。

到目前为止,未经检查的查询尚未进入DAML的原因很简单,原因是混淆了共享,保证和验证的逻辑内容以及单个客户关注的内容。在当前的设计中,这种划分恰好在DAML合同和分类账客户之间。

失败的事务实际上并不那么昂贵,只要它们在解释期间在提交者节点上失败即可。重要的是设计合同模型和分类帐客户,以使uncheckedContractActive : (Template t) => ContractId t -> Update Bool调用只能因竞争条件而失败,并且对合同的争用不会太多,因此交易失败很多。你可以尝试

  • 设计每个自动化过程,以使其跟踪“待定集”,即它希望通过其运行中的命令进行归档的一组合​​同ID。这样就消除了每个自动化过程对自己的争执
  • 如果同一方的自动化有两个竞争点,那就是将合同分成两部分,或者将自动化合并为一个。
  • 如果您有两个针对同一合同的当事方具有两个自动化功能,请调整选择结构以使工作流更加同步。即DAML中的控制权是谁
  • 如果您的自动化部件偶尔会进行大批量操作而导致与其他自动化部件发生竞争,请引入某种“防护措施”。例如。向分类帐写入Bool合同,以指示非批处理自动化应暂停,或使用fetch合同保护选择,该合同在批处理开始时将被吊销。后者具有更强的保证,但会增加开销,因为它会为每个选择添加Lock

一旦将争用减少到可接受的水平,就可以使用分类帐客户端中的重试逻辑来处理Operation失败的呼叫。