diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 7ee05a914..74990e875 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -127,7 +127,7 @@ }, { "ImportPath": "github.com/andybalholm/cascadia", - "Rev": "1c31af6f6c1a7b101ed05aacc7d8a738b43ae86e" + "Rev": "65919c611220063037b1db8eb334acaf17a6d8ea" }, { "ImportPath": "github.com/boltdb/bolt", @@ -163,6 +163,10 @@ "ImportPath": "github.com/jpillora/ansi", "Rev": "7e36a06e08cc6f803f6f0cc6a1f5f99ef571d1e4" }, + { + "ImportPath": "github.com/jpillora/backoff", + "Rev": "a6f64285fd4072883335339357436b78d62c96a4" + }, { "ImportPath": "github.com/jpillora/go-realtime", "Rev": "c8b52e99fa07b59183859c03304ea01f04e4921f" @@ -225,15 +229,15 @@ }, { "ImportPath": "golang.org/x/net/context", - "Rev": "65dfc08770ce66f74becfdff5f8ab01caef4e946" + "Rev": "4971afdc2f162e82d185353533d3cf16188a9f4e" }, { "ImportPath": "golang.org/x/net/html", - "Rev": "65dfc08770ce66f74becfdff5f8ab01caef4e946" + "Rev": "4971afdc2f162e82d185353533d3cf16188a9f4e" }, { "ImportPath": "golang.org/x/net/html/atom", - "Rev": "65dfc08770ce66f74becfdff5f8ab01caef4e946" + "Rev": "4971afdc2f162e82d185353533d3cf16188a9f4e" }, { "ImportPath": "golang.org/x/sys/unix", diff --git a/vendor/github.com/andybalholm/cascadia/parser.go b/vendor/github.com/andybalholm/cascadia/parser.go index 6fc22039b..3325b8619 100644 --- a/vendor/github.com/andybalholm/cascadia/parser.go +++ b/vendor/github.com/andybalholm/cascadia/parser.go @@ -395,6 +395,8 @@ func (p *parser) parseAttributeSelector() (Selector, error) { switch op { case "=": return attributeEqualsSelector(key, val), nil + case "!=": + return attributeNotEqualSelector(key, val), nil case "~=": return attributeIncludesSelector(key, val), nil case "|=": diff --git a/vendor/github.com/andybalholm/cascadia/selector.go b/vendor/github.com/andybalholm/cascadia/selector.go index e906f7d29..684c4a1eb 100644 --- a/vendor/github.com/andybalholm/cascadia/selector.go +++ b/vendor/github.com/andybalholm/cascadia/selector.go @@ -169,6 +169,23 @@ func attributeEqualsSelector(key, val string) Selector { }) } +// attributeNotEqualSelector returns a Selector that matches elements where +// the attribute named key does not have the value val. +func attributeNotEqualSelector(key, val string) Selector { + key = toLowerASCII(key) + return func(n *html.Node) bool { + if n.Type != html.ElementNode { + return false + } + for _, a := range n.Attr { + if a.Key == key && a.Val == val { + return false + } + } + return true + } +} + // attributeIncludesSelector returns a Selector that matches elements where // the attribute named key is a whitespace-separated list that includes val. func attributeIncludesSelector(key, val string) Selector { diff --git a/vendor/github.com/jpillora/backoff/README.md b/vendor/github.com/jpillora/backoff/README.md new file mode 100644 index 000000000..4f4c3e7f2 --- /dev/null +++ b/vendor/github.com/jpillora/backoff/README.md @@ -0,0 +1,142 @@ +# Backoff + +A simple exponential backoff counter in Go (Golang) + +[![GoDoc](https://godoc.org/github.com/jpillora/backoff?status.svg)](https://godoc.org/github.com/jpillora/backoff) [![Circle CI](https://circleci.com/gh/jpillora/backoff.svg?style=shield)](https://circleci.com/gh/jpillora/backoff) + +### Install + +``` +$ go get -v github.com/jpillora/backoff +``` + +### Usage + +Backoff is a `time.Duration` counter. It starts at `Min`. After every call to `Duration()` it is multiplied by `Factor`. It is capped at `Max`. It returns to `Min` on every call to `Reset()`. `Jitter` adds randomness ([see below](#example-using-jitter)). Used in conjunction with the `time` package. + +--- + +#### Simple example + +``` go + +b := &backoff.Backoff{ + //These are the defaults + Min: 100 * time.Millisecond, + Max: 10 * time.Second, + Factor: 2, + Jitter: false, +} + +fmt.Printf("%s\n", b.Duration()) +fmt.Printf("%s\n", b.Duration()) +fmt.Printf("%s\n", b.Duration()) + +fmt.Printf("Reset!\n") +b.Reset() + +fmt.Printf("%s\n", b.Duration()) +``` + +``` +100ms +200ms +400ms +Reset! +100ms +``` + +--- + +#### Example using `net` package + +``` go +b := &backoff.Backoff{ + Max: 5 * time.Minute, +} + +for { + conn, err := net.Dial("tcp", "example.com:5309") + if err != nil { + d := b.Duration() + fmt.Printf("%s, reconnecting in %s", err, d) + time.Sleep(d) + continue + } + //connected + b.Reset() + conn.Write([]byte("hello world!")) + // ... Read ... Write ... etc + conn.Close() + //disconnected +} + +``` + +--- + +#### Example using `Jitter` + +Enabling `Jitter` adds some randomization to the backoff durations. [See Amazon's writeup of performance gains using jitter](http://www.awsarchitectureblog.com/2015/03/backoff.html). Seeding is not necessary but doing so gives repeatable results. + +```go +import "math/rand" + +b := &backoff.Backoff{ + Jitter: true, +} + +rand.Seed(42) + +fmt.Printf("%s\n", b.Duration()) +fmt.Printf("%s\n", b.Duration()) +fmt.Printf("%s\n", b.Duration()) + +fmt.Printf("Reset!\n") +b.Reset() + +fmt.Printf("%s\n", b.Duration()) +fmt.Printf("%s\n", b.Duration()) +fmt.Printf("%s\n", b.Duration()) +``` + +``` +100ms +106.600049ms +281.228155ms +Reset! +100ms +104.381845ms +214.957989ms +``` + +#### Documentation + +https://godoc.org/github.com/jpillora/backoff + +#### Credits + +Ported from some JavaScript written by [@tj](https://github.com/tj) + +#### MIT License + +Copyright © 2015 Jaime Pillora <dev@jpillora.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/jpillora/backoff/backoff.go b/vendor/github.com/jpillora/backoff/backoff.go new file mode 100644 index 000000000..a6380e0d9 --- /dev/null +++ b/vendor/github.com/jpillora/backoff/backoff.go @@ -0,0 +1,79 @@ +package backoff + +import ( + "math" + "math/rand" + "time" +) + +//Backoff is a time.Duration counter. It starts at Min. +//After every call to Duration() it is multiplied by Factor. +//It is capped at Max. It returns to Min on every call to Reset(). +//Used in conjunction with the time package. +// +// Backoff is not threadsafe, but the ForAttempt method can be +// used concurrently if non-zero values for Factor, Max, and Min +// are set on the Backoff shared among threads. +type Backoff struct { + //Factor is the multiplying factor for each increment step + attempt, Factor float64 + //Jitter eases contention by randomizing backoff steps + Jitter bool + //Min and Max are the minimum and maximum values of the counter + Min, Max time.Duration +} + +//Returns the current value of the counter and then +//multiplies it Factor +func (b *Backoff) Duration() time.Duration { + d := b.ForAttempt(b.attempt) + b.attempt++ + return d +} + +// ForAttempt returns the duration for a specific attempt. This is useful if +// you have a large number of independent Backoffs, but don't want use +// unnecessary memory storing the Backoff parameters per Backoff. The first +// attempt should be 0. +// +// ForAttempt is threadsafe iff non-zero values for Factor, Max, and Min +// are set before any calls to ForAttempt are made. +func (b *Backoff) ForAttempt(attempt float64) time.Duration { + if float64(b.Min) > float64(b.Max) { + return b.Max + } + + //Zero-values are nonsensical, so we use + //them to apply defaults + if b.Min == 0 { + b.Min = 100 * time.Millisecond + } + if b.Max == 0 { + b.Max = 10 * time.Second + } + if b.Factor == 0 { + b.Factor = 2 + } + + //calculate this duration + dur := float64(b.Min) * math.Pow(b.Factor, attempt) + if b.Jitter == true { + dur = rand.Float64()*(dur-float64(b.Min)) + float64(b.Min) + } + //cap! + if dur > float64(b.Max) { + return b.Max + } + //return as a time.Duration + return time.Duration(dur) +} + +//Resets the current value of the counter back to Min +func (b *Backoff) Reset() { + b.attempt = 0 +} + +//Get the current backoff attempt +func (b *Backoff) Attempt() float64 { + return b.attempt +}