-
Notifications
You must be signed in to change notification settings - Fork 173
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
Tester tolerate unconsumed queues #199
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
e26c6d6
#176 bugfix processor shutdown when producer gets closed
frairon b5d3f05
workaround for #176. Timing out when the partition is stuck
frairon bc52dc0
timeout for producer shutdown, improve logging
frairon c12b6f3
tester: queue consumer drops events once the events-channel gets full
frairon 4bd0eff
view:fix logging
frairon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
"sync/atomic" | ||
"time" | ||
|
||
"github.com/lovoo/goka" | ||
"github.com/lovoo/goka/codec" | ||
"github.com/lovoo/goka/kafka" | ||
) | ||
|
||
func main() { | ||
|
||
proc, err := goka.NewProcessor([]string{"localhost:9092"}, | ||
goka.DefineGroup("processor-stuck-test", | ||
goka.Input("input", new(codec.Int64), func(ctx goka.Context, msg interface{}) { | ||
ctx.SetValue(msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
ctx.Emit("output", ctx.Key(), msg) | ||
}), | ||
goka.Output("output", new(codec.Int64)), | ||
goka.Persist(new(codec.Int64)), | ||
)) | ||
|
||
if err != nil { | ||
log.Fatalf("Cannot start processor: %v", err) | ||
} | ||
|
||
ctx, cancel := context.WithCancel(context.Background()) | ||
done := make(chan struct{}) | ||
go func() { | ||
defer close(done) | ||
|
||
log.Printf("Running processor") | ||
procRunErr := proc.Run(ctx) | ||
log.Printf("Processor finished with %v", procRunErr) | ||
}() | ||
|
||
log.Printf("wait 5 seconds before starting to emit") | ||
time.Sleep(5 * time.Second) | ||
|
||
for i := 0; i < 50; i++ { | ||
go func() { | ||
|
||
cfg := kafka.NewConfig() | ||
cfg.Producer.Retry.Max = 0 | ||
cfg.Producer.Retry.Backoff = 1 * time.Millisecond | ||
emitter, err := goka.NewEmitter([]string{"localhost:9092"}, "input", new(codec.Int64), | ||
goka.WithEmitterProducerBuilder( | ||
kafka.ProducerBuilderWithConfig(cfg), | ||
), | ||
) | ||
if err != nil { | ||
log.Fatalf("Error creating emitter: %v", err) | ||
} | ||
|
||
time.Sleep(2 * time.Second) | ||
defer func() { | ||
log.Printf("finishing") | ||
emitter.Finish() | ||
log.Printf("done") | ||
}() | ||
|
||
defer recover() | ||
var done int64 | ||
var emitted int64 | ||
for i := 0; ; i++ { | ||
if atomic.LoadInt64(&done) > 0 { | ||
break | ||
} | ||
|
||
// when the context is done, stop emitting | ||
go func() { | ||
<-ctx.Done() | ||
atomic.AddInt64(&done, 1) | ||
}() | ||
emitted++ | ||
if emitted%1000 == 0 { | ||
log.Printf("emitted %d", emitted) | ||
} | ||
prom, err := emitter.Emit(fmt.Sprintf("%d", i), int64(i)) | ||
if err != nil { | ||
break | ||
} | ||
prom.Then(func(err error) { | ||
if err != nil { | ||
atomic.AddInt64(&done, 1) | ||
} | ||
}) | ||
time.Sleep(10 * time.Millisecond) | ||
} | ||
}() | ||
} | ||
|
||
log.Printf("waiting for the processor to shutdown") | ||
<-done | ||
log.Printf("processor is dead. Nice!") | ||
|
||
cancel() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// +build kafka | ||
|
||
package kafka | ||
|
||
import ( | ||
"log" | ||
"sync/atomic" | ||
"testing" | ||
"time" | ||
) | ||
|
||
// This tests how a producer behaves when being shutdown to make sure, | ||
// no promises stay unfinished. | ||
// To run the test, get a local kafka-container running (e.g. go to | ||
// examples-directory and do `make restart`), then run the tests with | ||
// `go test -v github.com/lovoo/goka/kafka/ -tags=kafka` | ||
func TestProducerError(t *testing.T) { | ||
cfg := NewConfig().Config | ||
p, err := NewProducer([]string{"localhost:9092"}, &cfg) | ||
|
||
if err != nil { | ||
t.Fatalf("error creating producer: %v", err) | ||
} | ||
|
||
var ( | ||
promises []*Promise | ||
donePromises int64 | ||
emitted int64 | ||
done = make(chan bool) | ||
) | ||
|
||
go func() { | ||
defer func() { | ||
recover() | ||
}() | ||
defer close(done) | ||
for { | ||
promise := p.Emit("test", "test", []byte{}) | ||
promise.Then(func(err error) { | ||
atomic.AddInt64(&donePromises, 1) | ||
if err != nil { | ||
log.Printf("error producing message: %v", err) | ||
} | ||
}) | ||
promises = append(promises, promise) | ||
emitted++ | ||
time.Sleep(20 * time.Millisecond) | ||
} | ||
}() | ||
|
||
// let it run for 1 second | ||
time.Sleep(1000 * time.Millisecond) | ||
|
||
// close the producer | ||
err = p.Close() | ||
if err != nil { | ||
log.Printf("Error closing producer: %v", err) | ||
} | ||
// wait for the promises to be | ||
<-done | ||
|
||
if len(promises) != int(emitted) { | ||
t.Errorf("Promises/Emits do not match: promises: %d, emitted. %d", len(promises), emitted) | ||
} | ||
if len(promises) != int(donePromises) { | ||
t.Errorf("Promises/Done promises do not match: promises: %d, done. %d", len(promises), donePromises) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These loops could use some more overview imo