code: func (r *RateLimiter) Attempt(id string) (bool, error) {
  	// Create hash from id
  	hash := r.hasher.Hash(id)
  
  	// Get value for hash in Redis. If redis.Nil is returned, key does not
  	// exist.
  	exists := true
  
  	val, err := r.redisClient.Get(hash).Result()
  	if err != nil {
  		if err == redis.Nil {
  			// Key does not exist. See: http://redis.io/commands/GET
  			exists = false
  		} else {
  			return false, err
  		}
  	}
  
  	// If key exists and is >= max requests, return false.
  	if exists {
  		intVal, err := strconv.ParseInt(val, 10, 64)
  		if err != nil {
  			return false, err
  		}
  
  		if intVal >= r.max {
  			return false, nil
  		}
  	}
  
  	// Otherwise, increment and expire key for hasher.Duration(). Note, we call
  	// Expire even when key already exists to avoid race condition where key
  	// expires between prior existence check and this Incr call.
  	//
  	// See: http://redis.io/commands/INCR
  	// See: http://redis.io/commands/INCR#pattern-rate-limiter-1
  	err = r.redisClient.Watch(func(rx *redis.Tx) error {
  		_, err := rx.Pipelined(func(pipe *redis.Pipeline) error {
  			if err := pipe.Incr(hash).Err(); err != nil {
  				return err
  			}
  
  			return pipe.Expire(hash, r.hasher.Duration()).Err()
  		})
  
  		return err
  	})
  
  	if err != nil {
  		return false, err
  	}
  
  	return true, nil
  }
docs: // Attempt attempts to perform a request for an id and returns whether it was
  // successful or not.