AOS 2.0 发布更新已经一周时间了。这次更新可谓是研发者的福音,尤其是其中的消息等待机制,让开发者不用再陷入繁杂的异步调用网络中。那么接下来让我们一睹为快吧!
作者: txohyeah
审阅:outprog
来源:内容公会 - 新闻
如果你需要新创建一个 aos 2.0 的进程,那么需要更新本地的 aos 包,命令如下
npm i -g https://preview_ao.g8way.io
如果是过去已经创建的进程,那么需要在更新本地的 aos 到 2.0 以后,再连接上进程后,运行.update命令。如下图,升级完成后,aos 给出的 prompt 有如下变化,就是升级成功了。
本次升级最主要包含 3 个功能的升级:
简单的说这个方法就是 aos 中的 await 方法。这也是官方的解释:the await of aos.
相信这样解释各位开发人员已经能很好理解了,我也不做过多解释。直接看个例子:
aos2.0@aos-2.0.0.rc2[Inbox:2]> .editor
<editor mode> use '.done' to submit or '.cancel' to cancel
Send({Target = LlamaCoinProcessId, Action = "Balance", Tags = { Target = ao.id }})
local res = Receive({From = LlamaCoinProcessId})
print(res.Data)
.done
=========== print result ==============
0
上面简单的三行代码,就可以避免之前把逻辑散落各处的 Handler 的写法。可以让开发者逻辑更清晰,代码可以被更好的阅读。
PS:Handlers.once() 也是 aos2.0 的新特性,后面会介绍到。
当前要介绍的新功能其实是对上述功能的扩展。大家都知道,AO 是基于 Actor Model 构建的。不同 Actor 之间的通讯,依靠的是消息的发送与接收。因此,Receive(pattern) 方法其实是与 AO 的设计浑然天成的。所以 aos 2.0 中就赋予了 message 两个内置的函数:receive 和 replay。
aos2.0@aos-2.0.0.rc2[Inbox:6]> .editor
<editor mode> use '.done' to submit or '.cancel' to cancel
local bal = Send({Target = TestToken, Action = "Balance"}).receive().Data
print("bal: " .. bal)
.done
=========== print result ==============
bal: 0
如上面的代码,我们就可以根据 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 版本。
Handlers.add('info', "Info", function(msg)
msg.reply({
Name = Name,
Ticker = Ticker,
Logo = Logo,
Denomination = tostring(Denomination)
})
end)
reply 方法则简单很多,更像是一个语法糖。上面的例子是 blue-print 中 token.lua 根据 aos 2.0 进行的改造。原来 msg.reply 是一个 ao.send 方法,但是在参数列表中少了 Target 这个参数。相当于开发者可以不用再关系 msg 的发送者,reply 函数会自动找到应该回复消息的进程。
forward 方法是一个消息转发的工具方法。以下引用一个官方的例子,更容易理解。
进程 C 向进程 B 发送了一条消息,进程 B 在 Handler 中转发给了 A,并修改了其中的 Data 的值。同样的,进程 A 也在 Handler 中转发给了 C,也修改了 Data 的值。
如果在没有 forward 的时候,我们则需要构建一个完整的消息体,把所有值都赋值到新的消息体中。现在可以完全的省略这些操作。所有需要转发的字段,都会按照标准的格式转发。
-- 进程 A
Handlers.add("Greeting", "Greeting", function (msg)
msg.forward(msg['X-Origin'], { Data = msg.Data .. " Squarepants"})
end)
-- 进程 B
local process_a_id = "Process A id"
Handlers.add("Greeting", "Greeting", function (msg)
msg.forward(process_a_id , { Data = "Hello " .. msg.Data })
end)
-- 进程 C
local process_b_id = "Process B id"
local res = Send({Target = process_b_id, Action = "Greeting", Data = "SpongeBob"}).receive("Process A id")
print(res.Data)
aos 2.0 中的 Handler 含有 4 个参数,aos 2.0 之前是 3 个参数。
名称 | 类型 | 说明 | ||
---|---|---|---|---|
name | string | Handlers 本质上是一个 lua 的 table,因此 name就是在 Handlers 中唯一标识该 Handler 的 key | ||
pattern | string | table | function | 收到的消息是否匹配当前 Handler |
handle | function | 消息处理函数,主要的业务逻辑 | ||
MaxRuns | number (optional) | 当前 Handler 最多运行几次。 |
这里需要扩展讲下 pattern、handle 和 MaxRuns,因为这三个参数是 aos 2.0 升级的内容。另外,还有一些其他功能的升级。
Handlers.add("Get-Balance", function (msg) return msg.Action == "Balance", doBalance)
即 function (msg) return msg.Action == "Balance" 是判断收到的消息是否匹配当前 Handler。在 aos 2.0 之后的 pattern 就更加的灵活,由于前面提到过 Receive(pattern) 中的 pattern。因此,此处就不再赘述。
Handlers.add("foobarbaz", { Action = "Update" }, {
[{ Status = "foo" }] = function (msg) print("foo") end,
[{ Status = "bar" }] = function (msg) print("bar") end,
[{ Status = "baz" }] = function (msg) print("baz") end
})
那么如果我如下发送消息的时候,则会有以下的返回。显而易见的是,不需要在 handle function 中对 Status 进行值的判断。Handler 中会自动匹配到当前消息中 Status 的值,所对应的函数。
aos2.0@aos-2.0.0.rc2[Inbox:6]> Send({Target = ao.id, Action = "Update", Tags = { Status = "foo"} })
{
receive = function: 0x29bc5e0,
onReply = function: 0x29bc480,
output = "Message added to outbox"
}
=========== print result ==============
foo
现在所有的消息都需要 Authority Tag,通过 aos 2.0 发送的消息都会默认带有 fcoN_xJeisVsPXA-trzVAuIiqO3ydLQxM-L4XbrQKzY 这个地址作为 Authority Tag
os.time 终于可以使用了。他是根据接收到的 message 中的 Timestamp 去更新 os.time 的数值。
aos 加了新的命令行,后续创建一个 sqlite process 不需要再去记住 sqlite module id 了,直接输入 aos --sqlite 就可以了。
在 .editor 中输入代码的时候,如果不小心输入错了一行,那么在 aos 2.0 之前只能通过 .cancel 重头再来。现在可以通过 .delete 删除上一行错误代码。不用再重新来过啦。
-- Install APM
aos> .load-blueprint apm
-- Loading... apm
-- 📦 Loaded APM Client
-- Update APM
aos> APM.update()
-- 📤 Update request sent
-- ℹ Attempting to load client 1.1.0
-- 📦 Loaded APM Client
-- ✨ Client has been updated to 1.1.0
-- Install Llama-Herder
aos> APM.install("@sam/Llama-Herder")
友情链接:https://github.com/twilson63/aos-packages/blob/main/packages/db-admin/src/DbAdmin.lua
local sqlite3 = require("lsqlite3")
local dbAdmin = require("DbAdmin")
-- Open the database
local db = sqlite3.open_memory()
-- Create a new dbAdmin instance
DbAdmin = dbAdmin.new(db)
-- to use DbAdmin
print(DbAdmin:tables())
强大的 aos 2.0 给开发者带来了开发效率的巨大提示。但是由于 ao 与 aos 发展的非常快,相关的文档不能说是很完善(尤其是中文文档)影响了生态接入的速度。大家有什么想法欢迎沟通交流,一起完善生态。
PS:aos 2.0 的不少通讯方法,在使用的时候,需要通讯方法的进程都是 aos 2.0 的版本才能生效。笔者建议,构建项目的时候需要统一版本,并且最好用 aos 2.0 直接创建的 process,而不是升级上来的 process。可以避免很多不必要的坑。
免责声明:本文不代表 PermaDAO 的观点或立场。PermaDAO 不提供投资建议,亦不为任何项目背书。请读者遵守所在国法律,合规进行 Web3 活动。
🔗 关于 PermaDAO:Website | Twitter | Telegram | Discord | Medium | Youtube
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!