Skip to content

Commit 95f841b

Browse files
authored
Merge pull request #2 from Gerfey/v0.7.0
2 parents 0fb4328 + 839bfd7 commit 95f841b

38 files changed

+1557
-683
lines changed

README.md

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
[![Go Reference](https://pkg.go.dev/badge/github.com/Gerfey/messenger.svg)](https://pkg.go.dev/github.com/Gerfey/messenger)
88
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
99

10-
> ⚠️ `v0.6.0` is a pre-release version — feel free to test and report issues!
10+
> ⚠️ `v0.7.0` is a pre-release version — feel free to test and report issues!
1111
1212
> 📚 Full documentation available in the [GitHub Wiki](https://github.com/Gerfey/messenger/wiki/Documentation)
1313
@@ -25,7 +25,7 @@
2525
## 📦 Installation
2626
> Requires Go 1.24+
2727
```bash
28-
go get github.com/gerfey/messenger@v0.6.0
28+
go get github.com/gerfey/messenger@v0.7.0
2929
```
3030

3131
## 🚀 Quick Start
@@ -60,13 +60,6 @@ default_bus: default
6060

6161
buses:
6262
default: ~
63-
64-
transports:
65-
sync:
66-
dsn: "in-memory://"
67-
68-
routing:
69-
main.HelloMessage: sync
7063
```
7164
> 💡 If no transport is configured for a message, it will be executed synchronously by default (inline handler execution).
7265
@@ -75,7 +68,7 @@ routing:
7568
```go
7669
cfg, errConfig := config.LoadConfig("messenger.yaml")
7770
if errConfig != nil {
78-
l.Error("ERROR load config", "error", errConfig)
71+
fmt.Println("ERROR load config", "error", errConfig)
7972
return
8073
}
8174

@@ -88,8 +81,6 @@ go m.Run(ctx)
8881

8982
bus, _ := m.GetDefaultBus()
9083
_, _ = bus.Dispatch(ctx, &HelloMessage{Text: "World"})
91-
92-
time.Sleep(5 * time.Second)
9384
```
9485
9586
## 🔍 More Examples

README.ru.md

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
[![Go Reference](https://pkg.go.dev/badge/github.com/Gerfey/messenger.svg)](https://pkg.go.dev/github.com/Gerfey/messenger)
88
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
99

10-
> ⚠️ Версия `v0.6.0` — это пре-релиз. Тестируйте и сообщайте о багах!
10+
> ⚠️ Версия `v0.7.0` — это пре-релиз. Тестируйте и сообщайте о багах!
1111
1212
> 📚 Полная документация доступна на [GitHub Wiki](https://github.com/Gerfey/messenger/wiki/Documentation)
1313
@@ -27,7 +27,7 @@
2727
## 📦 Установка
2828
> Требуется Go версии **1.24+**
2929
```bash
30-
go get github.com/gerfey/messenger@v0.6.0
30+
go get github.com/gerfey/messenger@v0.7.0
3131
```
3232

3333
## 🚀 Быстрый старт
@@ -62,13 +62,6 @@ default_bus: default
6262

6363
buses:
6464
default: ~
65-
66-
transports:
67-
sync:
68-
dsn: "in-memory://"
69-
70-
routing:
71-
main.HelloMessage: sync
7265
```
7366
> 💡 Если транспорт для сообщения не указан — оно будет выполнено синхронно (inline).
7467
@@ -77,7 +70,7 @@ routing:
7770
```go
7871
cfg, errConfig := config.LoadConfig("messenger.yaml")
7972
if errConfig != nil {
80-
l.Error("ERROR load config", "error", errConfig)
73+
fmt.Println("ERROR load config", "error", errConfig)
8174
return
8275
}
8376

@@ -90,8 +83,6 @@ go m.Run(ctx)
9083

9184
bus, _ := m.GetDefaultBus()
9285
_, _ = bus.Dispatch(ctx, &HelloMessage{Text: "World"})
93-
94-
time.Sleep(5 * time.Second)
9586
```
9687
9788
## 🔍 Больше примеров

api/transport.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,35 @@ package api
22

33
import (
44
"context"
5+
"reflect"
56

67
"github.com/gerfey/messenger/config"
78
)
89

910
type Transport interface {
10-
Name() string
11-
Send(context.Context, Envelope) error
12-
Receive(context.Context, func(context.Context, Envelope) error) error
13-
}
14-
15-
type RetryableTransport interface {
16-
Transport
17-
Retry(context.Context, Envelope) error
11+
Sender
12+
Receiver
1813
}
1914

2015
type Sender interface {
16+
Name() string
2117
Send(context.Context, Envelope) error
2218
}
2319

2420
type Receiver interface {
2521
Receive(context.Context, func(context.Context, Envelope) error) error
2622
}
2723

28-
type TransportLocator interface {
29-
Register(string, Transport) error
30-
GetAllTransports() []Transport
31-
GetTransport(string) Transport
24+
type RetryableTransport interface {
25+
Transport
26+
Retry(context.Context, Envelope) error
27+
}
28+
29+
type SenderLocator interface {
30+
Register(string, Sender) error
31+
GetSenders(Envelope) []Sender
32+
RegisterMessageType(reflect.Type, []string)
33+
SetFallback([]string)
3234
}
3335

3436
type TransportFactory interface {

builder/builder.go

Lines changed: 102 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,15 @@ import (
2121
"github.com/gerfey/messenger/transport"
2222
"github.com/gerfey/messenger/transport/amqp"
2323
"github.com/gerfey/messenger/transport/inmemory"
24+
"github.com/gerfey/messenger/transport/sync"
2425
)
2526

2627
type Builder struct {
2728
cfg *config.MessengerConfig
2829
resolver api.TypeResolver
2930
transportFactory *transport.FactoryChain
3031
handlersLocator api.HandlerLocator
31-
transportLocator api.TransportLocator
32+
senderLocator api.SenderLocator
3233
middlewareLocator api.MiddlewareLocator
3334
busLocator api.BusLocator
3435
eventDispatcher api.EventDispatcher
@@ -38,19 +39,22 @@ type Builder struct {
3839
func NewBuilder(cfg *config.MessengerConfig, logger *slog.Logger) api.Builder {
3940
resolver := NewResolver()
4041

42+
busLocator := bus.NewLocator()
43+
4144
tf := transport.NewFactoryChain(
42-
amqp.NewTransportFactory(resolver, logger),
43-
inmemory.NewTransportFactory(resolver, logger),
45+
amqp.NewTransportFactory(logger, resolver),
46+
inmemory.NewTransportFactory(logger, resolver),
47+
sync.NewTransportFactory(logger, busLocator),
4448
)
4549

4650
return &Builder{
4751
cfg: cfg,
4852
resolver: resolver,
4953
transportFactory: tf,
5054
handlersLocator: handler.NewHandlerLocator(),
51-
transportLocator: transport.NewLocator(),
55+
senderLocator: transport.NewSenderLocator(),
5256
middlewareLocator: middleware.NewMiddlewareLocator(),
53-
busLocator: bus.NewLocator(),
57+
busLocator: busLocator,
5458
eventDispatcher: event.NewEventDispatcher(logger),
5559
logger: logger,
5660
}
@@ -91,25 +95,16 @@ func (b *Builder) RegisterListener(event any, listener any) {
9195
}
9296

9397
func (b *Builder) Build() (api.Messenger, error) {
94-
router := routing.NewRouter()
95-
for msgTypeStr, transportName := range b.cfg.Routing {
96-
t, err := b.handlersLocator.ResolveMessageType(msgTypeStr)
97-
if err != nil {
98-
return nil, fmt.Errorf("failed to resolve message type '%s' in routing configuration: %w", msgTypeStr, err)
99-
}
100-
router.RouteTypeTo(t, transportName)
101-
}
102-
10398
b.registerStamps()
10499

105-
if err := b.setupBuses(router); err != nil {
100+
if err := b.setupBuses(); err != nil {
106101
return nil, err
107102
}
108103

109-
return b.createMessenger(router)
104+
return b.createMessenger()
110105
}
111106

112-
func (b *Builder) setupBuses(router api.Router) error {
107+
func (b *Builder) setupBuses() error {
113108
for name, cfg := range b.cfg.Buses {
114109
var chain []api.Middleware
115110

@@ -124,9 +119,9 @@ func (b *Builder) setupBuses(router api.Router) error {
124119
chain = append(chain, implementation.NewAddBusNameMiddleware(name))
125120
chain = append(
126121
chain,
127-
implementation.NewSendMessageMiddleware(router, b.transportLocator, b.eventDispatcher, b.logger),
122+
implementation.NewSendMessageMiddleware(b.logger, b.senderLocator, b.eventDispatcher),
128123
)
129-
chain = append(chain, implementation.NewHandleMessageMiddleware(b.handlersLocator, b.logger))
124+
chain = append(chain, implementation.NewHandleMessageMiddleware(b.logger, b.handlersLocator))
130125

131126
createNewBus := bus.NewBus(chain...)
132127

@@ -139,7 +134,48 @@ func (b *Builder) setupBuses(router api.Router) error {
139134
return nil
140135
}
141136

142-
func (b *Builder) createMessenger(router api.Router) (api.Messenger, error) {
137+
func (b *Builder) createMessenger() (api.Messenger, error) {
138+
router, err := b.setupRouting()
139+
if err != nil {
140+
return nil, err
141+
}
142+
143+
busMap := b.createBusMap()
144+
handlerManager := b.createHandlerManager(busMap)
145+
manager := transport.NewManager(b.logger, handlerManager, b.eventDispatcher)
146+
147+
createdTransports, transportNames, err := b.createTransports(manager)
148+
if err != nil {
149+
return nil, err
150+
}
151+
152+
b.setupFallbackTransports(transportNames)
153+
b.setupRetryListeners(createdTransports)
154+
155+
defaultBus, ok := b.busLocator.Get(b.cfg.DefaultBus)
156+
if !ok {
157+
return nil, fmt.Errorf("default_bus %q not found", defaultBus)
158+
}
159+
160+
return messenger.NewMessenger(b.cfg.DefaultBus, manager, b.busLocator, router), nil
161+
}
162+
163+
func (b *Builder) setupRouting() (api.Router, error) {
164+
router := routing.NewRouter()
165+
166+
for msgTypeStr, transportName := range b.cfg.Routing {
167+
t, err := b.handlersLocator.ResolveMessageType(msgTypeStr)
168+
if err != nil {
169+
return nil, fmt.Errorf("failed to resolve message type '%s' in routing configuration: %w", msgTypeStr, err)
170+
}
171+
router.RouteTypeTo(t, transportName)
172+
b.senderLocator.RegisterMessageType(t, []string{transportName})
173+
}
174+
175+
return router, nil
176+
}
177+
178+
func (b *Builder) createBusMap() map[reflect.Type]string {
143179
busMap := make(map[reflect.Type]string)
144180
for _, h := range b.handlersLocator.GetAll() {
145181
busName := h.BusName
@@ -149,7 +185,11 @@ func (b *Builder) createMessenger(router api.Router) (api.Messenger, error) {
149185
busMap[h.InputType] = busName
150186
}
151187

152-
handlerManager := func(ctx context.Context, env api.Envelope) error {
188+
return busMap
189+
}
190+
191+
func (b *Builder) createHandlerManager(busMap map[reflect.Type]string) func(context.Context, api.Envelope) error {
192+
return func(ctx context.Context, env api.Envelope) error {
153193
msgType := reflect.TypeOf(env.Message())
154194
busName, ok := busMap[msgType]
155195
if !ok {
@@ -165,27 +205,47 @@ func (b *Builder) createMessenger(router api.Router) (api.Messenger, error) {
165205

166206
return err
167207
}
208+
}
168209

169-
manager := transport.NewManager(handlerManager, b.eventDispatcher, b.logger)
210+
func (b *Builder) createTransports(manager *transport.Manager) (map[string]api.Transport, []string, error) {
211+
var transportNames []string
212+
createdTransports := make(map[string]api.Transport)
213+
214+
b.createdSyncTransport(createdTransports)
170215

171216
for name, tCfg := range b.cfg.Transports {
172217
tr, err := b.transportFactory.CreateTransport(name, tCfg)
173218
if err != nil {
174-
return nil, fmt.Errorf("failed to create transport '%s': %w", name, err)
219+
return nil, nil, fmt.Errorf("failed to create transport '%s': %w", name, err)
175220
}
176221

222+
createdTransports[name] = tr
223+
}
224+
225+
for nameTransport, tr := range createdTransports {
177226
manager.AddTransport(tr)
227+
transportNames = append(transportNames, nameTransport)
178228

179-
errTransportLocator := b.transportLocator.Register(name, tr)
229+
errTransportLocator := b.senderLocator.Register(nameTransport, tr)
180230
if errTransportLocator != nil {
181-
return nil, fmt.Errorf("failed to register transport '%s': %w", name, errTransportLocator)
231+
return nil, nil, fmt.Errorf("failed to register transport '%s': %w", nameTransport, errTransportLocator)
182232
}
183233
}
184234

235+
return createdTransports, transportNames, nil
236+
}
237+
238+
func (b *Builder) setupFallbackTransports(transportNames []string) {
239+
if len(b.cfg.Routing) == 0 && len(transportNames) > 0 {
240+
b.senderLocator.SetFallback(transportNames)
241+
}
242+
}
243+
244+
func (b *Builder) setupRetryListeners(createdTransports map[string]api.Transport) {
185245
for name, tCfg := range b.cfg.Transports {
186-
tr := b.transportLocator.GetTransport(name)
246+
t := createdTransports[name]
187247

188-
if retryable, ok := tr.(api.RetryableTransport); ok && tCfg.RetryStrategy != nil {
248+
if retryable, ok := t.(api.RetryableTransport); ok && tCfg.RetryStrategy != nil {
189249
strategy := retry.NewMultiplierRetryStrategy(
190250
tCfg.RetryStrategy.MaxRetries,
191251
tCfg.RetryStrategy.Delay,
@@ -195,23 +255,29 @@ func (b *Builder) createMessenger(router api.Router) (api.Messenger, error) {
195255

196256
var failureTransport api.Transport
197257
if b.cfg.FailureTransport != "" {
198-
failureTransport = b.transportLocator.GetTransport(b.cfg.FailureTransport)
258+
if ft, exists := createdTransports[b.cfg.FailureTransport]; exists {
259+
failureTransport = ft
260+
}
199261
}
200262

201-
lst := listener.NewSendFailedMessageForRetryListener(retryable, failureTransport, strategy, b.logger)
263+
lst := listener.NewSendFailedMessageForRetryListener(b.logger, retryable, failureTransport, strategy)
202264
b.eventDispatcher.AddListener(event.SendFailedMessageEvent{}, lst)
203265
}
204266
}
205-
206-
defaultBus, ok := b.busLocator.Get(b.cfg.DefaultBus)
207-
if !ok {
208-
return nil, fmt.Errorf("default_bus %q not found", defaultBus)
209-
}
210-
211-
return messenger.NewMessenger(b.cfg.DefaultBus, manager, b.busLocator, router), nil
212267
}
213268

214269
func (b *Builder) registerStamps() {
215270
b.resolver.RegisterStamp(stamps.BusNameStamp{})
216271
b.resolver.RegisterStamp(stamps.RedeliveryStamp{})
217272
}
273+
274+
func (b *Builder) createdSyncTransport(createdTransports map[string]api.Transport) {
275+
cfg := config.TransportConfig{
276+
DSN: "sync://",
277+
Options: config.OptionsConfig{},
278+
}
279+
280+
if syncTransport, err := b.transportFactory.CreateTransport("sync", cfg); err == nil {
281+
createdTransports["sync"] = syncTransport
282+
}
283+
}

0 commit comments

Comments
 (0)