Allow user to override no-op checkpoint with Option
This commit is contained in:
parent
c64b40b4ad
commit
3770136f64
4 changed files with 28 additions and 35 deletions
20
README.md
20
README.md
|
|
@ -18,11 +18,13 @@ Get the package source:
|
||||||
|
|
||||||
The consumer leverages a handler func that accepts a Kinesis record. The `Scan` method will consume all shards concurrently and call the callback func as it receives records from the stream.
|
The consumer leverages a handler func that accepts a Kinesis record. The `Scan` method will consume all shards concurrently and call the callback func as it receives records from the stream.
|
||||||
|
|
||||||
|
Important: The default Log, Counter, and Checkpoint are no-op which means no logs, counts, or checkpoints will be emitted when scanning the stream. See the options below to override these defaults.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import(
|
import(
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
consumer "github.com/harlow/kinesis-consumer"
|
consumer "github.com/harlow/kinesis-consumer"
|
||||||
checkpoint "github.com/harlow/kinesis-consumer/checkpoint/redis"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
@ -32,14 +34,8 @@ func main() {
|
||||||
)
|
)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// new checkpoint
|
// consumer
|
||||||
ck, err := checkpoint.New(*app, *stream)
|
c, err := consumer.New(*app, *stream)
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("checkpoint error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// new consumer
|
|
||||||
c, err := consumer.New(ck, *app, *stream)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("consumer error: %v", err)
|
log.Fatalf("consumer error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +64,9 @@ The uniq identifier for a consumer is `[appName, streamName, shardID]`
|
||||||
|
|
||||||
<img width="722" alt="kinesis-checkpoints" src="https://user-images.githubusercontent.com/739782/33085867-d8336122-ce9a-11e7-8c8a-a8afeb09dff1.png">
|
<img width="722" alt="kinesis-checkpoints" src="https://user-images.githubusercontent.com/739782/33085867-d8336122-ce9a-11e7-8c8a-a8afeb09dff1.png">
|
||||||
|
|
||||||
There are currently two storage types for checkpoints:
|
Note: The default checkpoint is no-op. Which means the scan will not persist any state and the consumer will start from the beginning of the stream each time it is re-started.
|
||||||
|
|
||||||
|
To persist scan progress choose one of the following checkpoints:
|
||||||
|
|
||||||
### Redis Checkpoint
|
### Redis Checkpoint
|
||||||
|
|
||||||
|
|
@ -116,7 +114,7 @@ client := kinesis.New(session.New(aws.NewConfig()))
|
||||||
|
|
||||||
// consumer
|
// consumer
|
||||||
c, err := consumer.New(
|
c, err := consumer.New(
|
||||||
consumer,
|
appName,
|
||||||
streamName,
|
streamName,
|
||||||
consumer.WithClient(client),
|
consumer.WithClient(client),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
package checkpoint
|
|
||||||
|
|
||||||
// Checkpoint interface used to allow swappable backends for checkpoining
|
|
||||||
// consumer progress in the stream.
|
|
||||||
type Checkpoint interface {
|
|
||||||
Get(shardID string) (string, error)
|
|
||||||
Set(shardID string, sequenceNumber string) error
|
|
||||||
}
|
|
||||||
32
consumer.go
32
consumer.go
|
|
@ -10,12 +10,11 @@ import (
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/aws/aws-sdk-go/service/kinesis"
|
"github.com/aws/aws-sdk-go/service/kinesis"
|
||||||
"github.com/harlow/kinesis-consumer/checkpoint"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Record = kinesis.Record
|
type Record = kinesis.Record
|
||||||
|
|
||||||
// Counter is used for exposing basic metrics from the scanner
|
// Counter interface is used for exposing basic metrics from the scanner
|
||||||
type Counter interface {
|
type Counter interface {
|
||||||
Add(string, int64)
|
Add(string, int64)
|
||||||
}
|
}
|
||||||
|
|
@ -24,11 +23,22 @@ type noopCounter struct{}
|
||||||
|
|
||||||
func (n noopCounter) Add(string, int64) {}
|
func (n noopCounter) Add(string, int64) {}
|
||||||
|
|
||||||
|
// Checkpoint interface used track consumer progress in the stream
|
||||||
|
type Checkpoint interface {
|
||||||
|
Get(shardID string) (string, error)
|
||||||
|
Set(shardID string, sequenceNumber string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type noopCheckpoint struct{}
|
||||||
|
|
||||||
|
func (n noopCheckpoint) Set(string, string) error { return nil }
|
||||||
|
func (n noopCheckpoint) Get(string) (string, error) { return "", nil }
|
||||||
|
|
||||||
// Option is used to override defaults when creating a new Consumer
|
// Option is used to override defaults when creating a new Consumer
|
||||||
type Option func(*Consumer) error
|
type Option func(*Consumer) error
|
||||||
|
|
||||||
// WithCheckpoint overrides the default checkpoint
|
// WithCheckpoint overrides the default checkpoint
|
||||||
func WithCheckpoint(checkpoint checkpoint.Checkpoint) Option {
|
func WithCheckpoint(checkpoint Checkpoint) Option {
|
||||||
return func(c *Consumer) error {
|
return func(c *Consumer) error {
|
||||||
c.checkpoint = checkpoint
|
c.checkpoint = checkpoint
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -53,11 +63,7 @@ func WithCounter(counter Counter) Option {
|
||||||
|
|
||||||
// New creates a kinesis consumer with default settings. Use Option to override
|
// New creates a kinesis consumer with default settings. Use Option to override
|
||||||
// any of the optional attributes.
|
// any of the optional attributes.
|
||||||
func New(checkpoint checkpoint.Checkpoint, app, stream string, opts ...Option) (*Consumer, error) {
|
func New(app, stream string, opts ...Option) (*Consumer, error) {
|
||||||
if checkpoint == nil {
|
|
||||||
return nil, fmt.Errorf("must provide checkpoint")
|
|
||||||
}
|
|
||||||
|
|
||||||
if app == "" {
|
if app == "" {
|
||||||
return nil, fmt.Errorf("must provide app name")
|
return nil, fmt.Errorf("must provide app name")
|
||||||
}
|
}
|
||||||
|
|
@ -67,9 +73,10 @@ func New(checkpoint checkpoint.Checkpoint, app, stream string, opts ...Option) (
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &Consumer{
|
c := &Consumer{
|
||||||
checkpoint: checkpoint,
|
|
||||||
appName: app,
|
appName: app,
|
||||||
streamName: stream,
|
streamName: stream,
|
||||||
|
checkpoint: &noopCheckpoint{},
|
||||||
|
counter: &noopCounter{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// set options
|
// set options
|
||||||
|
|
@ -89,11 +96,6 @@ func New(checkpoint checkpoint.Checkpoint, app, stream string, opts ...Option) (
|
||||||
c.client = kinesis.New(session.New(aws.NewConfig()))
|
c.client = kinesis.New(session.New(aws.NewConfig()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// provide default no-op counter
|
|
||||||
if c.counter == nil {
|
|
||||||
c.counter = &noopCounter{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,7 +105,7 @@ type Consumer struct {
|
||||||
streamName string
|
streamName string
|
||||||
client *kinesis.Kinesis
|
client *kinesis.Kinesis
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
checkpoint checkpoint.Checkpoint
|
checkpoint Checkpoint
|
||||||
counter Counter
|
counter Counter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,8 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// consumer
|
// consumer
|
||||||
c, err := consumer.New(ck, *app, *stream,
|
c, err := consumer.New(*app, *stream,
|
||||||
|
consumer.WithCheckpoint(ck),
|
||||||
consumer.WithLogger(logger),
|
consumer.WithLogger(logger),
|
||||||
consumer.WithCounter(counter),
|
consumer.WithCounter(counter),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue