elixir - 用于提供重复条目的字符串的自定义自动递增字段
问题描述
我目前正在开发一个应用程序,该应用程序要求在系统中注册的每个学生在注册时都有一个唯一的注册号,每次注册都会自动递增。2019年注册的第一个学生的注册号格式为“01/19”,第890个学生的注册号格式为“890/19”等。
注册数据是从kobo 数据收集 工具上传的,因此它会在非常短的时间间隔内到达我的端点,因为一次可以完成近 200 次提交。
我意识到在 1000 条记录中,有近 27 个重复的注册号。这就是我实现注册号生成逻辑的方式
def registration_changeset(student, attrs) do
student |> changeset(attrs) |> Accounts.add_registration_number()
end
然后 Accounts 上下文具有以下用于添加注册号的代码
def add_registration_number(changeset) do
struct = changeset.data.__struct__
registration_number =
case struct |> last() |> Repo.one() do
nil -> _create_new_registration_number()
resource -> _increment_registration(resource.registration_number)
end
put_change(changeset, :registration_number, registration_number)
end
在上述情况下,我打赌最后创建的学生将拥有最新的注册号
有没有更好的方法来实现这一点?
解决方案
您在这里需要一些同步代码:)
创建一个专用流程,服务于单一目的:产生数字。GenServer.handle_call/3
已经做了你需要的任何事情,进程邮箱是完美的队列,OTP 会为你做一切。
defmodule MyApp.RegNumHelper do
@moduledoc false
use GenServer
def start_link(opts),
do: GenServer.start_link(__MODULE__, opts, name: name)
def add_registration_number(changeset),
do: GenServer.call(__MODULE__, {:reg_num, changeset})
@impl true
def init(opts), do: {:ok, opts}
@impl true
def handle_call({:reg_num, changeset}, _from, state) do
# your logic assigning changeset
{:reply, changeset, state}
end
end
这种方法还有另一个优点:由于该过程已经是有状态的,因此您实际上不需要每次都查询数据库。只需在进程开始时查询它并将当前数字保存到state
.
推荐阅读
- react-native - 在反应导航中管理多个导航器(堆栈导航器和底部标签导航器)
- javascript - 如何获取特定复选框的位置编号
- python - 使用 Python scrapy 时错误的图像 src url
- excel - 在word中使用vba将文本添加到excel单元格
- blazor - 在 Blazor 中滚动时延迟加载下拉项目
- date - 将纪元时间转换为时间戳颤动
- elasticsearch - ElasticSearch 查找给定单词最常用的单词
- google-app-engine - 谷歌云应用引擎错误 502 Bad Gateway 上带有 django rest 后端的 Angular 前端
- javascript - 尝试从表中获取数据时出错
- java - github上的Java代码覆盖工具,无需在本地机器上运行