今天也在 GitHub 搜 Koishi,搜到了这个 这个看起来也不是官方发的,但是感觉好好玩 就转载过来了
然后我感觉这篇文章里讲的东西有很多其实是不合理或者难以实现的 所以只是图一乐
今天也在 GitHub 搜 Koishi,搜到了这个 这个看起来也不是官方发的,但是感觉好好玩 就转载过来了
然后我感觉这篇文章里讲的东西有很多其实是不合理或者难以实现的 所以只是图一乐
这篇文章描述了 Koishi 插件设计模式中「零占用的 Koishi」部分的相关内容和实现方法。我们鼓励开发者在编写插件时遵守该模式。
零占用的 Koishi 是指,给定一个正在运行的 Koishi 实例,移除该实例项目目录下的所有内容,实例应按照预期的方式保持工作。
此处的「保持工作」是指,实例内的所有模块,包括 Koishi 本体及所有插件,均在设计时对此情况做了考虑,并编写了相应的处理逻辑。如:
koishi.yml
文件。但在启动后删除该文件,Koishi 保持工作。实现了「零占用的 Koishi」模式的 Koishi 项目将会获得以下优点:
可以编写插件更新 Koishi 及其依赖。在更新依赖的整个过程中,Koishi 及所有插件仍保持可用。
现已有 market 插件实现。
文件的暂时无法访问不会导致 Koishi 停止运行。这对项目文件夹使用网络映射的场景更友好。
可以先升级项目文件夹,然后滚动更新 Koishi。这将极大地提高 Koishi 的高可用性(并未实现「高可用(HA)」)。
下列功能依赖此模式工作:
截至当前,Koishi 本体已实现此模式,Koishi 插件市场内的绝大多数插件也均实现了此模式。下面仅列举一些未实现此模式的情况:
此外,一些现已实现了此模式的插件也曾经未实现此模式,如:
一个 Koishi 插件要想实现「零占用的 Koishi」模式,只需要保证不占用项目目录内的任何内容。
作为一般情况,只要插件不使用项目文件夹内的任何文件,那么该插件就已自动实现了此模式。
实现「零占用的 Koishi」模式需要同时满足两点:不依赖 和 不占用 项目目录内的文件。
要避免对项目目录内文件的依赖,有以下三种途径实现:
如果依赖的文件体积较小,则可以在插件启动时预先读取文件的全部内容到内存。文件体积较大时不建议采用此途径。
可以缓存热点文件,使文件在硬盘上缺失时仍能命中缓存。
作为一种兜底的途径,可以在文件缺失时将可读的错误提示输出到用户侧或日志。
避免占用的场景和方法在各类型的插件之间有较大的不同,下面列举几个典型的插件作为常见场景的代表进行说明。
gocqhttp 是 Koishi 插件市场中广受好评的插件之一,也是少有的被包含在 Koishi 模板项目中的非官方插件。gocqhttp 插件实现了此模式。实现使用以下四步:
node_modules
下面的自身的包(此处即为 koishi-plugin-gocqhttp
)的名称下的 go-cqhttp
二进制文件的以对应版本为名称的目录下是否存在所需文件(如果目录不存在则创建),没有的话开始下载此文件;在此期间插件无法使用,日志输出警告;HOME
下面的包名下的 go-cqhttp
二进制文件的以对应版本为名称的目录下是否存在所需文件(如果目录不存在则创建),没有的话将 node_modules
中的同文件复制过去;在此期间插件无法使用,日志输出警告apply
函数内检测 HOME
下面的包名下的 go-cqhttp
二进制文件的以对应版本为名称的目录下是否存在所需文件(如果目录不存在则创建),没有的话将 node_modules
中的同文件复制过去;在此期间插件无法使用,日志输出警告HOME
下面的包名下的 go-cqhttp
二进制文件的以对应版本为名称的目录下的 go-cqhttp
二进制文件。作为 Koishi 插件市场内评分最低而被安装次数和安装失败次数均居高位的不安全插件,petpet 足够作为典型进行分析和实现。
petpet 未实现此模式的原因是它依赖了 sharp,这也是它被列为不安全插件的原因。sharp 是一个 Node.js 的图像处理库,它使用 Node 的 Addon 功能实现了 JS 封装层与 C++ 实现层的互操作,以期实现 Node.js 平台的高效图像处理。然而 Node Addon 文件(.node
文件)只要加载便会被占用,由于 node-gyp 将此文件输出到包目录下,因此造成了项目目录中的文件占用。
petpet 实现此模式的方法和 gocqhttp 基本相同,然而以下两点需要注意:
const xxx = require('xxx')
)模式,即使在 TypeScript 中也是如此。另外,在 ESM 中,对应的加载模式变更为 Dynamic Import,因此使用了 const-require 模式的代码将无法对多目标模块模式进行转译,即使是在 TypeScript 中也是如此。「零占用的 Koishi」模式目前仍存在以下缺陷:
「可预期的重载」是指,Koishi 在收到项目文件变更请求后,预先卸载可能受到影响的插件并要求插件释放占用的文件。插件必须在卸载时释放文件。
该方案将会带来较大的 downtime,且实现成本相较「零占用的 Koishi」模式更高。Koishi 已经实现了「零占用的 Koishi」模式的一部分,没有必要再切换到其他方案。
如上文所述,Koishi 的热重载功能和完全重载功能均依赖此设计模式工作。但热重载功能本身是 Koishi 的自有逻辑,与此模式无关。
你将可能遇到以下两种情况:
node_modules
以外,Koishi 桌面的实例管理功能(克隆和重命名等)将会失败。node_modules
内,market 进行的任何依赖更改都将失败。此种情况下你的插件将应该被标记为不安全。指定有限个数的目录用于逃逸,其本质仍然是限制了开发者随意使用项目目录内任何文件的权力,与本设计模式没有区别,也不会使开发成本降低。
特别地,网络上的一些社区约定了使用某个位于项目文件夹外的特定目录作为逃逸目录,可以参考此链接:
参考链接没挂上,想看看
我也想知道链接 不过 GitHub 上的原文就是没有链接的 很怪
好文[紫薯布丁]