@@ -88,9 +88,9 @@ type Session struct {
8888 User * api.GitHubUser
8989}
9090
91- // ListSessionsForViewer lists all agent sessions for the
91+ // ListLatestSessionsForViewer lists all agent sessions for the
9292// authenticated user up to limit.
93- func (c * CAPIClient ) ListSessionsForViewer (ctx context.Context , limit int ) ([]* Session , error ) {
93+ func (c * CAPIClient ) ListLatestSessionsForViewer (ctx context.Context , limit int ) ([]* Session , error ) {
9494 if limit == 0 {
9595 return nil , nil
9696 }
@@ -99,7 +99,8 @@ func (c *CAPIClient) ListSessionsForViewer(ctx context.Context, limit int) ([]*S
9999 pageSize := defaultSessionsPerPage
100100
101101 sessions := make ([]session , 0 , limit + pageSize )
102-
102+ seenResources := make (map [int64 ]struct {})
103+ latestSessions := make ([]session , 0 , limit )
103104 for page := 1 ; ; page ++ {
104105 req , err := http .NewRequestWithContext (ctx , http .MethodGet , url , http .NoBody )
105106 if err != nil {
@@ -109,6 +110,7 @@ func (c *CAPIClient) ListSessionsForViewer(ctx context.Context, limit int) ([]*S
109110 q := req .URL .Query ()
110111 q .Set ("page_size" , strconv .Itoa (pageSize ))
111112 q .Set ("page_number" , strconv .Itoa (page ))
113+ q .Set ("sort" , "last_updated_at,desc" )
112114 req .URL .RawQuery = q .Encode ()
113115
114116 res , err := c .httpClient .Do (req )
@@ -126,81 +128,45 @@ func (c *CAPIClient) ListSessionsForViewer(ctx context.Context, limit int) ([]*S
126128 return nil , fmt .Errorf ("failed to decode sessions response: %w" , err )
127129 }
128130
129- sessions = append (sessions , response .Sessions ... )
130- if len (response .Sessions ) < pageSize || len (sessions ) >= limit {
131- break
132- }
133- }
134-
135- // Drop any above the limit
136- if len (sessions ) > limit {
137- sessions = sessions [:limit ]
138- }
139-
140- result , err := c .hydrateSessionPullRequestsAndUsers (sessions )
141- if err != nil {
142- return nil , fmt .Errorf ("failed to fetch session resources: %w" , err )
143- }
144-
145- return result , nil
146- }
147-
148- // ListSessionsForRepo lists agent sessions for a specific repository identified by owner/name up to limit.
149- func (c * CAPIClient ) ListSessionsForRepo (ctx context.Context , owner string , repo string , limit int ) ([]* Session , error ) {
150- if owner == "" || repo == "" {
151- return nil , fmt .Errorf ("owner and repo are required" )
152- }
131+ // Process only the newly fetched page worth of sessions.
132+ pageSessions := response .Sessions
133+ sessions = append (sessions , pageSessions ... )
153134
154- if limit == 0 {
155- return nil , nil
156- }
157-
158- url := fmt .Sprintf ("%s/agents/sessions/nwo/%s/%s" , baseCAPIURL , url .PathEscape (owner ), url .PathEscape (repo ))
159- pageSize := defaultSessionsPerPage
160-
161- sessions := make ([]session , 0 , limit + pageSize )
162-
163- for page := 1 ; ; page ++ {
164- req , err := http .NewRequestWithContext (ctx , http .MethodGet , url , http .NoBody )
165- if err != nil {
166- return nil , err
167- }
135+ // De-duplicate sessions by resource ID.
136+ // Because the API returns newest first, once we've seen
137+ // a resource ID we can ignore any older sessions for it.
138+ for _ , s := range pageSessions {
139+ if _ , exists := seenResources [s .ResourceID ]; exists {
140+ continue
141+ }
168142
169- q := req .URL .Query ()
170- q .Set ("page_size" , strconv .Itoa (pageSize ))
171- q .Set ("page_number" , strconv .Itoa (page ))
172- req .URL .RawQuery = q .Encode ()
143+ // A zero resource ID is a temporary situation before a PR/resource
144+ // is associated with the session. We should not mark such case as seen.
145+ if s .ResourceID != 0 {
146+ seenResources [s .ResourceID ] = struct {}{}
147+ }
173148
174- res , err := c .httpClient .Do (req )
175- if err != nil {
176- return nil , err
177- }
178- defer res .Body .Close ()
179- if res .StatusCode != http .StatusOK {
180- return nil , fmt .Errorf ("failed to list sessions: %s" , res .Status )
181- }
182- var response struct {
183- Sessions []session `json:"sessions"`
184- }
185- if err := json .NewDecoder (res .Body ).Decode (& response ); err != nil {
186- return nil , fmt .Errorf ("failed to decode sessions response: %w" , err )
149+ latestSessions = append (latestSessions , s )
150+ if len (latestSessions ) >= limit {
151+ break
152+ }
187153 }
188154
189- sessions = append (sessions , response .Sessions ... )
190- if len (response .Sessions ) < pageSize || len (sessions ) >= limit {
155+ if len (response .Sessions ) < pageSize || len (latestSessions ) >= limit {
191156 break
192157 }
193158 }
194159
195160 // Drop any above the limit
196- if len (sessions ) > limit {
197- sessions = sessions [:limit ]
161+ if len (latestSessions ) > limit {
162+ latestSessions = latestSessions [:limit ]
198163 }
199164
200- result , err := c .hydrateSessionPullRequestsAndUsers (sessions )
165+ result , err := c .hydrateSessionPullRequestsAndUsers (latestSessions )
201166 if err != nil {
202167 return nil , fmt .Errorf ("failed to fetch session resources: %w" , err )
203168 }
169+
204170 return result , nil
205171}
206172
0 commit comments