AOS 2.0 都有哪些让人兴奋的更新(附 Demo)

作者: txohyeah

审阅:outprog

来源:内容公会 - 新闻

AOS 升级

如果你需要新创建一个 aos 2.0 的进程,那么需要更新本地的 aos 包,命令如下

AOS 2.0 都有哪些让人兴奋的更新(附 Demo)

如果是过去已经创建的进程,那么需要在更新本地的 aos 到 2.0 以后,再连接上进程后,运行.update命令。如下图,升级完成后,aos 给出的 prompt 有如下变化,就是升级成功了。

AOS 2.0 都有哪些让人兴奋的更新(附 Demo)

本次升级最主要包含 3 个功能的升级:

  1. Receive() 方法,类似于 javascript 中的 await 方法。
  2. 通过更符合语义的方式,对消息进行 Request 和 Response。
  3. 对于 Handlers 中的匹配给出了更加符合语义的语法。

Receive() 方法

案例

简单的说这个方法就是 aos 中的 await 方法。这也是官方的解释:the await of aos.

相信这样解释各位开发人员已经能很好理解了,我也不做过多解释。直接看个例子:

AOS 2.0 都有哪些让人兴奋的更新(附 Demo)

上面简单的三行代码,就可以避免之前把逻辑散落各处的 Handler 的写法。可以让开发者逻辑更清晰,代码可以被更好的阅读。

原理介绍

  1. Receive(pattern) 是一个内置的全局方法。Receive 函数中使用了新引入的特性 coroutine,Lua 中的 coroutine 是一种实现协同程序(协程)的机制。协程是一种比线程更轻量级的执行单元,可以在用户空间调度和管理,不需要操作系统级别的支持。在代码运行的当前位置进行 yield(即阻塞本次执行,让渡出资源,等到接收到匹配的消息,再恢复执行),如上面例子中就是 local res = Receive({From = LlamaCoinProcessId}) 这句。然后通过 Handlers.once() 函数,添加一个一次性的 Handlers 去监听下一次满足 pattern 的消息。当监听到该消息后,resume 这里的代码并继续运行。

PS:Handlers.once() 也是 aos2.0 的新特性,后面会介绍到。

  1. pattern 是匹配模式,相当于之前添加 Handlers 时的第二个参数,如Handlers.add('balance', Handlers.utils.hasMatchingTag("Action", "Balance"), function(msg) { ... }) 。相较于之前的参数,pattern 更为灵活。当然 Handlers.add 中也已经支持了这个 pattern 的方式。目前,可以有以下三种入参:
  • string:aos 会去自动匹配 Action 这个 Tag
  • table:aos 会把 table 中的 key 和 value 拆分开,分别去匹配 message 中所有的 Tag。其中 value 可以是一个 lua match expression,可以更方便的匹配 Tag 的内容。
  • function:这个方式就和之前的一模一样了

更符合语义的 REQ / RESP

案例

当前要介绍的新功能其实是对上述功能的扩展。大家都知道,AO 是基于 Actor Model 构建的。不同 Actor 之间的通讯,依靠的是消息的发送与接收。因此,Receive(pattern) 方法其实是与 AO 的设计浑然天成的。所以 aos 2.0 中就赋予了 message 两个内置的函数:receive 和 replay。

message.receive()

AOS 2.0 都有哪些让人兴奋的更新(附 Demo)

如上面的代码,我们就可以根据 message 中内置的 receive() 方式实现了 Receive(pattern) 的功能,不需要自己再去写 pattern,是不是就好像 RPC 请求一样方便。在上面例子中我们拿到了查询的余额以后,就可以执行应该有的业务逻辑。代码看起来就相当的丝滑了。

同样的,spawn 一个进程后,也可以通过 local msg = Spawn(ao.env.Module.Id, {}).receive() 获取创建进程后的消息。

PS:对于旧的进程是无法进行这样的操作的。原因是 receive() 方法中是根据 Reference 这个 Tag 去查找返回的消息是否为需要回复接收的消息。而在之前旧的进程中,并没有 Reference 这个 Tag。但是 Receive(pattern) 依旧可以用的,需要自己构建 pattern 过滤出下一条消息为自己需要处理的消息。但是笔者建议,最好都升级下进程的 aos 版本。

AOS 2.0 都有哪些让人兴奋的更新(附 Demo)

message.replay({...})

AOS 2.0 都有哪些让人兴奋的更新(附 Demo)

reply 方法则简单很多,更像是一个语法糖。上面的例子是 blue-print 中 token.lua 根据 aos 2.0 进行的改造。原来 msg.reply 是一个 ao.send 方法,但是在参数列表中少了 Target 这个参数。相当于开发者可以不用再关系 msg 的发送者,reply 函数会自动找到应该回复消息的进程。

message.forward({...})

