Skip to content
This repository has been archived by the owner on Oct 25, 2022. It is now read-only.

Commit

Permalink
Better stack traces
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanoverna committed Sep 22, 2020
1 parent daecc1c commit 5752ecd
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 46 deletions.
78 changes: 43 additions & 35 deletions src/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,36 @@ export default class Client {
this.extraHeaders = extraHeaders;
}

get(url, params = {}, options = {}) {
return this.request(this.buildUrl(url, params), options);
get(...args) {
return this.request(this.buildGetRequest(...args));
}

put(url, body, params = {}, options = {}) {
return this.request(this.buildUrl(url, params), {
method: 'PUT',
body: JSON.stringify(body, undefinedToNull),
...options,
});
buildGetRequest(url, params = {}, options = {}) {
return this.buildFetchRequest('GET', url, params, undefined, options);
}

post(url, body, params = {}, options = {}) {
return this.request(this.buildUrl(url, params), {
method: 'POST',
body: JSON.stringify(body, undefinedToNull),
...options,
});
delete(...args) {
return this.request(this.buildDeleteRequest(...args));
}

delete(url, params = {}, options = {}) {
return this.request(this.buildUrl(url, params), {
method: 'DELETE',
...options,
});
buildDeleteRequest(url, params = {}, options = {}) {
return this.buildFetchRequest('DELETE', url, params, undefined, options);
}

put(...args) {
return this.request(this.buildPutRequest(...args));
}

buildPutRequest(url, body, params = {}, options = {}) {
return this.buildFetchRequest('PUT', url, params, body, options);
}

post(...args) {
return this.request(this.buildPostRequest(...args));
}

buildPostRequest(url, body, params = {}, options = {}) {
return this.buildFetchRequest('POST', url, params, body, options);
}

defaultHeaders() {
Expand All @@ -59,25 +64,29 @@ export default class Client {
return `${this.baseUrl}${path}${query}`;
}

request(url, options = {}, retryCount = 1, preCallStack = null) {
const fullHeaders = {
buildFetchRequest(method, url, params, body, extraOptions) {
const options = {
method,
body: body && JSON.stringify(body, undefinedToNull),
...(extraOptions || {}),
};

const headers = {
...this.defaultHeaders(),
...this.extraHeaders,
...options.headers,
};

Object.keys(fullHeaders).forEach(
key => fullHeaders[key] == null && delete fullHeaders[key],
);
Object.keys(headers).forEach(key => !headers[key] && delete headers[key]);

const fullOptions = { ...options, headers: fullHeaders };

if (!preCallStack) {
// eslint-disable-next-line no-param-reassign
preCallStack = new Error().stack;
}
return {
url: this.buildUrl(url, params),
options: { options, ...headers },
};
}

return fetch(url, fullOptions).then(res => {
request(fetchRequest, preCallStack = new Error().stack, retryCount = 1) {
return fetch(fetchRequest.url, fetchRequest.options).then(res => {
if (res.status === 429) {
const waitTime = parseInt(
res.headers.get('X-RateLimit-Reset') || '10',
Expand All @@ -87,7 +96,7 @@ export default class Client {
`Rate limit exceeded, waiting ${waitTime * retryCount} seconds...`,
);
return wait(waitTime * retryCount * 1000).then(() => {
return this.request(url, options, retryCount + 1, preCallStack);
return this.request(fetchRequest, preCallStack, retryCount + 1);
});
}

Expand All @@ -98,8 +107,7 @@ export default class Client {
}
return Promise.reject(
new ApiException(res, body, {
url,
options: fullOptions,
...fetchRequest,
preCallStack,
}),
);
Expand All @@ -117,7 +125,7 @@ export default class Client {
`Data validation in progress, waiting ${retryCount} seconds...`,
);
return wait(retryCount * 1000).then(() => {
return this.request(url, options, retryCount + 1, preCallStack);
return this.request(fetchRequest, preCallStack, retryCount + 1);
});
}
throw error;
Expand Down
53 changes: 42 additions & 11 deletions src/utils/generateClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ export default function generateClient(subdomain, cache, extraMethods = {}) {

const client = new Proxy(cache, {
get(obj1, namespace) {
const preCallStack = new Error().stack;

if (namespace === 'rawClient') {
return rawClient;
}
Expand Down Expand Up @@ -131,7 +133,7 @@ export default function generateClient(subdomain, cache, extraMethods = {}) {
? options.deserializeResponse
: true;

const deserialize = async response => {
const deserialize = async (fetchRequest, response) => {
if (response && response.data.type === 'job') {
let jobResult;
let retryCount = 0;
Expand Down Expand Up @@ -167,6 +169,10 @@ export default function generateClient(subdomain, cache, extraMethods = {}) {
statusText: jobResult.attributes.statusText,
},
jobResult.attributes.payload,
{
...fetchRequest,
preCallStack,
},
);
}

Expand Down Expand Up @@ -208,19 +214,36 @@ export default function generateClient(subdomain, cache, extraMethods = {}) {
}

if (link.method === 'POST') {
const fetchRequest = rawClient.buildPostRequest(
url,
body,
queryString,
);

return rawClient
.post(`${url}`, body, queryString)
.then(response => deserialize(response));
.request(fetchRequest, preCallStack)
.then(response => deserialize(fetchRequest, response));
}
if (link.method === 'PUT') {
const fetchRequest = rawClient.buildPutRequest(
url,
body,
queryString,
);

return rawClient
.put(`${url}`, body, queryString)
.then(response => deserialize(response));
.request(fetchRequest, preCallStack)
.then(response => deserialize(fetchRequest, response));
}
if (link.method === 'DELETE') {
const fetchRequest = rawClient.buildDeleteRequest(
url,
queryString,
);

return rawClient
.delete(url, queryString)
.then(response => deserialize(response));
.request(fetchRequest, preCallStack)
.then(response => deserialize(fetchRequest, response));
}

const allPages = Object.prototype.hasOwnProperty.call(
Expand All @@ -230,11 +253,19 @@ export default function generateClient(subdomain, cache, extraMethods = {}) {
? options.allPages
: false;

const request = allPages
? fetchAllPages(rawClient, url, queryString)
: rawClient.get(url, queryString);
if (allPages) {
const request = fetchAllPages(rawClient, url, queryString);
return request.then(response => deserialize(null, response));
}

const fetchRequest = rawClient.buildGetRequest(
url,
queryString,
);

return request.then(response => deserialize(response));
return rawClient
.request(fetchRequest, preCallStack)
.then(response => deserialize(fetchRequest, response));
});
};
},
Expand Down

0 comments on commit 5752ecd

Please sign in to comment.