Throttling to respect rate limits
This commit is contained in:
parent
346c6fc590
commit
08e49dcf2e
@ -1,4 +1,7 @@
|
|||||||
import { fetchAsync, logUtils } from '@0x/utils';
|
import { fetchAsync, logUtils } from '@0x/utils';
|
||||||
|
import Bottleneck from 'bottleneck';
|
||||||
|
|
||||||
|
const ONE_SECOND = 1000;
|
||||||
|
|
||||||
export interface GithubRepoResponse {
|
export interface GithubRepoResponse {
|
||||||
full_name: string;
|
full_name: string;
|
||||||
@ -68,17 +71,22 @@ export interface GithubIssueResponse {
|
|||||||
// tslint:disable:prefer-function-over-method
|
// tslint:disable:prefer-function-over-method
|
||||||
// ^ Keep consistency with other sources and help logical organization
|
// ^ Keep consistency with other sources and help logical organization
|
||||||
export class GithubSource {
|
export class GithubSource {
|
||||||
public readonly _urlBase: string = 'https://api.github.com';
|
// rate-limit for all API calls through this class instance
|
||||||
public readonly _owner: string;
|
private readonly _limiter: Bottleneck;
|
||||||
public readonly _repo: string;
|
private readonly _urlBase: string = 'https://api.github.com';
|
||||||
public readonly _branch: string;
|
private readonly _owner: string;
|
||||||
public readonly _accessToken: string;
|
private readonly _repo: string;
|
||||||
|
private readonly _branch: string;
|
||||||
|
private readonly _accessToken: string;
|
||||||
|
|
||||||
constructor(owner: string, repo: string, branch: string, accessToken: string) {
|
constructor(owner: string, repo: string, branch: string, accessToken: string, maxReqsPerSecond: number) {
|
||||||
this._owner = owner;
|
this._owner = owner;
|
||||||
this._repo = repo;
|
this._repo = repo;
|
||||||
this._branch = branch;
|
this._branch = branch;
|
||||||
this._accessToken = accessToken;
|
this._accessToken = accessToken;
|
||||||
|
this._limiter = new Bottleneck({
|
||||||
|
minTime: ONE_SECOND / maxReqsPerSecond,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,7 +94,7 @@ export class GithubSource {
|
|||||||
*/
|
*/
|
||||||
public async getGithubRepoAsync(): Promise<GithubRepoResponse> {
|
public async getGithubRepoAsync(): Promise<GithubRepoResponse> {
|
||||||
const url = `${this._urlBase}/repos/${this._owner}/${this._repo}?access_token=${this._accessToken}`;
|
const url = `${this._urlBase}/repos/${this._owner}/${this._repo}?access_token=${this._accessToken}`;
|
||||||
const resp = await fetchAsync(url);
|
const resp = await this._limiter.schedule(() => fetchAsync(url));
|
||||||
const respJson: GithubRepoResponse = await resp.json();
|
const respJson: GithubRepoResponse = await resp.json();
|
||||||
return respJson;
|
return respJson;
|
||||||
}
|
}
|
||||||
@ -98,7 +106,7 @@ export class GithubSource {
|
|||||||
const url = `${this._urlBase}/repos/${this._owner}/${this._repo}/pulls?access_token=${
|
const url = `${this._urlBase}/repos/${this._owner}/${this._repo}/pulls?access_token=${
|
||||||
this._accessToken
|
this._accessToken
|
||||||
}&state=all&per_page=100&page=${page}`;
|
}&state=all&per_page=100&page=${page}`;
|
||||||
const resp = await fetchAsync(url);
|
const resp = await this._limiter.schedule(() => fetchAsync(url));
|
||||||
const respJson: GithubPullRequestResponse[] = await resp.json();
|
const respJson: GithubPullRequestResponse[] = await resp.json();
|
||||||
return respJson;
|
return respJson;
|
||||||
}
|
}
|
||||||
@ -110,7 +118,7 @@ export class GithubSource {
|
|||||||
const url = `${this._urlBase}/repos/${this._owner}/${this._repo}/forks?access_token=${
|
const url = `${this._urlBase}/repos/${this._owner}/${this._repo}/forks?access_token=${
|
||||||
this._accessToken
|
this._accessToken
|
||||||
}&per_page=100&page=${page}`;
|
}&per_page=100&page=${page}`;
|
||||||
const resp = await fetchAsync(url);
|
const resp = await this._limiter.schedule(() => fetchAsync(url));
|
||||||
const respJson: GithubForkResponse[] = await resp.json();
|
const respJson: GithubForkResponse[] = await resp.json();
|
||||||
return respJson;
|
return respJson;
|
||||||
}
|
}
|
||||||
@ -122,7 +130,7 @@ export class GithubSource {
|
|||||||
const url = `${this._urlBase}/repos/${this._owner}/${this._repo}/compare/${
|
const url = `${this._urlBase}/repos/${this._owner}/${this._repo}/compare/${
|
||||||
this._branch
|
this._branch
|
||||||
}...${forkOwner}:${forkBranch}?access_token=${this._accessToken}`;
|
}...${forkOwner}:${forkBranch}?access_token=${this._accessToken}`;
|
||||||
const resp = await fetchAsync(url);
|
const resp = await this._limiter.schedule(() => fetchAsync(url));
|
||||||
const respJson: GithubComparisonResponse = await resp.json();
|
const respJson: GithubComparisonResponse = await resp.json();
|
||||||
return respJson;
|
return respJson;
|
||||||
}
|
}
|
||||||
@ -134,7 +142,7 @@ export class GithubSource {
|
|||||||
const url = `${this._urlBase}/repos/${this._owner}/${this._repo}/issues?access_token=${
|
const url = `${this._urlBase}/repos/${this._owner}/${this._repo}/issues?access_token=${
|
||||||
this._accessToken
|
this._accessToken
|
||||||
}&state=all&per_page=100&page=${page}`;
|
}&state=all&per_page=100&page=${page}`;
|
||||||
const resp = await fetchAsync(url);
|
const resp = await this._limiter.schedule(() => fetchAsync(url));
|
||||||
const respJson: GithubIssueResponse[] = await resp.json();
|
const respJson: GithubIssueResponse[] = await resp.json();
|
||||||
if (!respJson[0]) {
|
if (!respJson[0]) {
|
||||||
logUtils.log(respJson);
|
logUtils.log(respJson);
|
||||||
|
@ -18,6 +18,7 @@ const GITHUB_OWNER = '0xProject';
|
|||||||
const GITHUB_REPO = '0x-monorepo';
|
const GITHUB_REPO = '0x-monorepo';
|
||||||
const GITHUB_BRANCH = 'development';
|
const GITHUB_BRANCH = 'development';
|
||||||
const RECORDS_PER_PAGE = 100;
|
const RECORDS_PER_PAGE = 100;
|
||||||
|
const MAX_REQUESTS_PER_SECOND = 1;
|
||||||
|
|
||||||
let connection: Connection;
|
let connection: Connection;
|
||||||
|
|
||||||
@ -27,7 +28,13 @@ let connection: Connection;
|
|||||||
if (accessToken === undefined) {
|
if (accessToken === undefined) {
|
||||||
throw new Error('Missing required env var: GITHUB_ACCESS_TOKEN');
|
throw new Error('Missing required env var: GITHUB_ACCESS_TOKEN');
|
||||||
}
|
}
|
||||||
const githubSource = new GithubSource(GITHUB_OWNER, GITHUB_REPO, GITHUB_BRANCH, accessToken);
|
const githubSource = new GithubSource(
|
||||||
|
GITHUB_OWNER,
|
||||||
|
GITHUB_REPO,
|
||||||
|
GITHUB_BRANCH,
|
||||||
|
accessToken,
|
||||||
|
MAX_REQUESTS_PER_SECOND,
|
||||||
|
);
|
||||||
const observedTimestamp = Date.now();
|
const observedTimestamp = Date.now();
|
||||||
|
|
||||||
// get repo and save
|
// get repo and save
|
||||||
|
Loading…
x
Reference in New Issue
Block a user