forward 方法是一个消息转发的工具方法。以下引用一个官方的例子,更容易理解。

进程 C 向进程 B 发送了一条消息,进程 B 在 Handler 中转发给了 A,并修改了其中的 Data 的值。同样的,进程 A 也在 Handler 中转发给了 C,也修改了 Data 的值。

如果在没有 forward 的时候,我们则需要构建一个完整的消息体,把所有值都赋值到新的消息体中。现在可以完全的省略这些操作。所有需要转发的字段,都会按照标准的格式转发。

AOS 2.0 都有哪些让人兴奋的更新(附 Demo)

Handler 升级

aos 2.0 中的 Handler 含有 4 个参数,aos 2.0 之前是 3 个参数。

名称 类型 说明
name string Handlers 本质上是一个 lua 的 table,因此 name就是在 Handlers 中唯一标识该 Handler 的 key
pattern string table
handle function 消息处理函数,主要的业务逻辑
MaxRuns number (optional) 当前 Handler 最多运行几次。

这里需要扩展讲下 pattern、handle 和 MaxRuns,因为这三个参数是 aos 2.0 升级的内容。另外,还有一些其他功能的升级。

  1. 其中 pattern 其实跟 Receive(pattern) 中的 pattern 是一致的。在 aos 2.0 之前,代码如下:

AOS 2.0 都有哪些让人兴奋的更新(附 Demo)

即 function (msg) return msg.Action == "Balance" 是判断收到的消息是否匹配当前 Handler。在 aos 2.0 之后的 pattern 就更加的灵活,由于前面提到过 Receive(pattern) 中的 pattern。因此,此处就不再赘述。

  1. MaxRuns:该参数为可选参数,如果不输入 MaxRuns,则表示当前 Handler 可以无限次执行。也就是和 aos 2.0 之前的 Handler 一致。如果输入了,则当当前 Handler 达到运行次数后,会从 Handlers 中删除该 Handler。
  2. 之前在 Receive(pattern) 这一部分讲到的 Handlers.once(),其实就是内置的一个函数,把 MaxRuns设置为 1 的 Handlers.add(...)。
  3. Handler 中新增了 Resolvers 用法。Resolvers 用法可以让你的代码看起来更加的整洁,减少大段的 if - else 结构。下面看个官方的例子,添加如下的 Handler

AOS 2.0 都有哪些让人兴奋的更新(附 Demo)

那么如果我如下发送消息的时候,则会有以下的返回。显而易见的是,不需要在 handle function 中对 Status 进行值的判断。Handler 中会自动匹配到当前消息中 Status 的值,所对应的函数。

AOS 2.0 都有哪些让人兴奋的更新(附 Demo)

其他更新

  1. 现在所有的消息都需要 Authority Tag,通过 aos 2.0 发送的消息都会默认带有 fcoN_xJeisVsPXA-trzVAuIiqO3ydLQxM-L4XbrQKzY 这个地址作为 Authority Tag

  2. os.time 终于可以使用了。他是根据接收到的 message 中的 Timestamp 去更新 os.time 的数值。

  3. aos 加了新的命令行,后续创建一个 sqlite process 不需要再去记住 sqlite module id 了,直接输入 aos --sqlite 就可以了。

  4. 在 .editor 中输入代码的时候,如果不小心输入错了一行,那么在 aos 2.0 之前只能通过 .cancel 重头再来。现在可以通过 .delete 删除上一行错误代码。不用再重新来过啦。

非 AOS 2.0 的一些重要更新

  • APM,全称是 AO package management。很多扩展包可以通过 apm 进行加载,就比如加载最近 AO 上大火的大模型。如下代码所示,AOS 2.0 都有哪些让人兴奋的更新(附 Demo)
  • DbAdmin 是 aos 的核心开发者提供的一个操作 sqlite 的工具类。直接通过 .load 加载该文件会出现内存溢出的错误。正确的引入方法如下,需要先下载 DbAdmin.lua 的代码,放在自己的项目工程中。然后在需要操作 sqlite 的文件中 require("DbAdmin")。

友情链接:https://github.com/twilson63/aos-packages/blob/main/packages/db-admin/src/DbAdmin.lua

AOS 2.0 都有哪些让人兴奋的更新(附 Demo)

结尾

强大的 aos 2.0 给开发者带来了开发效率的巨大提示。但是由于 ao 与 aos 发展的非常快,相关的文档不能说是很完善(尤其是中文文档)影响了生态接入的速度。大家有什么想法欢迎沟通交流,一起完善生态。

PS:aos 2.0 的不少通讯方法,在使用的时候,需要通讯方法的进程都是 aos 2.0 的版本才能生效。笔者建议,构建项目的时候需要统一版本,并且最好用 aos 2.0 直接创建的 process,而不是升级上来的 process。可以避免很多不必要的坑。