Improve feedback for user when Github rate limiting

Alexander Scharinger created

The Github bridge itself should not write anything. This commit removes
code writing to stdout and itroduces an event `ImportEventRateLimiting`
to `core.ImportResult` in order to inform about a rate limiting situation
of the Github GraphQL API. Now the communication with the user is
delegated to the various user interfaces.

Change summary

bridge/core/import.go            | 12 ++++++++++++
bridge/github/import.go          | 10 +++++-----
bridge/github/import_mediator.go |  8 ++++----
3 files changed, 21 insertions(+), 9 deletions(-)

Detailed changes

bridge/core/import.go 🔗

@@ -34,6 +34,9 @@ const (
 	// but not severe enough to consider the import a failure.
 	ImportEventWarning
 
+	// The import system (web API) has reached the rate limit
+	ImportEventRateLimiting
+
 	// Error happened during import
 	ImportEventError
 )
@@ -87,6 +90,8 @@ func (er ImportResult) String() string {
 			parts = append(parts, fmt.Sprintf("err: %s", er.Err))
 		}
 		return strings.Join(parts, " ")
+	case ImportEventRateLimiting:
+		return fmt.Sprintf("rate limiting: %s", er.Reason)
 
 	default:
 		panic("unknown import result")
@@ -165,3 +170,10 @@ func NewImportIdentity(id entity.Id) ImportResult {
 		Event: ImportEventIdentity,
 	}
 }
+
+func NewImportRateLimiting(msg string) ImportResult {
+	return ImportResult{
+		Reason: msg,
+		Event:  ImportEventRateLimiting,
+	}
+}

bridge/github/import.go 🔗

@@ -79,8 +79,8 @@ func (gi *githubImporter) ImportAll(ctx context.Context, repo *cache.RepoCache,
 			nextEvent = gi.getEventHandleMsgs()
 
 			switch event := currEvent.(type) {
-			case MessageEvent:
-				fmt.Println(event.msg)
+			case RateLimitingEvent:
+				out <- core.NewImportRateLimiting(event.msg)
 			case IssueEvent:
 				// first: commit what is being held in currBug
 				if err = gi.commit(currBug, out); err != nil {
@@ -148,9 +148,9 @@ func (gi *githubImporter) getEventHandleMsgs() ImportEvent {
 	for {
 		// read event from import mediator
 		event := gi.mediator.NextImportEvent()
-		// consume (and use) all message events
-		if e, ok := event.(MessageEvent); ok {
-			fmt.Println(e.msg)
+		// consume (and use) all rate limiting events
+		if e, ok := event.(RateLimitingEvent); ok {
+			gi.out <- core.NewImportRateLimiting(e.msg)
 			continue
 		}
 		return event

bridge/github/import_mediator.go 🔗

@@ -47,11 +47,11 @@ type ImportEvent interface {
 	isImportEvent()
 }
 
-type MessageEvent struct {
+type RateLimitingEvent struct {
 	msg string
 }
 
-func (MessageEvent) isImportEvent() {}
+func (RateLimitingEvent) isImportEvent() {}
 
 type IssueEvent struct {
 	issue
@@ -404,11 +404,11 @@ func (mm *importMediator) queryOnce(ctx context.Context, query rateLimiter, vars
 		resetTime := rateLimit.ResetAt.Time
 		// Add a few seconds (8) for good measure
 		resetTime = resetTime.Add(8 * time.Second)
-		msg := fmt.Sprintf("Github GraphQL API rate limit exhausted. Sleeping until %s", resetTime.String())
+		msg := fmt.Sprintf("Github GraphQL API: import will sleep until %s", resetTime.String())
 		select {
 		case <-ctx.Done():
 			return ctx.Err()
-		case mm.importEvents <- MessageEvent{msg}:
+		case mm.importEvents <- RateLimitingEvent{msg}:
 		}
 		timer := time.NewTimer(time.Until(resetTime))
 		select {