message broker sifatida redis qo'shildi

This commit is contained in:
A'zamov Samandar
2025-04-25 10:25:49 +05:00
parent 40200a4649
commit 71634fc19e
7 changed files with 163 additions and 48 deletions

View File

@@ -72,7 +72,7 @@ Notifications should be published to the RabbitMQ exchange with the following JS
} }
``` ```
Python example Python example rabbitmq broker
```python ```python
from kombu import Connection, Exchange, Producer from kombu import Connection, Exchange, Producer
@@ -93,6 +93,28 @@ producer.publish(message)
print("Message sent to all workers!") print("Message sent to all workers!")
``` ```
Python example redis broker
```python
import redis
import json
# Redis ulanishi
r = redis.StrictRedis(host='127.0.0.1', port=6379, db=0)
# Xabar tayyorlash
message = {
'type': 'email',
'message': "Subject: test\r\n\r\nclasscom.uz sayti va mobil ilovasiga ro'yxatdan o'tishingiz uchun tasdiqlash kodi: 1234",
'to': ["JscorpTech@gmail.com", "admin@jscorp.uz"]
}
# Xabarni JSON formatga otkazib, Redis listga push qilish
r.rpush('notification', json.dumps(message))
print("Message pushed to Redis list!")
```
Available notification types: Available notification types:
- `email`: For email notifications - `email`: For email notifications
- `sms`: For SMS notifications - `sms`: For SMS notifications

View File

@@ -0,0 +1,46 @@
package broker
import (
"context"
"encoding/json"
"fmt"
"log"
"github.com/JscorpTech/notification/internal/domain"
"github.com/JscorpTech/notification/internal/rabbitmq"
)
type rabbitMQBroker struct {
Ctx context.Context
}
func NewRabbitMQBroker(ctx context.Context) domain.BrokerPort {
return &rabbitMQBroker{
Ctx: ctx,
}
}
func (r rabbitMQBroker) Subscribe(topic string, handler func(domain.NotificationMsg)) {
conn, ch, err := rabbitmq.Connect()
if err != nil {
log.Fatal(err)
}
defer conn.Close()
defer ch.Close()
ch.ExchangeDeclare(topic, "direct", true, false, false, false, nil)
q, _ := ch.QueueDeclare(topic, true, false, false, false, nil)
ch.QueueBind(q.Name, topic, topic, false, nil)
msgs, _ := ch.Consume(q.Name, "", true, false, false, false, nil)
go func() {
for msg := range msgs {
var notification domain.NotificationMsg
if err := json.Unmarshal(msg.Body, &notification); err != nil {
fmt.Print(err.Error())
}
go handler(notification)
}
}()
}

39
internal/broker/redis.go Normal file
View File

@@ -0,0 +1,39 @@
package broker
import (
"context"
"encoding/json"
"fmt"
"github.com/JscorpTech/notification/internal/domain"
"github.com/JscorpTech/notification/internal/redis"
)
type redisBroker struct {
Ctx context.Context
}
func NewRedisBroker(ctx context.Context) domain.BrokerPort {
return &redisBroker{
Ctx: ctx,
}
}
func (r redisBroker) Subscribe(topic string, handler func(domain.NotificationMsg)) {
go func() {
for {
var notification domain.NotificationMsg
val, err := redis.RDB.BLPop(r.Ctx, 0, topic).Result()
if err != nil {
fmt.Print(err.Error())
return
}
if err := json.Unmarshal([]byte(val[1]), &notification); err != nil {
fmt.Print(err.Error())
return
}
go handler(notification)
}
}()
}

View File

