Allow user to override no-op checkpoint with Option

This commit is contained in:
Harlow Ward 2017-11-22 17:44:42 -08:00
parent c64b40b4ad
commit 3770136f64
4 changed files with 28 additions and 35 deletions

View file

@ -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),
) )

View file

@ -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
}

View file

@ -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
} }

View file

@ -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),
) )