octokit-load-balancer 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -36
- package/dist/index.js +5 -6
- package/dist/index.mjs +5 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
|
-
- **Multiple App Support** - Pool multiple GitHub Apps for higher aggregate rate limits
|
|
11
10
|
- **Smart Selection** - Always picks the app with the most available rate limit
|
|
12
11
|
- **Auto Key Detection** - Automatically detects raw PEM vs base64 encoded private keys
|
|
13
12
|
- **TypeScript First** - Full type definitions using Octokit types
|
|
@@ -16,7 +15,7 @@
|
|
|
16
15
|
## Installation
|
|
17
16
|
|
|
18
17
|
```bash
|
|
19
|
-
npm install octokit-load-balancer
|
|
18
|
+
npm install octokit-load-balancer
|
|
20
19
|
```
|
|
21
20
|
|
|
22
21
|
## Usage
|
|
@@ -47,7 +46,7 @@ await octokit.rest.repos.get({ owner: 'your-org', repo: 'your-repo' });
|
|
|
47
46
|
|
|
48
47
|
Every time you call `getApp(config)`:
|
|
49
48
|
|
|
50
|
-
1. Creates Octokit instances for
|
|
49
|
+
1. Creates Octokit instances for each app
|
|
51
50
|
2. Fetches rate limits for all apps in parallel
|
|
52
51
|
3. Returns the Octokit with the highest remaining rate limit
|
|
53
52
|
|
|
@@ -60,37 +59,6 @@ Every time you call `getApp(config)`:
|
|
|
60
59
|
|
|
61
60
|
App configs use `GitHubAppConfig` (re-exported from `@octokit/auth-app`'s `StrategyOptions`). All apps must have valid `appId` and `privateKey` — incomplete configs will throw an error.
|
|
62
61
|
|
|
63
|
-
##
|
|
62
|
+
## Scalability
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
| | octokit-load-balancer | plugin-throttling |
|
|
68
|
-
| ------------------ | ---------------------------------- | ------------------------- |
|
|
69
|
-
| Strategy | Pick app with most remaining quota | Queue and retry on limits |
|
|
70
|
-
| Multiple apps | Yes | No |
|
|
71
|
-
| Handles exhaustion | Throws | Waits and retries |
|
|
72
|
-
|
|
73
|
-
Choose based on your situation:
|
|
74
|
-
|
|
75
|
-
- **Need more than 5000 requests/hour?** → Create multiple GitHub Apps and use this library to distribute load across them (N apps = N × 5000 req/hr)
|
|
76
|
-
- **Single app, need graceful handling?** → Use plugin-throttling to wait and retry
|
|
77
|
-
|
|
78
|
-
## Debugging
|
|
79
|
-
|
|
80
|
-
Enable debug logs with the `DEBUG` environment variable:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
DEBUG=octokit-load-balancer node your-script.js
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Output:
|
|
87
|
-
|
|
88
|
-
```
|
|
89
|
-
[octokit-load-balancer] Using 2 valid app configs
|
|
90
|
-
[octokit-load-balancer] Rate limits: app[0]: 4500/5000, app[1]: 4900/5000
|
|
91
|
-
[octokit-load-balancer] Selected app[1] with 4900/5000 remaining
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## License
|
|
95
|
-
|
|
96
|
-
MIT
|
|
64
|
+
This library is designed for high-throughput scenarios where a single GitHub App's rate limit (5,000 requests/hour) isn't enough. By distributing requests across multiple apps, you get N × 5,000 requests/hour.
|
package/dist/index.js
CHANGED
|
@@ -32,8 +32,8 @@ async function getApp(config) {
|
|
|
32
32
|
if (!Array.isArray(config?.apps)) {
|
|
33
33
|
throw new Error("Invalid config: apps must be an array");
|
|
34
34
|
}
|
|
35
|
-
if (typeof config?.baseUrl !== "string") {
|
|
36
|
-
throw new Error("Invalid config: baseUrl must be a string");
|
|
35
|
+
if (typeof config?.baseUrl !== "string" || !config.baseUrl) {
|
|
36
|
+
throw new Error("Invalid config: baseUrl must be a non-empty string");
|
|
37
37
|
}
|
|
38
38
|
if (config.apps.length === 0) {
|
|
39
39
|
throw new Error("Invalid config: apps array is empty");
|
|
@@ -44,9 +44,8 @@ async function getApp(config) {
|
|
|
44
44
|
`Invalid config: ${invalidApps.length} app(s) missing required appId or privateKey`
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const octokits = validApps.map((app) => createOctokit(app, config.baseUrl));
|
|
47
|
+
log(`Using ${config.apps.length} app configs`);
|
|
48
|
+
const octokits = config.apps.map((app) => createOctokit(app, config.baseUrl));
|
|
50
49
|
const rateLimits = await Promise.all(
|
|
51
50
|
octokits.map((o, i) => getRateLimit(o, i))
|
|
52
51
|
);
|
|
@@ -83,7 +82,7 @@ function decodePrivateKey(key) {
|
|
|
83
82
|
function createOctokit(appConfig, baseUrl) {
|
|
84
83
|
return new import_octokit.Octokit({
|
|
85
84
|
authStrategy: import_auth_app.createAppAuth,
|
|
86
|
-
baseUrl
|
|
85
|
+
baseUrl,
|
|
87
86
|
auth: {
|
|
88
87
|
appId: appConfig.appId,
|
|
89
88
|
installationId: appConfig.installationId,
|
package/dist/index.mjs
CHANGED
|
@@ -6,8 +6,8 @@ async function getApp(config) {
|
|
|
6
6
|
if (!Array.isArray(config?.apps)) {
|
|
7
7
|
throw new Error("Invalid config: apps must be an array");
|
|
8
8
|
}
|
|
9
|
-
if (typeof config?.baseUrl !== "string") {
|
|
10
|
-
throw new Error("Invalid config: baseUrl must be a string");
|
|
9
|
+
if (typeof config?.baseUrl !== "string" || !config.baseUrl) {
|
|
10
|
+
throw new Error("Invalid config: baseUrl must be a non-empty string");
|
|
11
11
|
}
|
|
12
12
|
if (config.apps.length === 0) {
|
|
13
13
|
throw new Error("Invalid config: apps array is empty");
|
|
@@ -18,9 +18,8 @@ async function getApp(config) {
|
|
|
18
18
|
`Invalid config: ${invalidApps.length} app(s) missing required appId or privateKey`
|
|
19
19
|
);
|
|
20
20
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const octokits = validApps.map((app) => createOctokit(app, config.baseUrl));
|
|
21
|
+
log(`Using ${config.apps.length} app configs`);
|
|
22
|
+
const octokits = config.apps.map((app) => createOctokit(app, config.baseUrl));
|
|
24
23
|
const rateLimits = await Promise.all(
|
|
25
24
|
octokits.map((o, i) => getRateLimit(o, i))
|
|
26
25
|
);
|
|
@@ -57,7 +56,7 @@ function decodePrivateKey(key) {
|
|
|
57
56
|
function createOctokit(appConfig, baseUrl) {
|
|
58
57
|
return new Octokit({
|
|
59
58
|
authStrategy: createAppAuth,
|
|
60
|
-
baseUrl
|
|
59
|
+
baseUrl,
|
|
61
60
|
auth: {
|
|
62
61
|
appId: appConfig.appId,
|
|
63
62
|
installationId: appConfig.installationId,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "octokit-load-balancer",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Load balance across multiple GitHub App instances, always picking the one with most available rate limit",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"repository": {
|
|
43
43
|
"type": "git",
|
|
44
|
-
"url": "https://github.com/frankie303/octokit-load-balancer"
|
|
44
|
+
"url": "git+https://github.com/frankie303/octokit-load-balancer.git"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"@octokit/auth-app": "^7.0.0",
|