@@ -2,14 +2,12 @@ package consumer
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"log" "os"
"github.com/JscorpTech/notification/internal/broker"
"github.com/JscorpTech/notification/internal/domain" "github.com/JscorpTech/notification/internal/domain"
"github.com/JscorpTech/notification/internal/notifier" "github.com/JscorpTech/notification/internal/notifier"
"github.com/JscorpTech/notification/internal/rabbitmq"
"github.com/streadway/amqp"
) )
type notificationConsumer struct { type notificationConsumer struct {
@@ -23,39 +21,26 @@ func NewNotificationConsumer(ctx context.Context) domain.NotificationConsumerPor
} }
func (n *notificationConsumer) Start() { func (n *notificationConsumer) Start() {
conn, ch, err := rabbitmq.Connect()
if err != nil { brokerName := os.Getenv("BROKER")
log.Fatal(err) if brokerName == "" {
brokerName = "redis"
} }
defer conn.Close() var brokerService domain.BrokerPort
defer ch.Close() switch brokerName {
case "redis":
exchangeName := "notification" brokerService = broker.NewRedisBroker(n.Ctx)
queueName := "notification" case "rabbitmq":
routingKey := "notification" brokerService = broker.NewRabbitMQBroker(n.Ctx)
default:
ch.ExchangeDeclare(exchangeName, "direct", true, false, false, false, nil) brokerService = broker.NewRedisBroker(n.Ctx)
q, _ := ch.QueueDeclare(queueName, true, false, false, false, nil)
ch.QueueBind(q.Name, routingKey, exchangeName, false, nil)
msgs, _ := ch.Consume(q.Name, "", true, false, false, false, nil)
go func() {
for msg := range msgs {
go n.Handler(msg)
} }
}() brokerService.Subscribe(os.Getenv("TOPIC"), n.Handler)
fmt.Println("🚀 Server started. Ctrl+C to quit.") fmt.Println("🚀 Server started. Ctrl+C to quit.")
select {} select {}
} }
func (n *notificationConsumer) Handler(msg amqp.Delivery) { func (n *notificationConsumer) Handler(notification domain.NotificationMsg) {
var notification domain.NotificationMsg
err := json.Unmarshal(msg.Body, &notification)
if err != nil {
fmt.Print(err.Error())
}
var ntf domain.NotifierPort var ntf domain.NotifierPort
switch notification.Type { switch notification.Type {
case "sms": case "sms":

View File

@@ -0,0 +1,6 @@
package domain
type BrokerPort interface {
Subscribe(string, func(NotificationMsg))
// Publish()
}

View File

@@ -1,10 +1,8 @@
package domain package domain
import "github.com/streadway/amqp"
type NotificationConsumerPort interface { type NotificationConsumerPort interface {
Start() Start()
Handler(amqp.Delivery) Handler(NotificationMsg)
} }
type SMSServicePort interface { type SMSServicePort interface {

43
test.py
View File

@@ -1,17 +1,36 @@
from kombu import Connection, Exchange, Producer # from kombu import Connection, Exchange, Producer
# RabbitMQ ulanishi # # RabbitMQ ulanishi
rabbit_url = 'amqp://guest:guest@127.0.0.1:5672/' # rabbit_url = 'amqp://guest:guest@127.0.0.1:5672/'
connection = Connection(rabbit_url) # connection = Connection(rabbit_url)
channel = connection.channel() # channel = connection.channel()
exchange = Exchange('notification', type='direct') # exchange = Exchange('notification', type='direct')
# Producer yaratish # # Producer yaratish
producer = Producer(channel, exchange=exchange, routing_key="notification") # producer = Producer(channel, exchange=exchange, routing_key="notification")
# Xabar yuborish # # Xabar yuborish
message = {'type': 'email', 'message': "Subject: test\r\n\r\nclasscom.uz sayti va mobil ilovasiga ro'yxatdan o'tishingingiz uchun tasdiqlash kodi: 1234", "to": ["JscorpTech@gmail.com", "admin@jscorp.uz"]} # message = {'type': 'email', 'message': "Subject: test\r\n\r\nclasscom.uz sayti va mobil ilovasiga ro'yxatdan o'tishingingiz uchun tasdiqlash kodi: 1234", "to": ["JscorpTech@gmail.com", "admin@jscorp.uz"]}
producer.publish(message) # producer.publish(message)
print("Message sent to all workers!") # print("Message sent to all workers!")
import redis
import json
# Redis ulanishi
r = redis.StrictRedis(host='127.0.0.1', port=6379, db=0)
# Xabar tayyorlash
message = {
'type': 'email',
'message': "Subject: test\r\n\r\nclasscom.uz sayti va mobil ilovasiga ro'yxatdan o'tishingiz uchun tasdiqlash kodi: 1234",
'to': ["JscorpTech@gmail.com", "admin@jscorp.uz"]
}
# Xabarni JSON formatga otkazib, Redis listga push qilish
r.rpush('notification', json.dumps(message))
print("Message pushed to Redis list!")