[elixir! #0012] 漫话源码之Agent

news/2024/2/29 3:33:31

我们知道 Elixir 有一个从 Erlang 那里继承来的重要特性 —— immutable, 所以我们不能像 OO语言那样简单地用变量存储临时数据. 因此, Agent 出现了.

Agent 是关于 state 的简单抽象. state 可以解释为数据的某个状态. 在 Elixir 里经常需要在不同进程之间, 或者是同一个进程在不同的时间点, 分享或存储 state.

Agent 是一个基础的服务器实现, 它提供了简单的 API, 帮助我们对 state 进行获取与更新.

所有传送给 agent 的函数都会在 agent 里执行. 所以要避免在 agent 中进行昂贵的操作.

对比这两个例子:

# Compute in the agent/server
def get_something(agent) doAgent.get(agent, fn state -> do_something_expensive(state) end)
end# Compute in the agent/client
def get_something(agent) doAgent.get(agent, &(&1)) |> do_something_expensive()
end

第一个例子阻塞了 agent, 第二个例子将所有的 state 复制到客户端执行. 选择哪种方式取决于数据的大小, 是否大到需要在服务器执行, 或是小到可以传送到客户端.

agent 提供了两种 API, 一种是匿名函数, 另一种是确定的模块函数和参数. 使用分布式 agent 的时候最好选择后者.

agent 可以热更新代码, 只需要简单地传送一个模块,函数和参数的元组到更新命令里. 例如:

{:update, :sample, {:advanced, {Enum, :into, [%{}]}}}

agent 的 state 会被当做第一个参数添加到参数列表里.

Agent 模块里的主要函数

@spec start_link((() -> term), GenServer.options) :: on_start
@spec start_link(module, atom, [any], GenServer.options) :: on_start
启动一个包含了给定的函数, 链接到当前进程的 agent.

@spec start((() -> term), GenServer.options) :: on_start
@spec start(module, atom, [any], GenServer.options) :: on_start
启动一个没有链接的 agent. (在监督树之外)

@spec get(agent, (state -> a), timeout) :: a when a: var
@spec get(agent, module, atom, [term], timeout) :: any
通过给定的函数获取 agent 的值.

@spec get_and_update(agent, (state -> {a, state}), timeout) :: a when a: var
@spec get_and_update(agent, module, atom, [term], timeout) :: any
获取并更新 agent state.

@spec update(agent, (state -> state), timeout) :: :ok
@spec update(agent, module, atom, [term], timeout) :: :ok
更新 agent state.

@spec cast(agent, (state -> state)) :: :ok
@spec cast(agent, module, atom, [term]) :: :ok
在 agent state 中执行一个 cast 操作.

@spec stop(agent, reason :: term, timeout) :: :ok
以给定的原因关闭 agent.


https://www.jiucaihua.cn/news/show-1298421.html

相关文章

迭代流程_什么时候应该从迭代过渡到流程?

迭代流程我正在写程序管理书的一部分,讨论如何保持所有小东西以保持动力。 有时,为了保持工作量小,团队从迭代过渡到流程。 在某些情况下,您可能会考虑从迭代过渡到流程: 产品负责人出于商业原因希望在迭代中更改功能…

微信小程序选择题制作_制作较小故事的三种选择

微信小程序选择题制作几周前我在以色列教研班时,人们遇到的最大问题之一就是大故事。 为什么这是一个问题? 如果您的故事很大,则无法显示进度,更重要的是,您无法进行更改。 对我来说,敏捷的重点是透明度-嘿…

另类的ip地址伪装折腾记

收到这样一个需求:在现有结构不变的情况下,让被访问方看起来是很多物理地址在同时请求。为了便于大家理解,我画个图来描述,就明白了。新的业务规定是这样,见下图这样一来,就没有中间那个“业务处理服务器”…

scrum_Scrum适​​合您的产品吗?

scrumScrum何时最有帮助? 当您的产品是新产品或年轻产品时,以及延长产品生命周期时,像Scrum这样的过程非常适合您的产品,如下图所示。 这意味着并非每种产品都会从Scrum中受益:成熟或下降的产品不会从Scrum中受益-至少…

[android] 手机卫士项目

按照模块组织代码的包结构;各个模块之间的业务是独立的 风行网 ----播放器 com.funshion.android.player ----下载模块 com.funshion.android.download ----联网 com.funshion.android.network 按照类型组织代码的包结构 -----界面 com.tsh.activity -----自定义…

敏捷领导力_成为敏捷领导者,第2部分:与谁接触

敏捷领导力总结一下:您的敏捷转换被困住了。 您已经考虑了自己的原因,就像成为敏捷领导者一样,第1部分:定义原因 。 您对测量有一些想法。 也许您甚至已经开始测量以捕获数据。 现在,是时候与组织中的所有人交谈。 问…

基于云计算的商业智能

2019独角兽企业重金招聘Python工程师标准>>> 商业智能(BI,Business Intelligence)是一个从海量数据中发现潜在的、新颖的、有用的知识,用以支持组织的业务运作和管理决策的过程,海量的数据是商业智能提供服务的基础,对…

C 笔记

C 笔记 、 posted on 2016-04-04 23:03 秦瑞It行程实录 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/ruiy/p/5353302.html

JDBC连接不同数据库(从基础来了解耦合)

JDBC连接不同数据库的实现步骤:一、在Myeclipse或者Eclipse中新建JavaProject,命名:JDBCTest;二、在src目录下新建类:JDBC.java,同时输入包名:com.jdbc,同时在src目录下新建 …

PHP_008 命名空间

2019独角兽企业重金招聘Python工程师标准>>> 命名空间(namespace) PHP 命名空间(namespace)是在PHP 5.3中加入的。 PHP 命名空间可以解决以下两类问题: 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。为很长的标识符名称(通…