Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 向插件提供并发落锁 API #1204

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

MintCider
Copy link
Contributor

尽管海豹的 jsvm 的事件循环是单线程的,js 内部的变量无需考虑并发数据竞争。然而,涉及使用 storageGetstorageSet 读写外部数据时,仍然存在数据竞争的可能。

因此,向插件提供并发落锁 API 以解决此问题。

@@ -80,6 +80,9 @@ type ExtInfo struct {
// 为Storage使用互斥锁,并根据ID佬的说法修改为合适的名称
dbMu sync.Mutex `yaml:"-"` // 互斥锁
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

此处的dbMu是否已经实现此 pr ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

让我看看

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个好像是用来处理插件数据库初始化/关闭时的并发问题的

Copy link
Contributor

@Szzrain Szzrain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

另,我的想法是不添加新的函数,而是保证 storageGetstorageSet 的并发安全性,以避免增加开发成本

@MintCider
Copy link
Contributor Author

MintCider commented Jan 31, 2025

另,我的想法是不添加新的函数,而是保证 storageGetstorageSet 的并发安全性,以避免增加开发成本

我觉得这是几乎不可实现的。

storageGet(*1) -> *1 yield -> storageGet(*2) -> storageSet(*1) -> storageSet(*2)

这种情况下数据竞争必然发生。

理论上可以在通过「进行异步调用之后(比如 fetch)直接完成 get/set,而不要把 get 放在异步调用之前」来解决这个问题,但实际上我 这样修改 并没有奏效……


也可能是我对 JS 和 jsvm 的理解还是有问题

@Szzrain
Copy link
Contributor

Szzrain commented Jan 31, 2025

另,我的想法是不添加新的函数,而是保证 storageGetstorageSet 的并发安全性,以避免增加开发成本

我觉得这是几乎不可实现的。

storageGet(*1) -> *1 yield -> storageGet(*2) -> storageSet(*1) -> storageSet(*2)

这种情况下数据竞争必然发生。

理论上可以在通过「进行异步调用之后(比如 fetch)直接完成 get/set,而不要把 get 放在异步调用之前」来解决这个问题,但实际上我 这样修改 并没有奏效……

我注意到在 这里 你的每次 onNotCommandReceived 都会重新从数据库中读取 history,考虑到插件数据库没有 append 方法,而每次存储操作只能是全量存储。你可以考虑维护一个constant map,插件中的 storageGet 只在插件初始化时调用一次,而插件主体逻辑数据读取依赖于内存中的map,对于数据库的操作是“只存不读”

@Szzrain
Copy link
Contributor

Szzrain commented Jan 31, 2025

这里提供一个我的解决方案(AGPL 协议注意)https://github.com/Szzrain/sealdice-Enhanced-DnD/blob/master/src/io/io_helper.ts

@MintCider
Copy link
Contributor Author

另,我的想法是不添加新的函数,而是保证 storageGetstorageSet 的并发安全性,以避免增加开发成本

我觉得这是几乎不可实现的。

storageGet(*1) -> *1 yield -> storageGet(*2) -> storageSet(*1) -> storageSet(*2)

这种情况下数据竞争必然发生。
理论上可以在通过「进行异步调用之后(比如 fetch)直接完成 get/set,而不要把 get 放在异步调用之前」来解决这个问题,但实际上我 这样修改 并没有奏效……

你可以考虑维护一个constant map,插件中的 storageGet 只在插件初始化时调用一次,而插件主体逻辑数据读取依赖于内存中的map,对于数据库的操作是“只存不读”

非常好思路,使我插件旋转(我去试试喵)

非常坏海豹 API 😤

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants