음, 결국 일이 벌어졌네요. retort 플러그인 때문에 discourse를 업데이트할 수 없었습니다.
다음과 같은 데이터베이스 마이그레이션 오류가 발생했습니다:
could not create unique index "index_post_details_on_post_id_and_key_ccnew_ccnew" DETAIL: Key (post_id, key)=(30297, +1|retort) is duplicated.
저는 이 스크립트를 기반으로 자체 마이그레이션 코드를 작성했습니다. 제가 수행한 작업은 다음과 같습니다.
- discourse를 다시 작동시키기 위해 템플릿 .yml 파일의 "version"을 discourse 저장소에서 약 2주 전 커밋으로 덮어써야 했습니다.
- reactions 플러그인을 추가하여 사이트를 다시 빌드하여 복구했습니다.
- reactions 플러그인을 retort와 동일한 리액션 세트로 구성했습니다. '좋아요’로 해석될 수 있는 리액션은 사용하지 않았습니다.
- @mcdanlj의 스크립트를 약간 수정하여 다음 단계들을 따랐습니다 (모든 retort를 마이그레이션하고 싶었으며, retort와 리액션 사이에 이미 1:1 매핑이 있었기 때문):
./launcher enter app실행rails c실행- 아래 코드를 붙여넣으세요 (rails 콘솔이 잘못된 줄바꿈으로 코드를 다시 출력하는 것 같습니다. 이중 줄바꿈을 추가했지만 출력에는 큰 차이가 없었습니다. 만약 아래 코드에서 구문 오류가 발생하면 각 줄 뒤에 한 줄을 더 추가하세요):
def migrateRetortToReactions()
retort = "retort".freeze
emojiType = "emoji".freeze
usermap = Hash.new { |hash, username| hash[username] = User.find_by_username(username) }
postmap = Hash.new { |hash, post_id| hash[post_id] = Post.find(post_id) }
likeType = PostActionType.where(name_key: "like").pluck(:id).first
PostDetail.where(extra: retort).each do |pd|
begin
p = postmap[pd.post_id]
rescue
# PostDetail not consistent WRT delete
$stderr.puts sprintf("Could not find post for %d: %s / %s", pd.post_id, pd.key, pd.value)
next
end
emoji = pd.key.split('|').first
users = JSON.parse(pd.value)
users.each do |user|
u = usermap[user]
next if u.nil? # changed user name or deleted user leaves orphaned Retorts
e = emoji
r = DiscourseReactions::Reaction.where(post_id: p.id, reaction_type: emojiType, reaction_value: e).first_or_create
ru = DiscourseReactions::ReactionUser.where(user_id: u.id, post_id: p.id).first
next unless ru.nil?
$stderr.puts sprintf("Converting Retort %s to Reaction %s for user %s in %s", emoji, e, user, p.url)
DiscourseReactions::ReactionUser.create(reaction_id: r.id, user_id: u.id, post_id: p.id, created_at: pd.created_at)
end
end
end
- 이 시점에서 혹시 모르도록 사이트 백업을 만들었습니다.
- 그런 다음
migrateRetortToReactions를 실행하세요. 시간이 좀 걸릴 수 있습니다. 제 경우엔 문제를 보거나 겪지 않았습니다. 실행 후 콘솔에 변경된 모든 객체가 표시되는 것 같으니q를 눌러 종료하세요. - 이제 사이트에서 데이터가 올바르게 마이그레이션되었어야 합니다.
- 마지막 단계로
PostDetail.where(extra: "retort").destroy_all을 실행하여 retort 데이터를 삭제해야 합니다. - 이제 최신 discourse 버전으로 retort 플러그인 없이 사이트를 다시 빌드할 수 있었습니다.
결국 마이그레이션은 그렇게 어렵지 않았지만 꽤 무서웠습니다. 그리고 이전에 논의했듯이, 같은 사용자가 좋아요와 retort를 모두 달았던 게시물에서는 리액션이 좋아요를 덮어쓰게 됩니다.