New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
api down management #12
base: master
Are you sure you want to change the base?
api down management #12
Conversation
I have some questions about the application. My backend API uses https://quarkus.io/guides/microprofile-health May be we can have a chat about that ? Thank you |
So I ve understand the whole mecanism. I noticed that you pass undefined as the fourth parameter of the begin function. |
@geniusit sorry for the delayed response! Yes, the initial implementation was missing a handling for when the original API went back up - it should have an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please let me know if you have any questions/concerns on the edits or if I can explain anything further!
src/pages/StatusPage/index.tsx
Outdated
public handleResponse = (api: Api, response: Response) => { | ||
console.log('handleResponse' + response); | ||
const apis = [...this.state.apis]; | ||
const index = apis.findIndex(stateApi => stateApi.api === api); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Object equality in JS won't work here - has to check a property or it will always be false.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I my implementation I did it like this :
const index = apis.findIndex(stateApi => stateApi.api.endpoint === api.endpoint);
Should I change here also ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const index = apis.findIndex(stateApi => stateApi.api === api);
is the way that you do...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it was probably an oversight on my part - it should probably be updated everywhere. I shall note where to update to make sure we get them all 😄
src/pages/StatusPage/index.tsx
Outdated
|
||
this.setState({ | ||
apis, | ||
hasError: hasError, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just pass hasError
. JS/TS will automatically map it.
hasError: hasError, | |
hasError, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, didn't know it ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a neat ES6 trick! https://alligator.io/js/object-property-shorthand-es6/
src/pages/StatusPage/index.tsx
Outdated
hasError: false, | ||
}); | ||
|
||
await begin(this.props.apis, this.handleResponse, this.props.interval); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, we still need the handleError
and the handleResponse
separately.
handleError
will get called specifically if there is an error.
handleResponse
will get called if there's not an error (the API is not down or if it came back up).
The logic needs to be:
handleError
- set error state
handleResponse
- check if previous error state - if there is, iterate through and see if that API is resolved. If no previous error state, do nothing (it's a good response, nothing to update).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check out the last line on the table: https://github.com/katiawheeler/healthy#functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I did some change.
According to your impl Im agree that we still need a way to differentiate Response and Error.
I rename Response with Success.
I propose you to have the handler like this :
- handleSuccess -> onSuccess
- handleError -> onError
- handleDown -> onDown
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we rename onDown
to onApiDown
just so it's clear what is down?
src/services/index.ts
Outdated
/** Begins the chain of API calls */ | ||
export const begin = async ( | ||
apis: Api[], | ||
onError: Handler, | ||
interval?: number, | ||
onResponse?: Handler | ||
) => { | ||
const currentInterval = interval ? interval : 30000; | ||
|
||
apis.forEach(async a => { | ||
await makeCall(a, onError, onResponse || undefined); | ||
}); | ||
|
||
/** Set the timeout and do it again */ | ||
setTimeout( | ||
async () => await begin(apis, onError, currentInterval, onResponse || undefined), | ||
currentInterval | ||
); | ||
export const begin = async (apis: Api[], onResponse: Handler, interval?: number) => { | ||
const currentInterval = interval ? interval : 30000; | ||
|
||
apis.forEach(async a => { | ||
await makeCall(a, onResponse); | ||
}); | ||
|
||
/** Set the timeout and do it again */ | ||
setTimeout(async () => await begin(apis, onResponse, currentInterval), currentInterval); | ||
}; | ||
|
||
/** Make the actual fetch and return a Response object */ | ||
const makeCall = async (api: Api, onError: Handler, onResponse?: Handler) => { | ||
await fetch(api.endpoint) | ||
.then(apiResponse => handleResponse(api, apiResponse, onError, onResponse || undefined)) | ||
// tslint:disable-next-line | ||
.catch(error => console.log('unhandled', error)); | ||
const makeCall = async (api: Api, onResponse: Handler) => { | ||
await fetch(api.endpoint) | ||
.then(apiResponse => handleResponse(api, apiResponse, onResponse)) | ||
// tslint:disable-next-line | ||
.catch(error => handleResponse(api, error, onResponse)); | ||
}; | ||
|
||
/** | ||
* Handles the Response | ||
*/ | ||
const handleResponse = (api: Api, response: Response, onError: Handler, onResponse?: Handler) => { | ||
const apiResponse: ApiResponse = { | ||
code: response.status, | ||
message: response.statusText, | ||
}; | ||
|
||
if (!response.ok) { | ||
onError(api, apiResponse); | ||
return; | ||
} | ||
|
||
if (onResponse) { | ||
onResponse(api, apiResponse); | ||
} | ||
* Handles the Response | ||
*/ | ||
const handleResponse = (api: Api, response: Response, onResponse: Handler) => { | ||
const apiResponse: ApiResponse = { | ||
code: response.status, | ||
message: response.statusText, | ||
}; | ||
|
||
onResponse(api, apiResponse); | ||
}; | ||
|
||
export default { begin, makeCall, handleResponse }; | ||
export default { begin, makeCall, handleResponse }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please revert
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fully reworked it according to your main idea
Also, @geniusit important to note - I am almost done refactoring this library to utilize hooks. I can incorporate your changes in that refactor, or if you'd like I can finish the refactor and you can make the changes using hooks. Whatever you'd like to do I'm fine with 😄 |
@geniusit just checking in that you saw my previous comment and didn't need any further help! |
@katiawheeler just workin on it ! Send you message in the day. |
Here is the final result of my HealthCheck : I use https://quarkus.io/guides/microprofile-health I got this kind of response from my backend : {
"status": "DOWN",
"checks": [
{
"name": "Micro Service - Crossing series ",
"status": "UP"
},
{
"name": "Micro Service - Crossing Scheduler",
"status": "UP"
},
{
"name": "Micro Service - Vehicle Regex",
"status": "DOWN",
"data": {
"Message": "RESTEASY004655: Unable to invoke request: java.net.ConnectException: Connection refused: connect"
}
},
{
"name": "Kafka cluster",
"status": "UP"
}
]
} It's my first React project and Im very happy of the result. Learning React with react-healthy is perfect. Here is my onBegin signature :
In my onResponse Handler I manage everything. Im looking for a nicer way to do it. I changed to fetch like this : await fetch(api.api.endpoint)
.then(apiResponse => handleResponse(api, apiResponse, onResponse))
// tslint:disable-next-line
.catch(error => handleError(api, onResponse));
}; BTW I added material-ui. I like it ;) I don't know hooks. I will learn it. I don't know the best way to use react-healthy. I copy/paste some files of your project into mine. |
I did a new commit. Some things to say : Uncaught (in promise) TypeError: onDown is not a function I will look on it. Im not yet familiar with the Healthy component. Also, in Handler is change the signature. The Response is now optional (onDown management) Also in my impl I add a way to parse the json returned by my api call. // Examine the text in the response
response.json().then(function(data) {
const apiResponse: ApiResponse = {
code: response.status,
message: response.statusText,
body: data,
};
200 == apiResponse.code ? onSuccess(api, apiResponse) : onError(api, apiResponse);
}); Here is my Response object definition : export interface Response {
/** HTTP Error Code */
code: number;
/** Status message */
message: string;
/** Body */
body: HealthCheck;
}
export interface HealthCheck {
status: string;
checks: Check [];
}
interface Check {
name: string;
status: string;
}
export interface ApiWithResponse {
api: Api;
response: Response;
} Do you want to implement it in your lib. Notice that it's tight coupling with quarkus health check and this is why I think we shouldn't implement it in the react-healthy lib. Now we have a clear separation of the 3 scenarios : success / failure / down. I hope that it doesn't break the Healthy component too much. You decide how we merge my code in the master branch. Im very interested by React hooks :) |
src/pages/StatusPage/index.tsx
Outdated
}; | ||
public handleError = (api: Api, response: Response) => { | ||
const apis = [...this.state.apis]; | ||
const index = apis.findIndex(stateApi => stateApi.api === api); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should check api.endpoint
equality
src/pages/StatusPage/index.tsx
Outdated
public componentDidMount = async () => { | ||
const apis = this.props.apis.map(api => ({ api, response: null, hasError: false })); | ||
const apis = [...this.state.apis]; | ||
const index = apis.findIndex(stateApi => stateApi.api === api); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should check api.endpoint
equality
src/pages/StatusPage/index.tsx
Outdated
apis, | ||
hasError: false, | ||
hasError: hasError, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can shorten to hasError,
src/pages/StatusPage/index.tsx
Outdated
this.setState({ | ||
...this.state, | ||
apis, | ||
hasError: hasError, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can shorten to hasError,
So, it looks like your |
Love the material design, by the way! Very slick! |
Also, I'll try to pull your branch either today or tomorrow and make sure that everything looks smoothly. Then I'll go ahead and merge it in and update the hooks refactor. To answer your question of whether or not to implement your |
cb684ce
to
5e57f15
Compare
|
|
So I ve removed onApiDown handler. Indeed it makes the same than onError handler.
const handleResponse = (api: Api, onSuccess: Handler, onError: Handler, response?: Response) => {
if(response){ ...
response != null ? apis[index].response = response : apis[index].response = null; I let you decide what you prefer. Me I prefer to have 3 separates Handler because it evics to have if statement in the handleResponse... What do you think ? |
BTW the Healthy component is still broke... I got the "We are currently experiencing issues with our Api1 service" message even if the API is up. Please could you check? |
I don't use the same linter than you. Sorry. It would be nice to find a way to lint in the same way than you.