Skip to content

[REFAC#393] validate worker + cmd/processor Kafka I/O → publisher facade - #408

Merged
juhy0987 merged 2 commits into
mainfrom
refactor/#393/publisher-validate
May 13, 2026
Merged

juhy0987 merged 2 commits into
mainfrom
refactor/#393/publisher-validate

Conversation

@juhy0987

@juhy0987 juhy0987 commented May 13, 2026

Copy link
Copy Markdown
Member

연관 이슈

Closes #393
부모 메타: #385 — Publisher 통합 Sub 8 (마지막)

구현 내용

validate worker 의 Kafka I/O 책임을 publisher facade 로 위임. Sub 5 (#390) / Sub 7 (#392) 와 동일 패턴 — 같은 추상화 (publisher.Consumer / Forward) 를 마지막 stage 인 validate 에도 일관 적용.

validate worker 변경

Before After
consumer queue.Consumer consumer publisher.Consumer (alias)
producer queue.Producer pub *publisher.Publisher
4종 w.producer.Publish(...) w.pub.Forward(...)
NewWorker(consumer, producer, ...) NewWorker(consumer, pub, ...)

4 publish 사이트:

cmd/issuetracker/main.go wiring

 validateProducer := queue.NewProducer(validateKafkaCfg)
 defer validateProducer.Close()
+validatePublisher := publisher.New(validateProducer, nil, log)

-validateWorker := validate.NewWorker(validateConsumer, validateProducer, ...)
+validateWorker := validate.NewWorker(validateConsumer, validatePublisher, ...)

validate 는 resolver / guard 불필요 (Forward 전용) — publisher.New(producer, nil, log) 로 thin wrap. crawlerProducer 와는 GroupID 가 다른 별개 producer 유지 (GroupValidators).

cmd/processor/main.go (validator 단독 entry) wiring

 producer := queue.NewProducer(kafkaCfg)
 defer producer.Close()
+pub := publisher.New(producer, nil, log)

-worker := validate.NewWorker(consumer, producer, ...)
+worker := validate.NewWorker(consumer, pub, ...)

테스트

  • test/internal/processor/validate/worker_test.go newTestPublisher(producer) 헬퍼 도입 (Sub 5/7 의 동일 패턴).
  • newWorker 헬퍼 + 4 개 reparse_test 케이스 모두 newTestPublisher(producer) 래핑.
  • 검증 로직 / DLQ 분기 / reparse trigger 검증 무변경 — pub.Forward 가 producer.Publish 위임이라 mockProducer expectations 그대로 작동.

CI / 머지 게이트 점검

  • gofmt -l internal/ cmd/ test/ — clean
  • go build ./internal/... ./cmd/issuetracker/ ./cmd/processor/ ./test/... — pass
  • go test -race -count=1 -timeout=180s ./test/internal/processor/validate/... ./test/internal/publisher/... + 관련 — 전 패키지 통과
  • PR 타이틀 [REFAC#393]
  • commit [REFAC]: prefix + 한국어

변경 영향 범위 + 위험도

  • 영향: validate/worker + cmd/issuetracker + cmd/processor + 2 test 파일
  • 위험도 Medium → 동작 동등성 확보됨:
    • publisher.Forward 는 thin pass-through (Sub 5/7 동일 검증)
    • 라이브 publish 시점/내용 무변경
    • 양 entry point (통합 / 단독) 동일 wiring 패턴 — 정합성 유지

후속

Sub 8 머지 후 메타 #385 의 남은 sub:

Sub 6 까지 머지되면 메타 #385 close 가능.

롤백 계획

PR revert 시 모든 시그니처가 동시에 원복 — wiring 회귀 없음.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
    • Updated internal publisher architecture to use a facade pattern, improving abstraction and decoupling from specific messaging infrastructure details. Processing behavior, performance, and user-facing functionality remain unchanged.

Review Change Stack

… (이슈 #393)

메타 #385 Sub 8 — validate worker 의 Kafka I/O 책임을 publisher facade 로 위임. 동일
패턴을 cmd/issuetracker + cmd/processor 양쪽 entry point 에 wiring 일관 적용.

## validate worker

- 필드 `consumer queue.Consumer` → `consumer publisher.Consumer` (별칭)
- 필드 `producer queue.Producer` → `pub *publisher.Publisher`
- 4 종 직접 publish 모두 `w.pub.Forward(...)` 위임:
  - TopicValidated publish (검증 통과 → downstream)
  - TopicDLQ publish (검증 실패 라우팅)
  - TopicNormalized publish (재큐잉)
  - reparse publish (validator → parser 재학습 trigger, #366)
- NewWorker 시그니처: consumer + producer → consumer + pub

## cmd/issuetracker/main.go

- `validateProducer` 직접 주입 → `publisher.New(validateProducer, nil, log)` 로 thin wrap
- validate 는 resolver / guard 불필요 — Forward 전용이라 nil resolver 로 충분
- crawlerProducer 와는 다른 producer 유지 (validateKafkaCfg.GroupID = GroupValidators 분리)

## cmd/processor/main.go (validator 단독 entry)

- 동일 패턴: `publisher.New(producer, nil, log)` → validate.NewWorker 에 pub 전달

## 테스트

- `test/.../validate/worker_test.go` `newTestPublisher(producer)` 헬퍼 도입 (Sub 5/7 동일 패턴)
- `newWorker` 헬퍼 + 4 개 reparse 테스트 모두 `newTestPublisher(producer)` 래핑
- 검증 로직 / DLQ 분기 / reparse trigger 무변경 — pub.Forward 가 producer.Publish 위임이라
  기존 mockProducer expectations 그대로 작동

## 검증

- `go build ./internal/... ./cmd/issuetracker/ ./cmd/processor/ ./test/...` — pass
- `go test -race -count=1 -timeout=180s ./test/internal/processor/validate/... + 관련` — 전 패키지 통과

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 13, 2026 03:26
@juhy0987 juhy0987 added the refactor Code refactoring label May 13, 2026
@coderabbitai

coderabbitai Bot commented May 13, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@juhy0987 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 56 minutes and 51 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a5f40575-ad77-4d46-afc3-1b048ea3e9c5

📥 Commits

Reviewing files that changed from the base of the PR and between 7024a85 and 52c4962.

📒 Files selected for processing (1)
  • internal/processor/validate/worker.go
📝 Walkthrough

Walkthrough

This PR refactors the validate worker to accept a publisher facade instead of a raw Kafka producer. The worker's constructor and struct are updated to take publisher.Consumer and *publisher.Publisher. All outbound publishing operations use publisher.Forward() instead of queue.Producer.Publish(). Both command entry points (issuetracker and processor) are updated to wire the publisher facade accordingly, and tests are updated to use a publisher wrapper.

Changes

Publisher Facade Integration

Layer / File(s) Summary
Validate worker publisher contract and constructor
internal/processor/validate/worker.go
Worker struct and constructor are updated to accept publisher.Consumer and *publisher.Publisher instead of queue.Consumer and queue.Producer. The publisher package import is added.
Publishing paths via publisher facade
internal/processor/validate/worker.go
All four message publishing methods (publishValidatedRef, sendToDLQ, requeue, republishForReparse) are updated to use w.pub.Forward(...) instead of w.producer.Publish(...). Context cancellation drain-timeout retry behavior is preserved.
Test publisher wrapper helper
test/internal/processor/validate/worker_test.go
The publisher import is added and newTestPublisher(producer) helper is introduced to wrap a queue.Producer mock inside a *publisher.Publisher for test injection.
Reparse test updates with publisher wrapper
test/internal/processor/validate/reparse_test.go
Four reparse tests are updated to pass newTestPublisher(producer) into validate.NewWorker instead of the raw producer.
Issuetracker entry point publisher wiring
cmd/issuetracker/main.go
A validatePublisher facade is constructed using publisher.New(validateProducer, nil, log) and passed to validate.NewWorker instead of the raw validateProducer.
Processor entry point publisher wiring
cmd/processor/main.go
The publisher import is added. A publisher facade is constructed using publisher.New(producer, nil, log) and passed to validate.NewWorker. Comments are updated to reflect publisher facade usage with nil resolver.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • EinSofINTEREST/IssueTracker#393: This PR directly implements the refactor objective—migrate validate worker Kafka I/O from direct queue.Producer/Consumer to the publisher facade, updating both issuetracker and processor wiring.
  • EinSofINTEREST/IssueTracker#385: Parent issue; this PR is a sub-task completing the validate worker's transition to the publisher facade as part of the larger publisher-integration work.

Possibly related PRs

  • EinSofINTEREST/IssueTracker#400: Both PRs refactor worker components to delegate Kafka I/O to the publisher facade, applying the same publisher-delegation pattern across multiple workers.

Suggested labels

refactor

Poem

📚 A rabbit refactors with joy and care,
Trading Kafka producers for facades fair,
Publishers now orchestrate the flow,
Workers publish less, delegation's the show,
Cleaner contracts, simpler to know! 🐰

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: refactoring the validate worker and cmd/processor to use the publisher facade for Kafka I/O instead of direct producer/consumer usage.
Linked Issues check ✅ Passed The PR meets all coding objectives from issue #393: validate worker now uses publisher facade (consumer/pub fields updated), all four publish operations route through publisher.Forward(), NewWorker signature updated, cmd/issuetracker/processor wiring creates publisher.New() wrappers, validation logic preserved, and tests updated with newTestPublisher helper.
Out of Scope Changes check ✅ Passed All changes are directly scoped to #393 objectives: validate worker refactoring, command entry point wiring updates, and test fixture modifications. No unrelated code modifications or features outside the publisher facade migration are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/#393/publisher-validate

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/processor/validate/worker.go (1)

61-75: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail fast when pub is nil in NewWorker

pub is now a pointer dependency (Line 63) and is dereferenced in multiple paths; if a caller passes nil, processing panics at runtime. Add a constructor guard so failure is immediate and explicit.

Suggested fix
 func NewWorker(
 	consumer publisher.Consumer,
 	pub *publisher.Publisher,
 	contentSvc service.ContentService,
 	gate locks.StageGate,
 	workerCount int,
 	cfg config.ValidateConfig,
 ) *Worker {
+	if pub == nil {
+		panic("validate.NewWorker: pub must not be nil")
+	}
 	if gate == nil {
 		gate = locks.NewNoopStageGate()
 	}
 	return &Worker{
 		consumer:    consumer,
 		pub:         pub,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/processor/validate/worker.go` around lines 61 - 75, NewWorker
currently accepts pub *publisher.Publisher and dereferences it later; add a
fail-fast guard at the start of NewWorker to explicitly reject a nil pub
(similar to the existing gate nil handling) by checking if pub == nil and
panicking with a clear message like "publisher.Publisher is nil in NewWorker"
(or returning a wrapped error if you prefer to change the signature), so callers
get an immediate, descriptive failure instead of a downstream panic when methods
on pub are invoked; update the constructor body around NewWorker and the
returned *Worker to ensure tests and callers expect this explicit failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@internal/processor/validate/worker.go`:
- Around line 61-75: NewWorker currently accepts pub *publisher.Publisher and
dereferences it later; add a fail-fast guard at the start of NewWorker to
explicitly reject a nil pub (similar to the existing gate nil handling) by
checking if pub == nil and panicking with a clear message like
"publisher.Publisher is nil in NewWorker" (or returning a wrapped error if you
prefer to change the signature), so callers get an immediate, descriptive
failure instead of a downstream panic when methods on pub are invoked; update
the constructor body around NewWorker and the returned *Worker to ensure tests
and callers expect this explicit failure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2c799252-213f-4691-a055-bca480a62133

📥 Commits

Reviewing files that changed from the base of the PR and between 29da4f3 and 7024a85.

📒 Files selected for processing (5)
  • cmd/issuetracker/main.go
  • cmd/processor/main.go
  • internal/processor/validate/worker.go
  • test/internal/processor/validate/reparse_test.go
  • test/internal/processor/validate/worker_test.go

…bbit Major)

CodeRabbit 피드백:
- pub 은 4 publish 사이트 (validated / dlq / requeue / reparse) 가 dereference 하는 hard
  dependency. nil 주입 시 publisher.Forward 가 error 를 반환하지만, validate worker 가
  publish 실패 시 commit skip → Kafka 무한 재배달 → 운영 진단 어려움.
- NewWorker 생성 시점에 panic 으로 fail-fast — silent failure 보다 안전.
- 호출 site (cmd/issuetracker / cmd/processor / 테스트) 모두 이미 non-nil pub 주입 — 회귀 0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the validate.Worker to depend on the publisher.Publisher facade instead of the queue.Producer interface directly. This change decouples the worker from the underlying queue implementation and involves updating the Worker struct, its constructor, and all internal publishing calls to use the pub.Forward method. Entry points in cmd/issuetracker and cmd/processor have been updated to initialize the publisher facade, and test suites now utilize a newTestPublisher helper to wrap mock producers. I have no feedback to provide as no review comments were submitted.

@juhy0987 juhy0987 self-assigned this May 13, 2026
@juhy0987
juhy0987 merged commit d83bcbf into main May 13, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor Code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[REFACTOR] validate worker + cmd/processor Kafka I/O → publisher facade (#385 Sub 8)

2 participants