11package linear
22
3- import "time"
3+ import (
4+ "context"
5+ "fmt"
6+ "strings"
7+ "time"
8+
9+ "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
10+ "go.uber.org/zap"
11+ )
412
513type PageInfo struct {
614 EndCursor string `json:"endCursor"`
@@ -93,7 +101,8 @@ type Project struct {
93101type GraphQLError struct {
94102 Error string `json:"error"`
95103 Errors []struct {
96- Message string `json:"message"`
104+ Message string `json:"message"`
105+ Extensions map [string ]interface {} `json:"extensions,omitempty"`
97106 } `json:"errors"`
98107}
99108
@@ -107,6 +116,50 @@ func (e *GraphQLError) Message() string {
107116 return e .Errors [0 ].Message
108117}
109118
119+ // IsRateLimited checks if the error contains Linear's RATELIMITED error code.
120+ func (e * GraphQLError ) IsRateLimited () bool {
121+ // Get logger from context if available, otherwise use a default logger
122+ ctx := context .Background ()
123+ l := ctxzap .Extract (ctx )
124+
125+ for _ , err := range e .Errors {
126+ // Log the error message and extensions for debugging
127+ l .Info ("checking GraphQL error for rate limiting" ,
128+ zap .String ("message" , err .Message ),
129+ zap .Any ("extensions" , err .Extensions ))
130+
131+ if extensions , ok := err .Extensions ["code" ]; ok {
132+ l .Info ("found 'code' extension" ,
133+ zap .Any ("code_value" , extensions ),
134+ zap .String ("code_type" , fmt .Sprintf ("%T" , extensions )))
135+
136+ if code , ok := extensions .(string ); ok && code == "RATELIMITED" {
137+ l .Info ("rate limited detected via code extension" ,
138+ zap .String ("code" , code ))
139+ return true
140+ } else {
141+ l .Info ("code extension is not 'RATELIMITED'" ,
142+ zap .Any ("got_value" , extensions ),
143+ zap .String ("got_type" , fmt .Sprintf ("%T" , extensions )))
144+ }
145+ } else {
146+ l .Info ("no 'code' extension found" )
147+ }
148+
149+ // Also check the message for backward compatibility
150+ if strings .Contains (strings .ToLower (err .Message ), "ratelimited" ) {
151+ l .Info ("rate limited detected via message" ,
152+ zap .String ("message" , err .Message ))
153+ return true
154+ } else {
155+ l .Info ("message does not contain 'ratelimited'" ,
156+ zap .String ("message" , err .Message ))
157+ }
158+ }
159+ l .Info ("no rate limiting detected in any GraphQL errors" )
160+ return false
161+ }
162+
110163type ViewerPermissions struct {
111164 Guest bool `json:"guest"`
112165 Admin bool `json:"admin"`
0 commit comments