This commit is contained in:
2026-04-13 08:14:09 +03:00
commit 0449337ae7
39 changed files with 2726 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
package main
func main() {
_, _ = InitializeEventBus()
}
+98
View File
@@ -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)
}
+32
View File
@@ -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
}