今天我尝试将我的 Discourse 安装从 2.9.0.beta9 升级到 2.9.0.beta10。但这次升级出了大问题。
我的第一次尝试是在控制台上
cd /var/discourse
sudo git pull
sudo ./launcher rebuild app
最后以这个消息中断,日志中间有这样的信息:
PG::InvalidParameterValue: ERROR: cannot extract elements from a scalar
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:110:in `exec'
我通过启动旧的镜像(它仍然存在)成功地恢复了论坛。
我的第二次尝试是通过 Web 控制台(/admin/upgrade)。但最后也因为同样的错误而中断:ERROR: cannot extract elements from a scalar。当我回到升级面板时,它告诉我所有组件都已成功更新。但在容器重启后,服务器现在抛出了一个 HTTP 500 错误
我在一台单独的机器上进行了干净安装,从头开始。我能够安装 beta10 版本,但尝试从备份恢复时出现了完全相同的错误!
有谁能提供帮助吗?
我找到了导致它卡住的查询
INSERT INTO question_answer_votes (post_id, user_id, created_at)
SELECT
X.post_id AS post_id,
(X.value->>'user_id')::int AS user_id,
(X.value->>'created_at')::timestamp AS created_at
FROM (
SELECT
post_id,
jsonb_array_elements(value::jsonb) AS value
FROM post_custom_fields WHERE name = 'vote_history'
) AS X
WHERE (X.value->>'action') != 'destroy'
ORDER BY (X.value->>'created_at')::timestamp DESC
ON CONFLICT DO NOTHING
如果我的理解没错的话,这是因为 psql 函数 jsonb_array_elements 期望接收一个数组,但却收到了一个 NULL 值。
已经有几份关于此的报告:
I am trying to rebuild one (forum.techandtiny.com ) of three Discourse instances that I run on my server. The crazy part is the plugins used are identical to the two other instances (forum.tabletpc.review and forum.farfarawaynews.com ) that I run on my server. However, in updating all three instances today, only this one fails to spin up after rebuilding. Attached is the terminal output.
Unable to install Discourse Question Answer
== 20211020062413 CreateQuestionAnswerVotes: migrating ========================
-- create_table(:question_answer_votes, {})
-> 0.0478s
-- add_index(:question_answer_votes, [:post_id, :user_id], {:unique=>true})
-> 0.0024s
-- execute("INSERT INTO question_answer_votes (post_id, user_id, created_at)\nSELECT\n X.post_id AS post_id,\n (X.value->>'user_id')::int AS user_id,\n (X.value->>'created_at')::timestamp AS created_at\nFROM (\n SELECT\n …
我认为这可能与之前安装了 Pavilion Question/Answer 插件有关?
我会找人深入研究一下。
我们正在使用这个插件:https://github.com/angusmcleod/discourse-question-answer。
它似乎与 Pavilion Question and Answer 插件有关。
它是 discourse/discourse-upvotes 插件的一个分支。
为了确认一下,您的 app.yml 中有哪些插件?
pfaffman
(Jay Pfaffman)
2022 年10 月 6 日 10:44
9
我看到的网站上有很多自定义帖子字段,其中包含许多经过多次编码的字符串,导致它们无法使用。
一些解决方案,按复杂程度排序:
停止使用该插件(并可能切换到新的“赞成票”)
删除所有这些字段
删除不好的字段
编辑这些字段,将数据恢复为有效的 JSON 字符串。
我看到的网站上有几年前的错误数据。这似乎是一个多年前存在的错误,现在才被发现。
可能可以编写代码来修复损坏的 JSON 字符串,但我花了 10 分钟也未能弄清楚如何做到这一点。
请参阅 Question Answer Plugin - #301 by pfaffman 获取示例。
nat
(Natalie T)
2022 年10 月 6 日 10:57
10
Jay Pfaffman:
停止使用该插件(也许可以切换到新的点赞功能)
我也这么想过,但快速查看了 Angus 的分支,似乎没有进行任何数据迁移。 https://github.com/angusmcleod/discourse-question-answer/compare/main...discourse:discourse-upvotes:main
正如你所说,这感觉像是旧的问答帖造成的数据污染。我也觉得奇怪的是,这现在才出现,考虑到这次迁移是 2021 年 11 月的——我猜是因为 JayJay 现在才切换到新插件?无论如何,我们会再次查看这次迁移。
- git clone https://github.com/discourse/docker_manager.git
- git clone https://github.com/discourse/discourse-solved.git
- git clone https://github.com/unfoldingWord-dev/discourse-mermaid.git
- git clone https://github.com/angusmcleod/discourse-question-answer.git
- git clone https://github.com/discourse/discourse-checklist.git
- git clone https://github.com/discourse/discourse-cakeday.git
- git clone https://github.com/discourse/discourse-canned-replies.git
- git clone https://github.com/discourse/discourse-footnote.git
- git clone https://github.com/discourse/discourse-staff-notes.git
- git clone https://github.com/discourse/discourse-graphviz.git
- git clone https://github.com/discourse/discourse-assign.git
- git clone https://github.com/discourse/discourse-voting.git
- git clone https://github.com/discourse/discourse-yearly-review.git
- git clone https://github.com/discourse/discourse-saved-searches.git
@nat 我根本不会切换到新插件。我仍然在使用我们已经使用了一段时间的插件集。
至少每个月,我们都会运行更新,所以版本之间不会有很大的差距。
除了问答问题之外,还有一个小小的“供您参考”的说明,现在还有一个可以替代预设回复的功能:
摘要
Discourse Templates 允许创建内容模板以供重复使用。这些模板作为主题存储在特殊类别中,可以根据需要进行编辑和讨论。
安装指南
该插件已捆绑在 Discourse 核心中。无需单独安装该插件。
该插件基本上是 Discourse Canned Replies 的新版本,但它更灵活,并以不同的方式存储模板。
功能
此插件使用一个或多个类别来存储模板以便稍后使用。这些类别中每个主题的第一篇文章将用作回复的模板。
这种方法提供了比之前 discourse-canned-replies 更多的功能,因为每个模板都会有编辑历史记录,可以关联标签,并且后续帖子可用于讨论模板内容(如果需要)。
只有可见的主题将用作模板,因此未列出和归档的主题将不会列出。
该插件还利用类别的安全设置来检查哪些用户可以使用模板。如果用户可以阅读类别中的主题,则编辑器中将提供“插入模板”选项。用户只能看到他们有权限访问的类别中的模板/主题。
可以使用多个父类…
而且我相信现在还有一个官方的 Mermaid 主题组件:
如果我移除该插件,恢复备份仍然会导致有问题的查询运行。
因此,我需要移除该插件以及该插件使用的任何表+查询。
我将如何知道涉及的表?
Stephen
(Stephen)
2022 年10 月 6 日 11:49
18
您是否已注释掉该插件的行并尝试重新构建以进行确认?
我马上就试试。我查看了备份中的 dump.sql 文件,里面根本没有提到任何 question_answer_* 表。这让我很乐观……
pfaffman
(Jay Pfaffman)
2022 年10 月 6 日 12:13
21
损坏的数据位于 PostCustmField 表中。但是,如果您没有该插件,它将不会尝试将这些数据迁移到新表中。
Natalie T:
无论如何,我们会再次查看这次迁移。
问题不在于迁移本身,而在于过去某个时候数据被损坏了。它已经损坏了,但损坏的方式多年来一直未被发现。我认为也许每一次新的点赞都会使其进一步损坏。一个合理的修复方法可能是忽略损坏的数据,也许将其标记为损坏(也许重命名自定义字段),以便将来的迁移可以忽略它,并且有人可以根据需要手动修复它们。
在生产环境中也成功了。禁用了插件,然后我们继续进行。
仍然想知道为什么我没有更早遇到这个问题。正如我所说,我们每个月都会例行更新所有系统,所以我应该更早地看到这个问题。
我如何能够自己连接到 Discourse 数据库,以验证 post_custom_fields 表中的内容?
angus
(Angus McLeod)
2022 年10 月 6 日 13:14
23
@Jaap-Jan_Swijnenburg 很抱歉您遇到了问题。
Jay Pfaffman:
迁移本身不是问题
我对此持不同意见
旧的 QnA 插件使用了 标准的 Discourse 自定义字段类型转换 ,该转换旨在将该字段转换为 JSON。但在某些情况下(例如此情况)不起作用,这就是为什么您(理想情况下)在处理 Discourse 自定义字段时需要进行格式检查(尤其是在处理像这样相当旧的代码和数据时)。我建议 Upvotes 插件在此处需要执行此操作,这确实是当前错误来源的地方。
您可以使用数据浏览器插件来检查您在那里有什么。
摘要
Discourse 数据资源管理器允许您对实时数据库执行 SQL 查询,从而实现实时统计报告。
安装指南
此插件已包含在 Discourse 核心中。无需单独安装该插件。
如果您正在寻找自定义查询的示例或支持,可以在我们的 #data-reporting 类别下查找带有 sql-query 标签的大量主题。如果没有适合您特定需求的内容,请随时创建新主题向社区寻求帮助。 查询帮助
由我们托管?此插件可在我们的商业版和企业版计划中使用。Data Explorer | Discourse - Civilized Discussion
安装插件后,前往 /admin/plugins。
[de1]
点击“设置”按钮,启用 data explorer enabled,然后返回并刷新页面。
此时,堆叠导航栏中应会出现一个名为“数据资源管理器”的选项卡。选择它,或前往 /admin/plugins/discours…
pfaffman
(Jay Pfaffman)
2022 年10 月 6 日 20:35
24
Angus McLeod:
我将尊重地与您在此处意见不合
好吧,我在这方面大多听从您的意见,而且我认为我们确实意见一致。我认为迁移在数据没有损坏的情况下是有效的,这一点是正确的。我们同意,如果数据损坏,它应该比现在更优雅地失败。
是的,但数据可能在几年前就已损坏(我熟悉的网站就是这种情况),但您没有注意到,因为它没有发生灾难性故障。我很确定它没有像预期的那样管理投票,但没有人注意到。
我会从 rails 进行,类似这样:
./launcher enter app
rails c
然后是这样的东西:
all_votes=PostCustomField.where(name: "vote_history")
likely_broken_votes=PostCustomField.where(name: "vote_history").where("value like '\\\"%'")
只查看 id 和数据:
all_votes.pluck(:id,:value)
获取一个 pcf:
pcf=PostCustomField.find(1234)
修复它
pcf.value='您真正想要的东西'
pcf.save
angus
(Angus McLeod)
2022 年10 月 7 日 09:38
28
这里发生的情况是这样的:
有些人在他们的 app.yml 文件中有一个非常旧版本的问答插件,其存储库 URL 中包含我的个人 GitHub 用户名。
我多年前已将 QnA 插件转移到 paviliondev。GitHub 会在存储库转移时重定向 URL,因此包含我个人用户名的旧 URL 仍然有效。
多年后,Pavilion 将 Question Answer 插件转移到了 Discourse。Discourse 最初保留了名称 discourse-question-answer。
几个月前,我创建了我自己的插件分支,托管在 discourse 中,当时它仍然被称为 discourse-question-answer。
那些拥有指向包含我的个人 GitHub 帐户的 QnA 插件的非常旧链接的人,现在正在克隆托管在 discourse 中、经过显著更新的 discourse-question-answer 的新分支。换句话说,一个非常旧的链接现在指向了一个新插件的分支。尽管已经过去了这么多年,我本应该预料到这一点,对此我感到抱歉。我已经删除了那个分支。
Discourse 将 discourse-question-answer 的名称更改为 discourse-upvotes。这个名称更改对您的情况 @Jaap-Jan_Swijnenburg 没有实质性影响,但这就是为什么您现在(意外地)克隆该存储库分支的原因。
discourse/discourse-upvotes(以前是 discourse-question-answer)中的迁移假定 post_custom_fields 中的 value 列是 JSON 类型安全的。
该插件在 angusmcleod/discourse-question-answer(多年前)时创建的旧数据,并未被 discourse/discourse 中的 HasCustomFields 关联保存为有效的 JSON。我猜测,这些数据可能是在添加 JSON 类型检查 4 年前 之前添加的(在边缘情况下,注册为 JSON 的自定义字段中仍然可能出现无效 JSON)。
因此
当那些在 app.yml 中拥有(过时多年的)angusmcleod/discourse-question-answer URL 的人在更新他们的 Discourse 时,会克隆插件的新版本中的迁移,迁移运行,并可能产生此错误。
有几种解决方案:
@Jaap-Jan_Swijnen元 ,在您的情况下,您只需要删除指向我旧 QnA 插件的引用,就可以重建您的站点。就是这样;仅此而已。看起来您已经做到了
可以更新 discourse/discourse-upvotes 插件的迁移,以处理 post_custom_fields 中 value 列中的非 JSON 值。
我想指出的是,2 也可以处理那些确实想从旧版 QnA 插件切换到 discourse-upvotes 的用户的情况。在这种情况下,迁移将运行,如果 post_custom_fields 的 value 列中的任何条目不是有效的 JSON,迁移将失败。