Skip to content

Commit

Permalink
Merge pull request #97 from supertokens/staggered-network-requests
Browse files Browse the repository at this point in the history
refactor: Staggered network requests for 0.1
  • Loading branch information
rishabhpoddar authored Jul 18, 2023
2 parents 16a8083 + 34c1341 commit d3a2448
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 22 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [unreleased]

## [0.1.4] - 2023-07-18

- Refactor logic for making network requests

## [0.1.3] - 2022-09-26

### Changes
Expand Down
2 changes: 1 addition & 1 deletion build/static/css/main.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/static/js/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/static/js/bundle.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dashboard",
"version": "0.1.3",
"version": "0.1.4",
"private": true,
"dependencies": {
"@babel/core": "^7.16.0",
Expand Down
100 changes: 85 additions & 15 deletions src/services/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,41 @@ import { HttpMethod } from "../types";
* License for the specific language governing permissions and limitations
* under the License.
*/
class RequestQueueManager {
static requestQueue: { [key: string]: () => Promise<Response> } = {};
static waiters: { [key: string]: (response: Response) => void } = {};
static isProcessing = false;

static addRequestToQueue(request: () => Promise<Response>, waiter: (response: Response) => void): string {
const id = `${Date.now()}.${Math.floor(Math.random() * 1000)}`;
RequestQueueManager.requestQueue[id] = request;
RequestQueueManager.waiters[id] = waiter;
void this.processRequest();
return id;
}

static async processRequest() {
if (RequestQueueManager.isProcessing) {
return;
}

if (Object.keys(RequestQueueManager.requestQueue).length === 0) {
return;
}

RequestQueueManager.isProcessing = true;
const requestId = Object.keys(RequestQueueManager.requestQueue)[0];
const request = RequestQueueManager.requestQueue[requestId];
const waiter = RequestQueueManager.waiters[requestId];
delete RequestQueueManager.requestQueue[requestId];
delete RequestQueueManager.waiters[requestId];
const response = await request();
waiter(response);
RequestQueueManager.isProcessing = false;
void RequestQueueManager.processRequest();
}
}

export default class NetworkManager {
static async doRequest({
url,
Expand All @@ -26,11 +61,57 @@ export default class NetworkManager {
query?: { [key: string]: string };
config?: RequestInit;
}) {
if (method === "GET") {
return this.get(url, query, config);
}
const queuedRequestFunction = () => {
if (method === "GET") {
return this.get(url, query, config);
}

/**
* If the user's backend has a validation for the request body being missing, it is
* possible that it will fail for some of the dashboard requests (for example api
* key validation).
*
* This ensures that a body is always sent to the server even if the API itself does
* not consume it
*/
let bodyToUse: BodyInit = JSON.stringify({});

return this.post(url, config);
if (config !== undefined && config.body !== null && config.body !== undefined) {
bodyToUse = config.body;
}

return fetch(new URL(url), {
...config,
body: bodyToUse,
method,
headers: {
...config?.headers,
"Content-Type": "application/json",
},
});
};

let requestCompleted = false;
let response: Response;

RequestQueueManager.addRequestToQueue(queuedRequestFunction, (_response) => {
requestCompleted = true;
response = _response;
});

const waitForResponse = async () => {
while (!requestCompleted) {
await new Promise((resolve) => {
setTimeout(resolve, 10);
});
}
};

await waitForResponse();

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return response;
}

private static async get(url: string, query?: { [key: string]: string }, config?: RequestInit) {
Expand All @@ -45,15 +126,4 @@ export default class NetworkManager {

return fetch(_url, config);
}

private static async post(url: string, config?: RequestInit) {
return fetch(new URL(url), {
...config,
method: "POST",
headers: {
...config?.headers,
"Content-Type": "application/json",
},
});
}
}
2 changes: 1 addition & 1 deletion src/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
* under the License.
*/

export const package_version = "0.1.3";
export const package_version = "0.1.4";

0 comments on commit d3a2448

Please sign in to comment.