Explorar o código

fix infinite loop issue with github organisations endpoint

Signed-off-by: Ishan Khare <me@ishankhare.dev>
Ishan Khare %!s(int64=4) %!d(string=hai) anos
pai
achega
3d36e268c0
Modificáronse 1 ficheiros con 62 adicións e 14 borrados
  1. 62 14
      api/server/handlers/gitinstallation/get_accounts.go

+ 62 - 14
api/server/handlers/gitinstallation/get_accounts.go

@@ -2,8 +2,10 @@ package gitinstallation
 
 import (
 	"context"
+	"fmt"
 	"net/http"
 	"sort"
+	"time"
 
 	"github.com/google/go-github/github"
 	"github.com/porter-dev/porter/api/server/authz"
@@ -31,6 +33,41 @@ func NewGetGithubAppAccountsHandler(
 	}
 }
 
+func (c *GetGithubAppAccountsHandler) getOrgList(ctx context.Context,
+	client *github.Client,
+	orgsChan chan<- *github.Organization,
+	errChan chan<- error) {
+	defer close(orgsChan)
+	defer close(errChan)
+
+	for {
+		select {
+		case <-ctx.Done():
+			return
+		default:
+			orgs, pages, err := client.Organizations.List(context.Background(), "", &github.ListOptions{
+				PerPage: 100,
+				Page:    1,
+			})
+
+			if err != nil {
+				fmt.Println("error occured while fetching organisations. error:", err.Error())
+				errChan <- err
+				return
+			}
+
+			for _, org := range orgs {
+				orgsChan <- org
+				// res.Accounts = append(res.Accounts, *org.Login)
+			}
+
+			if pages.NextPage == 0 {
+				return
+			}
+		}
+	}
+}
+
 func (c *GetGithubAppAccountsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	tok, err := GetGithubAppOauthTokenFromRequest(c.Config(), r)
 
@@ -42,26 +79,37 @@ func (c *GetGithubAppAccountsHandler) ServeHTTP(w http.ResponseWriter, r *http.R
 	client := github.NewClient(c.Config().GithubAppConf.Client(oauth2.NoContext, tok))
 	res := &types.GetGithubAppAccountsResponse{}
 
-	for {
-		orgs, pages, err := client.Organizations.List(context.Background(), "", &github.ListOptions{
-			PerPage: 100,
-			Page:    1,
-		})
+	resultChannel := make(chan *github.Organization, 10)
+	errChan := make(chan error)
 
-		if err != nil {
-			continue
-		}
+	ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
+	defer cancel()
 
-		for _, org := range orgs {
-			res.Accounts = append(res.Accounts, *org.Login)
-		}
+	go c.getOrgList(ctx, client, resultChannel, errChan)
 
-		if pages.NextPage == 0 {
-			break
+resultOrErrorReader:
+	for {
+		select {
+		case result, ok := <-resultChannel:
+			if ok {
+				res.Accounts = append(res.Accounts, *result.Login)
+			} else {
+				// channel has been closed now
+				// close(errChan)
+				break resultOrErrorReader
+			}
+		case err, ok := <-errChan:
+			if ok {
+				c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+				return
+			} else {
+				// nothing in error, must be a close event
+				break resultOrErrorReader
+			}
 		}
 	}
 
-	authUser, _, err := client.Users.Get(context.Background(), "")
+	authUser, _, err := client.Users.Get(r.Context(), "")
 
 	if err != nil {
 		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))