Skip to content

Commit f2a37ba

Browse files
authored
Add an event for when PR model changes (#7310)
Part 1: add the event and dispose better Still to be done: - delete _onDidInvalidate - move timeline back into model
1 parent 4d19419 commit f2a37ba

12 files changed

+272
-109
lines changed

src/commands.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,9 +1347,7 @@ ${contents}
13471347
if (prQuery) {
13481348
for (const githubRepos of (manager?.gitHubRepositories ?? [])) {
13491349
const prNumber = Number(prQuery.prNumber);
1350-
if (githubRepos.pullRequestModels.has(prNumber)) {
1351-
return githubRepos.pullRequestModels.get(prNumber);
1352-
}
1350+
return githubRepos.getExistingPullRequestModel(prNumber);
13531351
}
13541352
}
13551353
} else {
@@ -1732,8 +1730,8 @@ ${contents}
17321730
for (const folderManager of reposManager.folderManagers) {
17331731
for (const githubRepository of folderManager.gitHubRepositories) {
17341732
for (const pullRequest of githubRepository.pullRequestModels) {
1735-
if (pullRequest[1].isResolved() && pullRequest[1].reviewThreadsCacheReady) {
1736-
pullRequest[1].initializeReviewThreadCache();
1733+
if (pullRequest.isResolved() && pullRequest.reviewThreadsCacheReady) {
1734+
pullRequest.initializeReviewThreadCache();
17371735
}
17381736
}
17391737
}

src/github/createPRViewProvider.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,10 @@ export abstract class BaseCreatePullRequestViewProvider<T extends BasePullReques
278278
return;
279279
}
280280
try {
281-
// TODO: We need to resolve the user and then use the replace function.
282-
await pr.addAssignees([resolved]);
281+
const user = await pr.githubRepository.resolveUser(resolved);
282+
if (user) {
283+
await pr.replaceAssignees([user]);
284+
}
283285
} catch (e) {
284286
Logger.error(`Unable to assign pull request to user ${resolved}.`, BaseCreatePullRequestViewProvider.ID);
285287
}

src/github/folderRepositoryManager.ts

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import { ConflictResolutionCoordinator } from './conflictResolutionCoordinator';
4343
import { Conflict, ConflictResolutionModel } from './conflictResolutionModel';
4444
import { CredentialStore } from './credentials';
4545
import { CopilotWorkingStatus, GitHubRepository, GraphQLError, GraphQLErrorType, IMetadata, ItemsData, PULL_REQUEST_PAGE_SIZE, PullRequestData, TeamReviewerRefreshKind, ViewerPermission } from './githubRepository';
46-
import { MergeMethod as GraphQLMergeMethod, MergePullRequestInput, MergePullRequestResponse, PullRequestResponse, PullRequestState, UserResponse } from './graphql';
46+
import { MergeMethod as GraphQLMergeMethod, MergePullRequestInput, MergePullRequestResponse, PullRequestResponse, PullRequestState } from './graphql';
4747
import { IAccount, ILabel, IMilestone, IProject, IPullRequestsPagingOptions, Issue, ITeam, MergeMethod, PRType, PullRequestMergeability, RepoAccessAndMergeMethods, User } from './interface';
4848
import { IssueModel } from './issueModel';
4949
import { PullRequestGitHelper, PullRequestMetadata } from './pullRequestGitHelper';
@@ -56,7 +56,6 @@ import {
5656
loginComparator,
5757
parseCombinedTimelineEvents,
5858
parseGraphQLPullRequest,
59-
parseGraphQLUser,
6059
teamComparator,
6160
variableSubstitution,
6261
} from './utils';
@@ -2221,23 +2220,7 @@ export class FolderRepositoryManager extends Disposable {
22212220
async resolveUser(owner: string, repositoryName: string, login: string): Promise<User | undefined> {
22222221
Logger.debug(`Fetch user ${login}`, this.id);
22232222
const githubRepository = await this.createGitHubRepositoryFromOwnerName(owner, repositoryName);
2224-
const { query, schema } = await githubRepository.ensure();
2225-
2226-
try {
2227-
const { data } = await query<UserResponse>({
2228-
query: schema.GetUser,
2229-
variables: {
2230-
login,
2231-
},
2232-
});
2233-
return parseGraphQLUser(data, githubRepository);
2234-
} catch (e) {
2235-
// Ignore cases where the user doesn't exist
2236-
if (!(e.message as (string | undefined))?.startsWith('GraphQL error: Could not resolve to a User with the login of')) {
2237-
Logger.warn(e.message);
2238-
}
2239-
}
2240-
return undefined;
2223+
return githubRepository.resolveUser(login);
22412224
}
22422225

22432226
async getMatchingPullRequestMetadataForBranch() {

src/github/githubRepository.ts

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55

66
import * as buffer from 'buffer';
77
import { ApolloQueryResult, DocumentNode, FetchResult, MutationOptions, NetworkStatus, QueryOptions } from 'apollo-boost';
8+
import LRUCache from 'lru-cache';
89
import * as vscode from 'vscode';
910
import { AuthenticationError, AuthProvider, GitHubServerType, isSamlError } from '../common/authentication';
1011
import { COPILOT_ACCOUNTS, IComment, IReviewThread } from '../common/comment';
11-
import { Disposable } from '../common/lifecycle';
12+
import { Disposable, disposeAll } from '../common/lifecycle';
1213
import Logger from '../common/logger';
1314
import { GitHubRemote, parseRemote } from '../common/remote';
1415
import { ITelemetry } from '../common/telemetry';
@@ -43,6 +44,7 @@ import {
4344
RevertPullRequestResponse,
4445
SuggestedActorsResponse,
4546
TimelineEventsResponse,
47+
UserResponse,
4648
ViewerPermissionResponse,
4749
} from './graphql';
4850
import {
@@ -57,6 +59,7 @@ import {
5759
PullRequestChecks,
5860
PullRequestReviewRequirement,
5961
RepoAccessAndMergeMethods,
62+
User,
6063
} from './interface';
6164
import { IssueModel } from './issueModel';
6265
import { LoggingOctokit } from './loggingOctokit';
@@ -76,6 +79,7 @@ import {
7679
parseCombinedTimelineEvents,
7780
parseGraphQLIssue,
7881
parseGraphQLPullRequest,
82+
parseGraphQLUser,
7983
parseGraphQLViewerPermission,
8084
parseMergeMethod,
8185
parseMilestone,
@@ -162,7 +166,13 @@ export class GitHubRepository extends Disposable {
162166
protected _metadata: Promise<IMetadata> | undefined;
163167
public commentsController?: vscode.CommentController;
164168
public commentsHandler?: PRCommentControllerRegistry;
165-
private _pullRequestModels = new Map<number, PullRequestModel>();
169+
private _pullRequestModelsByNumber: LRUCache<number, { model: PullRequestModel, disposables: vscode.Disposable[] }> = new LRUCache({
170+
maxAge: 1000 * 60 * 60 * 4 /* 4 hours */, stale: true, updateAgeOnGet: true,
171+
dispose: (_key, value) => {
172+
disposeAll(value.disposables);
173+
value.model.dispose();
174+
}
175+
});
166176
private _queriesSchema: any;
167177
private _areQueriesLimited: boolean = false;
168178

@@ -186,8 +196,12 @@ export class GitHubRepository extends Disposable {
186196
return this.remote.equals(repo.remote);
187197
}
188198

189-
get pullRequestModels(): Map<number, PullRequestModel> {
190-
return this._pullRequestModels;
199+
getExistingPullRequestModel(prNumber: number): PullRequestModel | undefined {
200+
return this._pullRequestModelsByNumber.get(prNumber)?.model;
201+
}
202+
203+
get pullRequestModels(): PullRequestModel[] {
204+
return Array.from(this._pullRequestModelsByNumber.values().map(value => value.model));
191205
}
192206

193207
public async ensureCommentsController(): Promise<void> {
@@ -940,19 +954,26 @@ export class GitHubRepository extends Disposable {
940954
}
941955

942956
createOrUpdatePullRequestModel(pullRequest: PullRequest): PullRequestModel {
943-
let model = this._pullRequestModels.get(pullRequest.number);
957+
let model = this._pullRequestModelsByNumber.get(pullRequest.number)?.model;
944958
if (model) {
945959
model.update(pullRequest);
946960
} else {
947961
model = new PullRequestModel(this._credentialStore, this._telemetry, this, this.remote, pullRequest);
962+
const prModel = model;
948963
model.onDidInvalidate(() => this.getPullRequest(pullRequest.number));
949-
this._pullRequestModels.set(pullRequest.number, model);
964+
const disposables: vscode.Disposable[] = [];
965+
disposables.push(model.onDidChange(() => this._onPullRequestModelChanged(prModel)));
966+
this._pullRequestModelsByNumber.set(pullRequest.number, { model, disposables });
950967
this._onDidAddPullRequest.fire(model);
951968
}
952969

953970
return model;
954971
}
955972

973+
private _onPullRequestModelChanged(model: PullRequestModel): void {
974+
this._onDidChangePullRequests.fire([model]);
975+
}
976+
956977
async createPullRequest(params: OctokitCommon.PullsCreateParams): Promise<PullRequestModel> {
957978
try {
958979
Logger.debug(`Create pull request - enter`, this.id);
@@ -1233,6 +1254,27 @@ export class GitHubRepository extends Disposable {
12331254
return ret;
12341255
}
12351256

1257+
async resolveUser(login: string): Promise<User | undefined> {
1258+
Logger.debug(`Fetch user ${login}`, this.id);
1259+
const { query, schema } = await this.ensure();
1260+
1261+
try {
1262+
const { data } = await query<UserResponse>({
1263+
query: schema.GetUser,
1264+
variables: {
1265+
login,
1266+
},
1267+
});
1268+
return parseGraphQLUser(data, this);
1269+
} catch (e) {
1270+
// Ignore cases where the user doesn't exist
1271+
if (!(e.message as (string | undefined))?.startsWith('GraphQL error: Could not resolve to a User with the login of')) {
1272+
Logger.warn(e.message);
1273+
}
1274+
}
1275+
return undefined;
1276+
}
1277+
12361278
async getAssignableUsers(): Promise<IAccount[]> {
12371279
Logger.debug(`Fetch assignable users - enter`, this.id);
12381280
const { query, remote, schema } = await this.ensure();
@@ -1554,9 +1596,9 @@ export class GitHubRepository extends Disposable {
15541596
return [event.source.url, event];
15551597
}));
15561598

1557-
for (const model of this._pullRequestModels.values()) {
1558-
if (crossRefs.has(model.html_url)) {
1559-
crossRefs.delete(model.html_url);
1599+
for (const pr of this._pullRequestModelsByNumber.values()) {
1600+
if (crossRefs.has(pr.model.html_url)) {
1601+
crossRefs.delete(pr.model.html_url);
15601602
}
15611603
}
15621604
const oldEvents = issueModel.timelineEvents;

src/github/graphql.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,13 @@ export interface UpdateIssueResponse {
558558
bodyHTML: string;
559559
title: string;
560560
titleHTML: string;
561+
milestone?: {
562+
title: string;
563+
dueOn?: string;
564+
id: string;
565+
createdAt: string;
566+
number: number;
567+
};
561568
};
562569
};
563570
}

0 commit comments

Comments
 (0)