docker_manager 플러그인에 rake 태스크를 추가하고 있는데, 태스크를 호출할 때 두 번 실행되는 문제를 겪고 있습니다. 가장 간단한 형태로 lib/tasks에 testing.rake 파일을 다음 내용으로 추가할 수 있습니다:
# frozen_string_literal: true
desc "A test"
task "docker_manager:test do
puts "test"
end
이 경우 다음과 같은 결과가 나옵니다:
/var/www/discourse# rake docker_manager:test --trace
** Invoke docker_manager:test (first_time)
** Execute docker_manager:test
test
test
poll 플러그인에 동일한 rake 파일을 추가하여 테스트해 본 결과, 플러그인의 태스크에 대한 일반적인 문제는 아닌 것을 확인했습니다. 그 결과는 다음과 같습니다:
/var/www/discourse# mv plugins/docker_manager/lib/tasks/testing.rake plugins/poll/lib/tasks/
/var/www/discourse# rake docker_manager:test --trace
** Invoke docker_manager:test (first_time)
** Execute docker_manager:test
test
아직 두 플러그인 중 이 문제를 방지하거나 유발할 수 있는 명확한 원인을 찾지 못했습니다. 따라서 poll에서는 이를 방지하는 요인이나 docker_manager에서는 이를 유발하는 요인이 무엇일 수 있는지 조언을 구하고자 합니다.
이 문제를 해결하셨나요?
저도 비슷한 문제를 겪고 있습니다:
플러그인에서 rake 태스크를 생성한다고 가정해 보겠습니다. 예를 들어 lib/tasks/test.rake 파일에 다음과 같은 내용을 넣으면:
desc "count posts"
task "test_rake:test" => :environment do
puts "Number of posts on this forum is #{Post.count}"
end
그리고 rake test_rake:test를 실행하면,
출력이 제게는 놀랍습니다:
Number of posts on this forum is 366
Number of posts on this forum is 366
Number of posts on this forum is 366
저는 분명 어떤 오류를 범하고 있는 것 같은데, 그게 무엇인지 모르겠습니다.
왜 이 태스크가 여러 번 실행되는 것이며, 어떻게 이를 방지할 수 있을까요?
프로덕션 환경에서도 비슷한 문제가 발생하는데, 이는 당연히 더 심각한 우려 사항입니다.
좋아요, 초기화 블록에서 해당 태스크를 로드하는 것을 _제거_함으로써 태스크가 두 번만 실행되도록 줄이는 데 성공했습니다. 사실 /lib/tasks에 단순히 넣어두기만 하면 별도로 로드할 필요가 없는 것 같습니다.
이로 인해 반복이 1회로 줄었습니다(총 2회로!)
Number of posts on this forum is 366
Number of posts on this forum is 366
이것은 OP의 경험과 동일한 현상을 반복하는 것입니다.
Robert:
이 문제를 해결하셨나요?
아쉽게도 해결하지 못했습니다. 처음에는 코어(core)의 어떤 부분이 두 번 로드되도록 만드는 줄로 착각했지만, 폴(poll) 플러그인에 추가했을 때 한 번만 실행되는 것을 보고 그 가설은 기각되었습니다.
이제는 거의 잊어버렸지만, --trace 옵션을 사용해도 한 번만 로드되는 것으로 표시된 것 같습니다. 제 기억이 정확하다면, 두 번 로드된다면 invoke 및/또는 execute 줄이 두 번 나타나야 합니다.
docker_manager와 poll 또는 코어 사이에 이 동작 차이를 설명할 수 있는 차이를 찾지 못했고, 게시글을 작성할 시점에는 사실상 포기한 상태였습니다.
manut
(Manuel Tancoigne)
2월 24, 2025, 10:31오전
5
조금 늦게 합류하는 것 같습니다
새 플러그인에서 동일한 문제를 겪고 있고, 조금 찾아봤습니다. 이 문제는 다른 플러그인에도 영향을 미치는 것 같습니다(예: 공식 채팅 플러그인). 하지만 태스크가 여러 번 등록되는 것을 방지하는 작동하는 해결책을 찾았습니다:
# 이전 등록 내용 삭제
task('import_json:preview').clear
# 태스크 정의
desc 'import_json에 의해 적용될 변경 사항을 미리 보여줍니다'
task 'import_json:preview', [:file_path] => :environment do |_task, args|
puts "Hello world!"
end
태스크 설명 이후 에 clear를 호출하면 rake --tasks로 태스크가 목록에 표시되지 않으므로, 그 전에 clear를 실행해야 합니다.
이것은 해당 플러그인에 태스크를 추가했을 때 동일한 결과가 나온다는 뜻인가요, 아니면 플러그인에 이미 존재하는 태스크가 이러한 동작을 보이는 것인가요?
정보 주셔서 감사합니다! 이를 지워야 한다는 점은 다소 해킹처럼 느껴지지만, 분명 유용한 우회책입니다.
다른 사용자들의 편의를 위해 해당 게시물을 해결책으로 표시하겠습니다. 근본적인 원인이 여전히 파악될 수 있기를 바랍니다. 그렇다면 질문은 다음과 같이 변할 것 같습니다: 왜 일부 플러그인에서는 태스크가 두 번 등록되고 다른 플러그인에서는 그렇지 않은가요?
manut
(Manuel Tancoigne)
2월 26, 2025, 2:46오후
7
작업을 추가했을 때 동일한 결과가 나오는 건지, 아니면 플러그인에 이미 존재하는 작업이 이러한 동작을 보이는 건지 묻는 건가요?
내가 개발한 플러그인의 작업이 두 번 실행되는 이유를 파악하기 위해 Chat 플러그인의 기존 작업을 테스트해 봤는데, 이 역시 두 번 실행되었습니다.
다른 플러그인의 작업들도 몇 가지 테스트해 봤지만 어떤 것이었는지 기억나지 않습니다. 일부는 한 번만 실행되었는데, 구현 방식의 차이가 명확하게 드러나지 않았습니다.
아마도 자동 로딩(autoloading)과 관련이 있는 것일까요?
새로운 플러그인에서는 엔진에 다음과 같은 줄이 포함되어 있습니다:
config.autoload_paths << File.join(config.root, "lib")
lib/tasks가 자동 로딩되지 않도록 lib 대신 lib/some_path를 자동 로딩 대상으로 지정하면 상황이 나아지는 것 같지만, 단점은 자동 로딩이 깨진다는 것입니다(여기서 멈췄습니다). 이로 인해 상쇄하기 위해 require_relative 문이 많이 필요할 수 있습니다…
Manuel Tancoigne:
자동 로딩(autoloading)과 관련이 있을 수도 있겠네요.
새 플러그인에서 엔진에는 이 줄이 포함되어 있습니다:
config.autoload_paths << File.join(config.root, "lib")
이미 작업을 로드하는 메커니즘이 있다면, 이로 인해 작업이 두 번째로 로드될 수 있다는 추측은 상당히 타당해 보입니다.
다음 중 하나를 사용하면 이 문제를 해결할 수 있을지 궁금합니다(자동 로딩을 한 번만 수행할 때 발생할 수 있는 부작용을 알 수 없으므로 후자를 선호할 것 같습니다):
config.autoload_once_paths << File.join(config.root, "lib")
config.autoload_lib(ignore: %w( tasks ))