Add checkpoint interface for custom checkpoints (#29)
To allow other checkpoint backends we extract a checkpoint interface which future checkpoints can implement. * Add checkpoint interface for custom checkpoints * Create RedisCheckpoint to implement checkpoint interface * Swap out hosie redis library for go-redis Minor changes * Allow configuration of Redis endpoint with env var `REDIS_URL` * Replace gvt with govendor
This commit is contained in:
parent
cc936aed04
commit
fedb6812fb
10 changed files with 469 additions and 271 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -38,7 +38,7 @@ tags*
|
|||
|
||||
# Vendored files
|
||||
vendor/**
|
||||
!vendor/manifest
|
||||
!vendor/vendor.json
|
||||
|
||||
# Benchmark files
|
||||
prof.cpu
|
||||
|
|
|
|||
15
README.md
15
README.md
|
|
@ -36,6 +36,14 @@ func main() {
|
|||
}
|
||||
```
|
||||
|
||||
### Config
|
||||
|
||||
The default behavior for checkpointing uses Redis on localhost. To set a custom Redis URL use ENV vars:
|
||||
|
||||
```
|
||||
REDIS_URL=my-custom-redis-server.com:6379
|
||||
```
|
||||
|
||||
### Logging
|
||||
|
||||
[Apex Log](https://medium.com/@tjholowaychuk/apex-log-e8d9627f4a9a#.5x1uo1767) is used for logging Info. Override the logs format with other [Log Handlers](https://github.com/apex/log/tree/master/_examples). For example using the "json" log handler:
|
||||
|
|
@ -70,14 +78,14 @@ Get the package source:
|
|||
|
||||
### Fetching Dependencies
|
||||
|
||||
Install `gvt`:
|
||||
Install `govendor`:
|
||||
|
||||
$ export GO15VENDOREXPERIMENT=1
|
||||
$ go get github.com/FiloSottile/gvt
|
||||
$ go get -u github.com/kardianos/govendor
|
||||
|
||||
Install dependencies into `./vendor/`:
|
||||
|
||||
$ gvt restore
|
||||
$ govendor sync
|
||||
|
||||
### Examples
|
||||
|
||||
|
|
@ -86,7 +94,6 @@ Use the [seed stream](https://github.com/harlow/kinesis-connectors/tree/master/e
|
|||
* [Firehose](https://github.com/harlow/kinesis-connectors/tree/master/examples/firehose)
|
||||
* [S3](https://github.com/harlow/kinesis-connectors/tree/master/examples/s3)
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see [CONTRIBUTING.md] for more information. Thank you, [contributors]!
|
||||
|
|
|
|||
|
|
@ -1,48 +1,9 @@
|
|||
package connector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hoisie/redis"
|
||||
)
|
||||
|
||||
// RedisCheckpoint implements the Checkpont interface.
|
||||
// This class is used to enable the Pipeline.ProcessShard to checkpoint their progress.
|
||||
type Checkpoint struct {
|
||||
AppName string
|
||||
StreamName string
|
||||
|
||||
client redis.Client
|
||||
sequenceNumber string
|
||||
}
|
||||
|
||||
// CheckpointExists determines if a checkpoint for a particular Shard exists.
|
||||
// Typically used to determine whether we should start processing the shard with
|
||||
// TRIM_HORIZON or AFTER_SEQUENCE_NUMBER (if checkpoint exists).
|
||||
func (c *Checkpoint) CheckpointExists(shardID string) bool {
|
||||
val, _ := c.client.Get(c.key(shardID))
|
||||
|
||||
if val != nil && string(val) != "" {
|
||||
c.sequenceNumber = string(val)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SequenceNumber returns the current checkpoint stored for the specified shard.
|
||||
func (c *Checkpoint) SequenceNumber() string {
|
||||
return c.sequenceNumber
|
||||
}
|
||||
|
||||
// SetCheckpoint stores a checkpoint for a shard (e.g. sequence number of last record processed by application).
|
||||
// Upon failover, record processing is resumed from this point.
|
||||
func (c *Checkpoint) SetCheckpoint(shardID string, sequenceNumber string) {
|
||||
c.client.Set(c.key(shardID), []byte(sequenceNumber))
|
||||
c.sequenceNumber = sequenceNumber
|
||||
}
|
||||
|
||||
// key generates a unique Redis key for storage of Checkpoint.
|
||||
func (c *Checkpoint) key(shardID string) string {
|
||||
return fmt.Sprintf("%v:checkpoint:%v:%v", c.AppName, c.StreamName, shardID)
|
||||
// Checkpoint interface for functions that checkpoints need to
|
||||
// implement in order to track consumer progress.
|
||||
type Checkpoint interface {
|
||||
CheckpointExists(shardID string) bool
|
||||
SequenceNumber() string
|
||||
SetCheckpoint(shardID string, sequenceNumber string)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
package connector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/bmizerany/assert"
|
||||
"github.com/hoisie/redis"
|
||||
)
|
||||
|
||||
func Test_key(t *testing.T) {
|
||||
c := Checkpoint{
|
||||
AppName: "app",
|
||||
StreamName: "stream",
|
||||
}
|
||||
|
||||
k := c.key("shard")
|
||||
assert.Equal(t, k, "app:checkpoint:stream:shard")
|
||||
}
|
||||
|
||||
func Test_CheckpointExists(t *testing.T) {
|
||||
var rc redis.Client
|
||||
rc.Set("app:checkpoint:stream:shard", []byte("testSeqNum"))
|
||||
c := Checkpoint{
|
||||
AppName: "app",
|
||||
StreamName: "stream",
|
||||
}
|
||||
|
||||
r := c.CheckpointExists("shard")
|
||||
assert.Equal(t, r, true)
|
||||
|
||||
rc.Del("app:checkpoint:stream:shard")
|
||||
}
|
||||
|
||||
func Test_SetCheckpoint(t *testing.T) {
|
||||
var rc redis.Client
|
||||
c := Checkpoint{
|
||||
AppName: "app",
|
||||
StreamName: "stream",
|
||||
}
|
||||
|
||||
c.SetCheckpoint("shard", "testSeqNum")
|
||||
r, _ := rc.Get("app:checkpoint:stream:shard")
|
||||
assert.Equal(t, string(r), "testSeqNum")
|
||||
|
||||
rc.Del("app:checkpoint:stream:shard")
|
||||
}
|
||||
37
config.go
37
config.go
|
|
@ -4,15 +4,19 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
redis "gopkg.in/redis.v5"
|
||||
|
||||
"github.com/apex/log"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultBufferSize = 500
|
||||
defaultRedisAddr = "127.0.0.1:6379"
|
||||
)
|
||||
|
||||
// Config vars for the application
|
||||
type Config struct {
|
||||
// AppName is the application name.
|
||||
// AppName is the application name and checkpoint namespace.
|
||||
AppName string
|
||||
|
||||
// StreamName is the Kinesis stream.
|
||||
|
|
@ -26,6 +30,9 @@ type Config struct {
|
|||
|
||||
// Logger is the logger used. Defaults to log.Log.
|
||||
Logger log.Interface
|
||||
|
||||
// Checkpoint for tracking progress of consumer.
|
||||
Checkpoint Checkpoint
|
||||
}
|
||||
|
||||
// defaults for configuration.
|
||||
|
|
@ -60,4 +67,32 @@ func (c *Config) setDefaults() {
|
|||
if c.FlushInterval == 0 {
|
||||
c.FlushInterval = time.Second
|
||||
}
|
||||
|
||||
if c.Checkpoint == nil {
|
||||
client, err := redisClient()
|
||||
if err != nil {
|
||||
c.Logger.WithError(err).Error("Redis connection failed")
|
||||
os.Exit(1)
|
||||
}
|
||||
c.Checkpoint = &RedisCheckpoint{
|
||||
AppName: c.AppName,
|
||||
StreamName: c.StreamName,
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func redisClient() (*redis.Client, error) {
|
||||
redisURL := os.Getenv("REDIS_URL")
|
||||
if redisURL == "" {
|
||||
redisURL = defaultRedisAddr
|
||||
}
|
||||
client := redis.NewClient(&redis.Options{
|
||||
Addr: redisURL,
|
||||
})
|
||||
_, err := client.Ping().Result()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
|
|
|||
11
consumer.go
11
consumer.go
|
|
@ -54,19 +54,14 @@ func (c *Consumer) handlerLoop(shardID string, handler Handler) {
|
|||
MaxRecordCount: c.BufferSize,
|
||||
}
|
||||
|
||||
checkpoint := &Checkpoint{
|
||||
AppName: c.AppName,
|
||||
StreamName: c.StreamName,
|
||||
}
|
||||
|
||||
params := &kinesis.GetShardIteratorInput{
|
||||
ShardId: aws.String(shardID),
|
||||
StreamName: aws.String(c.StreamName),
|
||||
}
|
||||
|
||||
if checkpoint.CheckpointExists(shardID) {
|
||||
if c.Checkpoint.CheckpointExists(shardID) {
|
||||
params.ShardIteratorType = aws.String("AFTER_SEQUENCE_NUMBER")
|
||||
params.StartingSequenceNumber = aws.String(checkpoint.SequenceNumber())
|
||||
params.StartingSequenceNumber = aws.String(c.Checkpoint.SequenceNumber())
|
||||
} else {
|
||||
params.ShardIteratorType = aws.String("TRIM_HORIZON")
|
||||
}
|
||||
|
|
@ -103,7 +98,7 @@ func (c *Consumer) handlerLoop(shardID string, handler Handler) {
|
|||
if buf.ShouldFlush() {
|
||||
handler.HandleRecords(*buf)
|
||||
ctx.WithField("count", buf.RecordCount()).Info("flushed")
|
||||
checkpoint.SetCheckpoint(shardID, buf.LastSeq())
|
||||
c.Checkpoint.SetCheckpoint(shardID, buf.LastSeq())
|
||||
buf.Flush()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
53
redis_checkpoint.go
Normal file
53
redis_checkpoint.go
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package connector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"gopkg.in/redis.v5"
|
||||
)
|
||||
|
||||
// RedisCheckpoint implements the Checkpont interface.
|
||||
// Used to enable the Pipeline.ProcessShard to checkpoint it's progress
|
||||
// while reading records from Kinesis stream.
|
||||
type RedisCheckpoint struct {
|
||||
AppName string
|
||||
StreamName string
|
||||
|
||||
client *redis.Client
|
||||
sequenceNumber string
|
||||
}
|
||||
|
||||
// CheckpointExists determines if a checkpoint for a particular Shard exists.
|
||||
// Typically used to determine whether we should start processing the shard with
|
||||
// TRIM_HORIZON or AFTER_SEQUENCE_NUMBER (if checkpoint exists).
|
||||
func (c *RedisCheckpoint) CheckpointExists(shardID string) bool {
|
||||
val, _ := c.client.Get(c.key(shardID)).Result()
|
||||
|
||||
if val != "" {
|
||||
c.sequenceNumber = val
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SequenceNumber returns the current checkpoint stored for the specified shard.
|
||||
func (c *RedisCheckpoint) SequenceNumber() string {
|
||||
return c.sequenceNumber
|
||||
}
|
||||
|
||||
// SetCheckpoint stores a checkpoint for a shard (e.g. sequence number of last record processed by application).
|
||||
// Upon failover, record processing is resumed from this point.
|
||||
func (c *RedisCheckpoint) SetCheckpoint(shardID string, sequenceNumber string) {
|
||||
err := c.client.Set(c.key(shardID), sequenceNumber, 0).Err()
|
||||
if err != nil {
|
||||
log.Printf("redis checkpoint set error: %v", err)
|
||||
}
|
||||
c.sequenceNumber = sequenceNumber
|
||||
}
|
||||
|
||||
// key generates a unique Redis key for storage of Checkpoint.
|
||||
func (c *RedisCheckpoint) key(shardID string) string {
|
||||
return fmt.Sprintf("%v:checkpoint:%v:%v", c.AppName, c.StreamName, shardID)
|
||||
}
|
||||
50
redis_checkpoint_test.go
Normal file
50
redis_checkpoint_test.go
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package connector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gopkg.in/redis.v5"
|
||||
)
|
||||
|
||||
var defaultAddr = "127.0.0.1:6379"
|
||||
|
||||
func Test_CheckpointLifecycle(t *testing.T) {
|
||||
client := redis.NewClient(&redis.Options{Addr: defaultAddr})
|
||||
|
||||
c := RedisCheckpoint{
|
||||
AppName: "app",
|
||||
StreamName: "stream",
|
||||
client: client,
|
||||
}
|
||||
|
||||
// set checkpoint
|
||||
c.SetCheckpoint("shard_id", "testSeqNum")
|
||||
|
||||
// checkpoint exists
|
||||
if val := c.CheckpointExists("shard_id"); val != true {
|
||||
t.Fatalf("checkpoint exists expected true, got %t", val)
|
||||
}
|
||||
|
||||
// get checkpoint
|
||||
if val := c.SequenceNumber(); val != "testSeqNum" {
|
||||
t.Fatalf("checkpoint exists expected %s, got %s", "testSeqNum", val)
|
||||
}
|
||||
|
||||
client.Del("app:checkpoint:stream:shard_id")
|
||||
}
|
||||
|
||||
func Test_key(t *testing.T) {
|
||||
client := redis.NewClient(&redis.Options{Addr: defaultAddr})
|
||||
|
||||
c := &RedisCheckpoint{
|
||||
AppName: "app",
|
||||
StreamName: "stream",
|
||||
client: client,
|
||||
}
|
||||
|
||||
expected := "app:checkpoint:stream:shard"
|
||||
|
||||
if val := c.key("shard"); val != expected {
|
||||
t.Fatalf("checkpoint exists expected %s, got %s", expected, val)
|
||||
}
|
||||
}
|
||||
166
vendor/manifest
vendored
166
vendor/manifest
vendored
|
|
@ -1,166 +0,0 @@
|
|||
{
|
||||
"version": 0,
|
||||
"dependencies": [
|
||||
{
|
||||
"importpath": "github.com/apex/log",
|
||||
"repository": "https://github.com/apex/log",
|
||||
"vcs": "git",
|
||||
"revision": "c20bfcdb771b706fdd57a954ee9da2d0ff97b02d",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/apex/log/handlers/discard",
|
||||
"repository": "https://github.com/apex/log",
|
||||
"vcs": "git",
|
||||
"revision": "c20bfcdb771b706fdd57a954ee9da2d0ff97b02d",
|
||||
"branch": "master",
|
||||
"path": "/handlers/discard",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/aws/aws-sdk-go/aws",
|
||||
"repository": "https://github.com/aws/aws-sdk-go",
|
||||
"vcs": "git",
|
||||
"revision": "966f1a968ba8e260628dfa6be07bcd48d8e98ef6",
|
||||
"branch": "master",
|
||||
"path": "/aws",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/aws/aws-sdk-go/aws/session",
|
||||
"repository": "https://github.com/aws/aws-sdk-go",
|
||||
"vcs": "git",
|
||||
"revision": "966f1a968ba8e260628dfa6be07bcd48d8e98ef6",
|
||||
"branch": "master",
|
||||
"path": "/aws/session",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/aws/aws-sdk-go/private/endpoints",
|
||||
"repository": "https://github.com/aws/aws-sdk-go",
|
||||
"vcs": "git",
|
||||
"revision": "966f1a968ba8e260628dfa6be07bcd48d8e98ef6",
|
||||
"branch": "master",
|
||||
"path": "/private/endpoints",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/aws/aws-sdk-go/private/protocol",
|
||||
"repository": "https://github.com/aws/aws-sdk-go",
|
||||
"vcs": "git",
|
||||
"revision": "966f1a968ba8e260628dfa6be07bcd48d8e98ef6",
|
||||
"branch": "master",
|
||||
"path": "/private/protocol",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/aws/aws-sdk-go/private/signer/v4",
|
||||
"repository": "https://github.com/aws/aws-sdk-go",
|
||||
"vcs": "git",
|
||||
"revision": "966f1a968ba8e260628dfa6be07bcd48d8e98ef6",
|
||||
"branch": "master",
|
||||
"path": "/private/signer/v4",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/aws/aws-sdk-go/private/waiter",
|
||||
"repository": "https://github.com/aws/aws-sdk-go",
|
||||
"vcs": "git",
|
||||
"revision": "966f1a968ba8e260628dfa6be07bcd48d8e98ef6",
|
||||
"branch": "master",
|
||||
"path": "/private/waiter",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/aws/aws-sdk-go/service/kinesis",
|
||||
"repository": "https://github.com/aws/aws-sdk-go",
|
||||
"vcs": "git",
|
||||
"revision": "966f1a968ba8e260628dfa6be07bcd48d8e98ef6",
|
||||
"branch": "master",
|
||||
"path": "/service/kinesis",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/go-ini/ini",
|
||||
"repository": "https://github.com/go-ini/ini",
|
||||
"vcs": "git",
|
||||
"revision": "12f418cc7edc5a618a51407b7ac1f1f512139df3",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/go-logfmt/logfmt",
|
||||
"repository": "https://github.com/go-logfmt/logfmt",
|
||||
"vcs": "git",
|
||||
"revision": "08ab82a63ef462ac643ec79e659f023891f588f5",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/hoisie/redis",
|
||||
"repository": "https://github.com/hoisie/redis",
|
||||
"vcs": "git",
|
||||
"revision": "788f01e396a99c96c8f56338383926f16841ebae",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/jmespath/go-jmespath",
|
||||
"repository": "https://github.com/jmespath/go-jmespath",
|
||||
"vcs": "git",
|
||||
"revision": "0b12d6b521d83fc7f755e7cfc1b1fbdd35a01a74",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/jpillora/backoff",
|
||||
"repository": "https://github.com/jpillora/backoff",
|
||||
"vcs": "git",
|
||||
"revision": "0496a6c14df020789376f4d4a261273d5ddb36ec",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/kr/pretty",
|
||||
"repository": "https://github.com/kr/pretty",
|
||||
"vcs": "git",
|
||||
"revision": "add1dbc86daf0f983cd4a48ceb39deb95c729b67",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/kr/text",
|
||||
"repository": "https://github.com/kr/text",
|
||||
"vcs": "git",
|
||||
"revision": "bb797dc4fb8320488f47bf11de07a733d7233e1f",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/rogpeppe/fastuuid",
|
||||
"repository": "https://github.com/rogpeppe/fastuuid",
|
||||
"vcs": "git",
|
||||
"revision": "6724a57986aff9bff1a1770e9347036def7c89f6",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/tj/go-elastic/batch",
|
||||
"repository": "https://github.com/tj/go-elastic",
|
||||
"vcs": "git",
|
||||
"revision": "6923cdab333be878d768a2b563cd25bc816c3dab",
|
||||
"branch": "master",
|
||||
"path": "/batch",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/tj/go-kinesis",
|
||||
"repository": "https://github.com/tj/go-kinesis",
|
||||
"vcs": "git",
|
||||
"revision": "677d118cb62c634d6d8dc7c49e979c4d40fac58b",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
}
|
||||
]
|
||||
}
|
||||
309
vendor/vendor.json
vendored
Normal file
309
vendor/vendor.json
vendored
Normal file
|
|
@ -0,0 +1,309 @@
|
|||
{
|
||||
"comment": "",
|
||||
"ignore": "test",
|
||||
"package": [
|
||||
{
|
||||
"checksumSHA1": "Ur88QI//9Ue82g83qvBSakGlzVg=",
|
||||
"path": "github.com/apex/log",
|
||||
"revision": "4ea85e918cc8389903d5f12d7ccac5c23ab7d89b",
|
||||
"revisionTime": "2016-09-05T15:13:04Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "o5a5xWoaGDKEnNy0W7TikB66lMc=",
|
||||
"path": "github.com/apex/log/handlers/text",
|
||||
"revision": "4ea85e918cc8389903d5f12d7ccac5c23ab7d89b",
|
||||
"revisionTime": "2016-09-05T15:13:04Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "dSo0vFXJGuTtd6H80q8ZczLszJM=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Y9W+4GimK4Fuxq+vyIskVYFRnX4=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/awserr",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "dkfyy7aRNZ6BmUZ4ZdLIcMMXiPA=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/awsutil",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "H/tMKHZU+Qka6RtYiGB50s2uA0s=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/client",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "ieAJ+Cvp/PKv1LpUEnUXpc3OI6E=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/client/metadata",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "gNWirlrTfSLbOe421hISBAhTqa4=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/corehandlers",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "dNZNaOPfBPnzE2CBnfhXXZ9g9jU=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/credentials",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "KQiUK/zr3mqnAXD7x/X55/iNme0=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "NUJUTWlc1sV8b7WjfiYc4JZbXl0=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/credentials/endpointcreds",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "4Ipx+5xN0gso+cENC2MHMWmQlR4=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/credentials/stscreds",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "nCMd1XKjgV21bEl7J8VZFqTV8PE=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/defaults",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "U0SthWum+t9ACanK7SDJOg3dO6M=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/ec2metadata",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "NyUg1P8ZS/LHAAQAk/4C5O4X3og=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/request",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "tBdFneml1Vn7uvezcktsa+hUsGg=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/session",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "7lla+sckQeF18wORAGuU2fFMlp4=",
|
||||
"path": "github.com/aws/aws-sdk-go/aws/signer/v4",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Bm6UrYb2QCzpYseLwwgw6aetgRc=",
|
||||
"path": "github.com/aws/aws-sdk-go/private/endpoints",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "wk7EyvDaHwb5qqoOP/4d3cV0708=",
|
||||
"path": "github.com/aws/aws-sdk-go/private/protocol",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "L7xWYwx0jNQnzlYHwBS+1q6DcCI=",
|
||||
"path": "github.com/aws/aws-sdk-go/private/protocol/json/jsonutil",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "H9TymcQkQnXSXSVfjggiiS4bpzM=",
|
||||
"path": "github.com/aws/aws-sdk-go/private/protocol/jsonrpc",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "isoix7lTx4qIq2zI2xFADtti5SI=",
|
||||
"path": "github.com/aws/aws-sdk-go/private/protocol/query",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "5xzix1R8prUyWxgLnzUQoxTsfik=",
|
||||
"path": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "TW/7U+/8ormL7acf6z2rv2hDD+s=",
|
||||
"path": "github.com/aws/aws-sdk-go/private/protocol/rest",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Y6Db2GGfGD9LPpcJIPj8vXE8BbQ=",
|
||||
"path": "github.com/aws/aws-sdk-go/private/protocol/restxml",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "eUEkjyMPAuekKBE4ou+nM9tXEas=",
|
||||
"path": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Eo9yODN5U99BK0pMzoqnBm7PCrY=",
|
||||
"path": "github.com/aws/aws-sdk-go/private/waiter",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "TtIAgZ+evpkKB5bBYCB69k0wZoU=",
|
||||
"path": "github.com/aws/aws-sdk-go/service/firehose",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "2n5/m0ClE4OyQRNdjfLwg+nSY3o=",
|
||||
"path": "github.com/aws/aws-sdk-go/service/kinesis",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "fgZ1cdh2T0cWRorIZkMGFDADMQw=",
|
||||
"path": "github.com/aws/aws-sdk-go/service/kinesis/kinesisiface",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "imxJucuPrgaPRMPtAgsu+Y7soB4=",
|
||||
"path": "github.com/aws/aws-sdk-go/service/s3",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "nH/itbdeFHpl4ysegdtgww9bFSA=",
|
||||
"path": "github.com/aws/aws-sdk-go/service/sts",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "zUyQXVCSaV97bbiVZbX1qn8UWm4=",
|
||||
"path": "github.com/bmizerany/assert",
|
||||
"revision": "e17e99893cb6509f428e1728281c2ad60a6b31e3",
|
||||
"revisionTime": "2012-07-16T20:56:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "i7BD7wKsIrix92VtlJ4zQRP4G8c=",
|
||||
"path": "github.com/crowdmob/goamz/aws",
|
||||
"revision": "3a06871fe9fc0281ca90f3a7d97258d042ed64c0",
|
||||
"revisionTime": "2015-01-28T19:49:25Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "qijq0UWIx8EKPT+GbsbuaZMw/gA=",
|
||||
"path": "github.com/crowdmob/goamz/s3",
|
||||
"revision": "3a06871fe9fc0281ca90f3a7d97258d042ed64c0",
|
||||
"revisionTime": "2015-01-28T19:49:25Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "FCeEm2BWZV/n4oTy+SGd/k0Ab5c=",
|
||||
"origin": "github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini",
|
||||
"path": "github.com/go-ini/ini",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "0ZrwvB6KoGPj2PoDNSEJwxQ6Mog=",
|
||||
"origin": "github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath",
|
||||
"path": "github.com/jmespath/go-jmespath",
|
||||
"revision": "f34b74c96bfd27df35643adeb14d8431ca047df5",
|
||||
"revisionTime": "2016-08-17T18:35:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "IXVypCQsDOlWf8dqyFogbOsRdvM=",
|
||||
"path": "github.com/jpillora/backoff",
|
||||
"revision": "0496a6c14df020789376f4d4a261273d5ddb36ec",
|
||||
"revisionTime": "2016-04-14T05:52:04Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "1YeGotQXMZMqk+mmm8sbBVJywpw=",
|
||||
"path": "github.com/kr/pretty",
|
||||
"revision": "e6ac2fc51e89a3249e82157fa0bb7a18ef9dd5bb",
|
||||
"revisionTime": "2015-05-20T16:35:14Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "uulQHQ7IsRKqDudBC8Go9J0gtAc=",
|
||||
"path": "github.com/kr/text",
|
||||
"revision": "bb797dc4fb8320488f47bf11de07a733d7233e1f",
|
||||
"revisionTime": "2015-09-05T22:45:08Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Tivm2ueYu71B9YxTEyGxe+8ZWgk=",
|
||||
"path": "github.com/lib/pq",
|
||||
"revision": "f59175c2986495ff94109dee3835c504a96c3e81",
|
||||
"revisionTime": "2016-01-27T22:38:42Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "xppHi82MLqVx1eyQmbhTesAEjx8=",
|
||||
"path": "github.com/lib/pq/oid",
|
||||
"revision": "f59175c2986495ff94109dee3835c504a96c3e81",
|
||||
"revisionTime": "2016-01-27T22:38:42Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "QI1tJqI+jMmFrCAKcXs+LefgES4=",
|
||||
"path": "github.com/tj/go-kinesis",
|
||||
"revision": "817ff40136c6d4909bcff1021e58fdedf788ba23",
|
||||
"revisionTime": "2016-06-02T03:00:41Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "+4r0PnLwwyhO5/jvU5R/TEJb4kA=",
|
||||
"path": "gopkg.in/bsm/ratelimit.v1",
|
||||
"revision": "db14e161995a5177acef654cb0dd785e8ee8bc22",
|
||||
"revisionTime": "2016-02-20T15:49:07Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "JtXTQXRlxRB///NYmPDuMpEpvNI=",
|
||||
"path": "gopkg.in/redis.v5",
|
||||
"revision": "854c88a72c8bb9c09936145aef886b7697d6b995",
|
||||
"revisionTime": "2016-12-03T15:45:52Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "vQSE4FOH4EvyzYA72w60XOetmVY=",
|
||||
"path": "gopkg.in/redis.v5/internal",
|
||||
"revision": "854c88a72c8bb9c09936145aef886b7697d6b995",
|
||||
"revisionTime": "2016-12-03T15:45:52Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "2Ek4SixeRSKOX3mUiBMs3Aw+Guc=",
|
||||
"path": "gopkg.in/redis.v5/internal/consistenthash",
|
||||
"revision": "854c88a72c8bb9c09936145aef886b7697d6b995",
|
||||
"revisionTime": "2016-12-03T15:45:52Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "rJYVKcBrwYUGl7nuuusmZGrt8mY=",
|
||||
"path": "gopkg.in/redis.v5/internal/hashtag",
|
||||
"revision": "854c88a72c8bb9c09936145aef886b7697d6b995",
|
||||
"revisionTime": "2016-12-03T15:45:52Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "VnsHRPAMRMuhz7/n/85MZwMrchQ=",
|
||||
"path": "gopkg.in/redis.v5/internal/pool",
|
||||
"revision": "854c88a72c8bb9c09936145aef886b7697d6b995",
|
||||
"revisionTime": "2016-12-03T15:45:52Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "604uyPTNWLBNAnAyNRMiwYHXknA=",
|
||||
"path": "gopkg.in/redis.v5/internal/proto",
|
||||
"revision": "854c88a72c8bb9c09936145aef886b7697d6b995",
|
||||
"revisionTime": "2016-12-03T15:45:52Z"
|
||||
}
|
||||
],
|
||||
"rootPath": "github.com/harlow/kinesis-connectors"
|
||||
}
|
||||
Loading…
Reference in a new issue