import
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
_, _ = InitializeEventBus()
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package main
|
||||
|
||||
// Это упрощённый граф зависимостей с циклом.
|
||||
// Та самая ситуация из антипаттерна: продакт попросил чтобы EventBus
|
||||
// сам доставлял уведомления через NotificationService.
|
||||
//
|
||||
// Цепочка:
|
||||
// EventBus → NotificationService → UserService → AuthService → EventBus
|
||||
// ↑ ЦИКЛ
|
||||
//
|
||||
// Wire не сможет это сгенерировать. Запустите:
|
||||
// task generate-wire-broken
|
||||
// и увидите ошибку.
|
||||
|
||||
import "log/slog"
|
||||
|
||||
// === Интерфейсы (consumer-defined) ===
|
||||
|
||||
// NotificationSender — то что EventBus хочет от NotificationService.
|
||||
type NotificationSender interface {
|
||||
Send(msg string)
|
||||
}
|
||||
|
||||
// EventPublisher — то что AuthService хочет от EventBus.
|
||||
type EventPublisher interface {
|
||||
Publish(event string)
|
||||
}
|
||||
|
||||
// EventSubscriber — то что NotificationService хочет от EventBus.
|
||||
type EventSubscriber interface {
|
||||
Subscribe(event string, handler func())
|
||||
}
|
||||
|
||||
// Auth — то что UserService хочет от AuthService.
|
||||
type Auth interface {
|
||||
Validate(token string) bool
|
||||
}
|
||||
|
||||
// Users — то что NotificationService хочет от UserService.
|
||||
type Users interface {
|
||||
GetEmail(userID int) string
|
||||
}
|
||||
|
||||
// === Реализации ===
|
||||
|
||||
// EventBus — шина событий, которая САМА доставляет уведомления.
|
||||
// Вот эта зависимость на NotificationSender создаёт цикл.
|
||||
type EventBus struct {
|
||||
notifications NotificationSender
|
||||
}
|
||||
|
||||
func NewEventBus(notifications NotificationSender) *EventBus {
|
||||
slog.Info("шина событий создана")
|
||||
return &EventBus{notifications: notifications}
|
||||
}
|
||||
|
||||
func (b *EventBus) Publish(event string) {}
|
||||
func (b *EventBus) Subscribe(event string, handler func()) {}
|
||||
|
||||
// AuthService — сервис авторизации. Зависит от EventBus для публикации событий.
|
||||
type AuthService struct {
|
||||
events EventPublisher
|
||||
}
|
||||
|
||||
func NewAuthService(events EventPublisher) *AuthService {
|
||||
slog.Info("сервис авторизации создан")
|
||||
return &AuthService{events: events}
|
||||
}
|
||||
|
||||
func (s *AuthService) Validate(token string) bool { return true }
|
||||
|
||||
// UserService — сервис пользователей. Зависит от AuthService.
|
||||
type UserService struct {
|
||||
auth Auth
|
||||
}
|
||||
|
||||
func NewUserService(auth Auth) *UserService {
|
||||
slog.Info("сервис пользователей создан")
|
||||
return &UserService{auth: auth}
|
||||
}
|
||||
|
||||
func (s *UserService) GetEmail(userID int) string { return "user@example.com" }
|
||||
|
||||
// NotificationService — сервис уведомлений.
|
||||
// Зависит от UserService и EventBus (для подписки на события).
|
||||
type NotificationService struct {
|
||||
users Users
|
||||
events EventSubscriber
|
||||
}
|
||||
|
||||
func NewNotificationService(users Users, events EventSubscriber) *NotificationService {
|
||||
slog.Info("сервис уведомлений создан")
|
||||
return &NotificationService{users: users, events: events}
|
||||
}
|
||||
|
||||
func (s *NotificationService) Send(msg string) {
|
||||
slog.Info("уведомление отправлено", "msg", msg)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
//go:build wireinject
|
||||
|
||||
package main
|
||||
|
||||
import "github.com/google/wire"
|
||||
|
||||
// InitializeEventBus — попытка собрать граф с циклической зависимостью.
|
||||
//
|
||||
// EventBus → NotificationService → UserService → AuthService → EventBus
|
||||
//
|
||||
// Wire сделает топологическую сортировку, обнаружит цикл и упадёт.
|
||||
// Ленивой инициализации нет — Wire должен знать порядок создания заранее.
|
||||
// А при цикле порядка не существует.
|
||||
//
|
||||
// Запустите: task generate-wire-broken
|
||||
// Результат: "cycle for *EventBus"
|
||||
func InitializeEventBus() (*EventBus, error) {
|
||||
wire.Build(
|
||||
NewEventBus,
|
||||
NewAuthService,
|
||||
NewUserService,
|
||||
NewNotificationService,
|
||||
|
||||
wire.Bind(new(NotificationSender), new(*NotificationService)),
|
||||
wire.Bind(new(EventPublisher), new(*EventBus)),
|
||||
wire.Bind(new(EventSubscriber), new(*EventBus)),
|
||||
wire.Bind(new(Auth), new(*AuthService)),
|
||||
wire.Bind(new(Users), new(*UserService)),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
Reference in New Issue
Block a user