Skip to content

Commit

Permalink
Block communication in client class when rate limited according to Da…
Browse files Browse the repository at this point in the history
…ikin response
  • Loading branch information
Apollon77 committed Jul 6, 2024
1 parent cbd390b commit 4681618
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ See [`src/example.ts`](./src/example.ts).
* Add Tests

## Changelog:
### __WORK IN PROGRESS__
* Block communication in client class when rate limited according to Daikin response

### 2.1.1 (2024-07-05)
* Expose the Rate limit error retryAfter time in the error object

Expand Down
18 changes: 17 additions & 1 deletion src/onecta/oidc-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ import {
import { startOnectaOIDCCallbackServer } from './oidc-callback-server.js';
import { RateLimitedError } from "../index";

type RequestParameters = Parameters<typeof BaseClient.prototype.requestResource>[2] & {
ignoreRateLimit?: boolean;
}

export class OnectaClient {
#config: OnectaClientConfig;
#client: BaseClient;
#tokenSet: TokenSet | null;
#emitter: EventEmitter;
#getTokenSetQueue: { resolve: (set: TokenSet) => any, reject: (err: Error) => any }[];
#blockedUntil: number = 0;

constructor(config: OnectaClientConfig, emitter: EventEmitter) {
this.#config = config;
Expand All @@ -39,6 +44,10 @@ export class OnectaClient {
}
}

get blockedUntil(): number {
return this.#blockedUntil;
}

async #authorize(): Promise<TokenSet> {
const redirectUri = this.#config.oidcCallbackServerBaseUrl;
const reqState = randomBytes(32).toString('hex');
Expand Down Expand Up @@ -140,7 +149,11 @@ export class OnectaClient {
};
}

async requestResource(path: string, opts?: Parameters<typeof BaseClient.prototype.requestResource>[2]): Promise<any> {
async requestResource(path: string, opts?: RequestParameters): Promise<any> {
if (!opts?.ignoreRateLimit && this.#blockedUntil > Date.now()) {
const retryAfter = Math.ceil((this.#blockedUntil - Date.now()) / 1000);
throw new RateLimitedError(`API request rate-limited, retry after ${retryAfter} seconds`, retryAfter);
}
const tokenSet = await this.#getTokenSetQueued();
const url = `${OnectaAPIBaseUrl.prod}${path}`;
const res = await this.#client.requestResource(url, tokenSet, opts);
Expand All @@ -160,6 +173,9 @@ export class OnectaClient {
case 429: {
// See "Rate limitation" at https://developer.cloud.daikineurope.com/docs/b0dffcaa-7b51-428a-bdff-a7c8a64195c0/general_api_guidelines
const retryAfter = maybeParseInt(res.headers['retry-after']);
if (retryAfter !== undefined) {
this.#blockedUntil = Date.now() + retryAfter * 1000;
}
throw new RateLimitedError(`API request rate-limited, retry after ${retryAfter} seconds`, retryAfter);
}
case 500:
Expand Down

0 comments on commit 4681618

Please sign in to comment.