-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wait For Inflight Messages #104
Conversation
Codecov Report
@@ Coverage Diff @@
## main #104 +/- ##
==========================================
+ Coverage 79.28% 79.31% +0.02%
==========================================
Files 16 16
Lines 2404 2407 +3
==========================================
+ Hits 1906 1909 +3
Misses 363 363
Partials 135 135
Continue to review full report at Codecov.
|
@brenol would you please test the PR? you can use: package main
import (
"fmt"
"github.com/rabbitmq/rabbitmq-stream-go-client/pkg/logs"
"log"
"sync/atomic"
"time"
"github.com/rabbitmq/rabbitmq-stream-go-client/pkg/amqp"
"github.com/rabbitmq/rabbitmq-stream-go-client/pkg/stream"
)
const streamName = "test-output"
var count int32
var fail int32
func handlePublishConfirm(confirms stream.ChannelPublishConfirm) {
go func() {
for confirmed := range confirms {
for _, msg := range confirmed {
if msg.IsConfirmed() {
atomic.AddInt32(&count, 1)
} else {
atomic.AddInt32(&fail, 1)
}
}
}
}()
}
func main() {
env, err := stream.NewEnvironment(
stream.NewEnvironmentOptions().SetUri("tcp://guest:guest@localhost:5552"),
)
if err != nil {
panic(err)
}
if err := setupStream(env); err != nil {
panic(err)
}
// consumer
// using producer.Close() no messages will be consumed
var consumerClose func() error
go func() {
opts := stream.NewConsumerOptions().
SetConsumerName("test")
cons, err := env.NewConsumer(streamName, consume, opts)
if err != nil {
panic(err)
}
consumerClose = cons.Close
}()
defer func() {
consumerClose()
}()
prod, err := env.NewProducer(streamName, stream.NewProducerOptions())
if err != nil {
panic(err)
}
handlePublishConfirm(prod.NotifyPublishConfirmation())
ticker := time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
produced := 0
__LOOP:
for {
select {
case <-ticker.C:
break __LOOP
default:
}
msg := amqp.NewMessage([]byte(fmt.Sprintf("producing: %d", produced)))
if err := prod.Send(msg); err != nil {
panic(err)
}
produced++
}
log.Printf("produced %d messages\n", produced)
stream.SetLevelInfo(logs.DEBUG)
notification := prod.NotifyClose()
// change from prod.Close() to env.Close()
if err := prod.Close(); err != nil {
log.Println("could not close producer:", err)
}
<-notification
log.Printf("got close notification. Produced: %d, Consumed: %d , failed %d - Total %d - confirmed %d \n", produced,
atomic.LoadInt64(&consumed), atomic.LoadInt32(&fail),
atomic.LoadInt64(&consumed)+int64(atomic.LoadInt32(&fail)), atomic.LoadInt32(&count))
}
var consumed int64
func consume(consumerContext stream.ConsumerContext, message *amqp.Message) {
atomic.AddInt64(&consumed, 1)
}
func setupStream(env *stream.Environment) error {
env.DeleteStream(streamName)
ok, err := env.StreamExists(streamName)
if err != nil {
return err
}
if !ok {
if err := env.DeclareStream(
streamName,
&stream.StreamOptions{MaxAge: 24 * 7 * time.Hour},
); err != nil {
return err
}
}
return nil
} at the end you should see something like:
Thank you! |
Hi @Gsantomaggio, thank you for the fast response & fast PR. 🥳 However, unfortunately, it did not work 100% for me: go.mod:
Code: package main
import (
"fmt"
"log"
"sync/atomic"
"time"
"github.com/rabbitmq/rabbitmq-stream-go-client/pkg/logs"
"github.com/rabbitmq/rabbitmq-stream-go-client/pkg/amqp"
"github.com/rabbitmq/rabbitmq-stream-go-client/pkg/stream"
)
const streamName = "test-output"
var count int32
var fail int32
func handlePublishConfirm(confirms stream.ChannelPublishConfirm) {
go func() {
for confirmed := range confirms {
for _, msg := range confirmed {
if msg.IsConfirmed() {
atomic.AddInt32(&count, 1)
} else {
atomic.AddInt32(&fail, 1)
}
}
}
}()
}
func main() {
env, err := stream.NewEnvironment(
stream.NewEnvironmentOptions().SetUri("tcp://guest:guest@localhost:5552"),
)
if err != nil {
panic(err)
}
if err := setupStream(env); err != nil {
panic(err)
}
// consumer
// using producer.Close() no messages will be consumed
var consumerClose func() error
go func() {
opts := stream.NewConsumerOptions().
SetConsumerName("test")
cons, err := env.NewConsumer(streamName, consume, opts)
if err != nil {
panic(err)
}
consumerClose = cons.Close
}()
defer func() {
consumerClose()
}()
prod, err := env.NewProducer(streamName, stream.NewProducerOptions())
if err != nil {
panic(err)
}
handlePublishConfirm(prod.NotifyPublishConfirmation())
ticker := time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
produced := 0
__LOOP:
for {
select {
case <-ticker.C:
break __LOOP
default:
}
msg := amqp.NewMessage([]byte(fmt.Sprintf("producing: %d", produced)))
if err := prod.Send(msg); err != nil {
panic(err)
}
produced++
}
log.Printf("produced %d messages\n", produced)
stream.SetLevelInfo(logs.DEBUG)
notification := prod.NotifyClose()
// change from prod.Close() to env.Close()
if err := prod.Close(); err != nil {
log.Println("could not close producer:", err)
}
<-notification
log.Printf("got close notification. Produced: %d, Consumed: %d , failed %d - Total %d - confirmed %d \n", produced,
atomic.LoadInt64(&consumed), atomic.LoadInt32(&fail),
atomic.LoadInt64(&consumed)+int64(atomic.LoadInt32(&fail)), atomic.LoadInt32(&count))
}
var consumed int64
func consume(consumerContext stream.ConsumerContext, message *amqp.Message) {
atomic.AddInt64(&consumed, 1)
}
func setupStream(env *stream.Environment) error {
env.DeleteStream(streamName)
ok, err := env.StreamExists(streamName)
if err != nil {
return err
}
if !ok {
if err := env.DeclareStream(
streamName,
&stream.StreamOptions{MaxAge: 24 * 7 * time.Hour},
); err != nil {
return err
}
}
return nil
} Output:
Using
So on my side its not working 100% of the time. Thank you again! |
@Gsantomaggio one more test I just did. Tried to move consumerClose() & add a wait (as it could be failing because consumer was not... consuming everything) but unfortunately it did not work as well. package main
import (
"fmt"
"log"
"sync/atomic"
"time"
"github.com/rabbitmq/rabbitmq-stream-go-client/pkg/logs"
"github.com/rabbitmq/rabbitmq-stream-go-client/pkg/amqp"
"github.com/rabbitmq/rabbitmq-stream-go-client/pkg/stream"
)
const streamName = "test-output"
var count int32
var fail int32
func handlePublishConfirm(confirms stream.ChannelPublishConfirm) {
go func() {
for confirmed := range confirms {
for _, msg := range confirmed {
if msg.IsConfirmed() {
atomic.AddInt32(&count, 1)
} else {
atomic.AddInt32(&fail, 1)
}
}
}
}()
}
func main() {
env, err := stream.NewEnvironment(
stream.NewEnvironmentOptions().SetUri("tcp://guest:guest@localhost:5552"),
)
if err != nil {
panic(err)
}
if err := setupStream(env); err != nil {
panic(err)
}
// consumer
var (
consumerClose func() error
consumerNotification stream.ChannelClose
)
go func() {
opts := stream.NewConsumerOptions().
SetConsumerName("test")
cons, err := env.NewConsumer(streamName, consume, opts)
if err != nil {
panic(err)
}
consumerClose = cons.Close
consumerNotification = cons.NotifyClose()
}()
prod, err := env.NewProducer(streamName, stream.NewProducerOptions())
if err != nil {
panic(err)
}
handlePublishConfirm(prod.NotifyPublishConfirmation())
ticker := time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
produced := 0
__LOOP:
for {
select {
case <-ticker.C:
break __LOOP
default:
}
msg := amqp.NewMessage([]byte(fmt.Sprintf("producing: %d", produced)))
if err := prod.Send(msg); err != nil {
panic(err)
}
produced++
}
log.Printf("produced %d messages\n", produced)
stream.SetLevelInfo(logs.DEBUG)
notification := prod.NotifyClose()
// change from prod.Close() to env.Close()
if err := prod.Close(); err != nil {
log.Println("could not close producer:", err)
}
<-notification
if err := consumerClose(); err != nil {
log.Println("could not close consumer:", err)
}
<-consumerNotification
log.Printf("got close notification. Produced: %d, Consumed: %d , failed %d - Total %d - confirmed %d \n", produced,
atomic.LoadInt64(&consumed), atomic.LoadInt32(&fail),
atomic.LoadInt64(&consumed)+int64(atomic.LoadInt32(&fail)), atomic.LoadInt32(&count))
}
var consumed int64
func consume(consumerContext stream.ConsumerContext, message *amqp.Message) {
atomic.AddInt64(&consumed, 1)
}
func setupStream(env *stream.Environment) error {
env.DeleteStream(streamName)
ok, err := env.StreamExists(streamName)
if err != nil {
return err
}
if !ok {
if err := env.DeclareStream(
streamName,
&stream.StreamOptions{MaxAge: 24 * 7 * time.Hour},
); err != nil {
return err
}
}
return nil
} Output:
|
Thanks @brenol but the commit is not correct :)
you should use:
and you should see this log:
|
@Gsantomaggio sorry!! Thank you, it worked flawlessly. I did not read the commit history correctly (in PRs older are shown first. In the branch, new ones are shown first... 😭 - so sorry again for that!) Now:
Thank you a lot! |
No problem! :)! |
Fixes #103