bgpwtf/cccampix/irr: limit concurrency

Change-Id: I958322f33c86469f9c3e21d1bd962faede2a3fee
diff --git a/bgpwtf/cccampix/irr/provider/ripe.go b/bgpwtf/cccampix/irr/provider/ripe.go
index 5b09b9f..291494d 100644
--- a/bgpwtf/cccampix/irr/provider/ripe.go
+++ b/bgpwtf/cccampix/irr/provider/ripe.go
@@ -11,6 +11,8 @@
 	"net/http"
 
 	pb "code.hackerspace.pl/hscloud/bgpwtf/cccampix/proto"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
 )
 
 type ripeResponse struct {
@@ -32,13 +34,21 @@
 }
 
 type ripe struct {
+	sem chan struct{}
 }
 
-func NewRIPE() Provider {
-	return &ripe{}
+func NewRIPE(limit int) Provider {
+	return &ripe{
+		sem: make(chan struct{}, limit),
+	}
 }
 
 func (r *ripe) Query(ctx context.Context, as uint64) (*pb.IRRQueryResponse, error) {
+	r.sem <- struct{}{}
+	defer func() {
+		<-r.sem
+	}()
+
 	req, err := http.NewRequest("GET", fmt.Sprintf("http://rest.db.ripe.net/ripe/aut-num/AS%d.json", as), nil)
 	if err != nil {
 		return nil, err
@@ -49,22 +59,22 @@
 
 	res, err := client.Do(req)
 	if err != nil {
-		return nil, fmt.Errorf("could not run GET to RIPE: %v", err)
+		return nil, status.Errorf(codes.Unavailable, "could not run GET to RIPE: %v", err)
 	}
 	defer res.Body.Close()
 	bytes, err := ioutil.ReadAll(res.Body)
 	if err != nil {
-		return nil, fmt.Errorf("could not read response from RIPE: %v", err)
+		return nil, status.Errorf(codes.Unavailable, "could not read response from RIPE: %v", err)
 	}
 
 	data := ripeResponse{}
 	err = json.Unmarshal(bytes, &data)
 	if err != nil {
-		return nil, fmt.Errorf("could not decode response from RIPE: %v", err)
+		return nil, status.Errorf(codes.Unavailable, "could not decode response from RIPE: %v", err)
 	}
 
 	if len(data.Objects.Object) != 1 {
-		return nil, fmt.Errorf("could not retriev aut-num from RIPE")
+		return nil, status.Error(codes.NotFound, "could not retrieve aut-num from RIPE")
 	}
 
 	attributes := make([]rpslRawAttribute, len(data.Objects.Object[0].Attributes.Attribute))