[WIP] [PoC] '&' -> '&mut' #777
无评审员
标签
未选择标签
A: API
A: Backend
A: Federation
A: Front-End
A: I18N
A: Meta
A: Security
Build
C: Bug
C: Discussion
C: Enhancement
C: Feature
Compatibility
Dependency
Design
Documentation
Good first issue
Help welcome
Mobile
Rendering
S: Blocked
S: Duplicate
S: Incomplete
S: Instance specific
S: Invalid
S: Needs Voting/Discussion
S: Ready for review
Suggestion
S: Voted on Loomio
S: Wontfix
未选择里程碑
暂无项目
未指派成员
2 位参与者
通知
到期时间
未设置到期时间。
依赖工单
没有设置依赖项。
引用:Plume/Plume#777
正在加载…
添加表格
在新工单中引用
没有提供说明。
删除分支 "igalic/go/async-all-mut"
删除分支是永久的。虽然已删除的分支在实际被删除前有可能会短时间存在,但这在大多数情况下无法撤销。是否继续?
This is a (incomplete) proof of concept of a possible workaround for
Sync
issues that appear inasync
code.Roughly, the issue is this:
Send
. This requirement comes from Rocket, and would be nontrivial and/or undesirable to change in Rocket.&PlumeRocket
or an&Connection
held across anawait
point&PlumeRocket
/&Connection
must beSend
&T: Send
iffT: Sync
, soPlumeRocket
/Connection
must beSync
PlumeRocket
contains aConnection
, andConnection
contains a dieselPgConnection
, which is notSync
.The approach demonstrated here is to change every
&PlumeRocket
or&Connection
to an&mut PlumeRocket
or&mut Connection
.&mut T
isSend
ifT
isSend
, so the problem is eliminated:Send
.&mut PlumeRocket
or an&mut Connection
held across anawait
point&mut PlumeRocket
/&mut Connection
must beSend
&mut T: Send
iffT: Send
, soPlumeRocket
/Connection
must beSend
PlumeRocket
contains aConnection
, andConnection
contains a dieselPgConnection
, which isSend
.Downsides
&PlumeRocket
could allow more work to be done in parallel, at least in the future. It does not look like that is currently the case, since every call to the database blocks anyway.FromId
andInbox
. I know relatively little about the overall structure of this code, so this could be incorrect or inconvenient in ways I don't know about!&
->&mut
change. A different solution that keeps&
in more places would be easier to work with overall.async
fns, which can cause issues ranging from degraded performance to deadlocks.Alternatives
Mutex
around theConnection
somewhere. Uncontended mutexes (which this one should be) are not a huge performance concern, butMutex
may be at least as or more unwieldy than this solution throughout the code.Connection
with an API likeconn.run(|c| Post::load(&c)).await
, whererun
handles the synchronization. This has similar tradeoffs to aMutex
, is probably the most inconvenient option in terms of overall code changes, and is also a significant chunk of new code to write and debug. However, it has the advantage of being capable of fixing the blocking-in-async
-fn problem.I think the best way to handle sql connections would be to have worker threads that are basically dedicated to that, and have a mpsc channel through which requests can be send to them, alongside a one shot channel that allow to return a result.
This is basically how actors work (like in Erlang and derivative, or the Actix lib for Rust), it would allow to keep
&
, would properly handle blocking operation out of async context, and maybe allow to compile both Postgresql and Sqlite in the same binary (however this would also be a lot of work, not that much new code, but lots of moving things around)Yeah, I think that's more or less the direction I was going with "wrap
Connection
with an API likeconn.run(|c| Post::load(&c)).await
". I agree that it's a nicer overall solution, with the biggest drawback being:🤷♀️
we have come this far, we might as well do it right.
查看命令行说明
检出
从你的仓库中检出一个新的分支并测试变更。合并
合并更改并在 Forgejo 上更新。警告:未启用此仓库的“自动检测手动合并”设置,您之后必须将此合并请求标记为手动合并。