-
Notifications
You must be signed in to change notification settings - Fork 6
SCAL-255099 Enhance event listener management in TsEmbed #315
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
Conversation
Summary of ChangesHello @shivam-kumar-ts, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request enhances the application's resilience to network fluctuations by implementing a robust internet connectivity check. This new utility ensures that actions dependent on network availability, such as reloading the embed on an 'online' event, are only performed when a stable connection is verified, improving the user experience by preventing premature or failed operations. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
🎉 Snyk checks have passed. No issues have been found so far.✅ security/snyk check is complete. No issues have been found. (View Details) ✅ license/snyk check is complete. No issues have been found. (View Details) |
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.
Code Review
This pull request introduces a utility function, checkInternetConnection
, to verify internet connectivity with an exponential backoff mechanism and integrates it into the onlineEventListener
. While the intention is good, I've found a few critical issues. The implementation of checkInternetConnection
has a bug that prevents the retry logic from executing on non-2xx HTTP responses. Additionally, the integration in ts-embed.ts
is missing an await
for the asynchronous call, which means it won't work as intended. The tests for the new utility are also insufficient as they don't cover the retry scenarios. I've provided detailed comments and suggestions to address these points.
src/embed/ts-embed.ts
Outdated
const onlineEventListener = (e: Event) => { | ||
this.trigger(HostEvent.Reload); | ||
if(checkInternetConnection(5 , 1000 , this.thoughtSpotHost)) { | ||
this.trigger(HostEvent.Reload); | ||
} |
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.
The checkInternetConnection
function is async
and returns a Promise
. In an if
condition, a Promise
is always truthy, so this.trigger(HostEvent.Reload)
will always be called when the online
event fires, regardless of the actual connectivity. You need to await
the result of checkInternetConnection
and make the onlineEventListener
callback async
.
const onlineEventListener = (e: Event) => { | |
this.trigger(HostEvent.Reload); | |
if(checkInternetConnection(5 , 1000 , this.thoughtSpotHost)) { | |
this.trigger(HostEvent.Reload); | |
} | |
const onlineEventListener = async (e: Event) => { | |
if(await checkInternetConnection(5 , 1000 , this.thoughtSpotHost)) { | |
this.trigger(HostEvent.Reload); | |
} | |
}; |
src/utils.ts
Outdated
logger.debug(`Pinging ${pingUrl} failed with HTTP ${response.status}: ${response.statusText}`); | ||
return 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.
There's a critical issue here. The function returns false
immediately upon receiving a non-2xx HTTP response, which prevents the retry mechanism from being triggered. The retry logic with exponential backoff is only in the catch
block, which is not executed for resolved promises with error statuses. To fix this, you should throw an error to ensure that non-2xx responses are handled by the retry logic in the catch
block.
logger.debug(`Pinging ${pingUrl} failed with HTTP ${response.status}: ${response.statusText}`); | |
return false; | |
logger.debug(`Pinging ${pingUrl} failed with HTTP ${response.status}: ${response.statusText}`); | |
throw new Error(`Server responded with status ${response.status}`); |
src/embed/ts-embed.ts
Outdated
|
||
const onlineEventListener = (e: Event) => { | ||
this.trigger(HostEvent.Reload); | ||
if(checkInternetConnection(5 , 1000 , this.thoughtSpotHost)) { |
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.
src/utils.spec.ts
Outdated
describe('checkInternetConnection', () => { | ||
const thoughtSpotHost = 'http://localhost:3000'; | ||
|
||
it('should return true when internet connection is available', async () => { | ||
jest.spyOn(window, 'fetch').mockImplementation(() => Promise.resolve({ | ||
ok: true, | ||
status: 200, | ||
statusText: 'OK', | ||
})); | ||
expect(await checkInternetConnection(5 , 1000 , thoughtSpotHost)).toBe(true); | ||
}); | ||
|
||
it('should return false when internet connection is not available', async () => { | ||
jest.spyOn(window, 'fetch').mockImplementation(() => Promise.resolve({ | ||
ok: false, | ||
status: 404, | ||
statusText: 'Not Found', | ||
})); | ||
expect(await checkInternetConnection(5 , 1000 , thoughtSpotHost)).toBe(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.
The current tests for checkInternetConnection
are insufficient as they do not cover the retry logic, which is a core part of this utility. The tests only check for immediate success or immediate failure.
Please add tests to cover the following scenarios:
- The connection check fails once but succeeds on a retry.
- The connection check fails for all retry attempts.
This will ensure the exponential backoff and retry mechanism works as expected. You might find jest.useFakeTimers()
useful to avoid long-running tests.
src/utils.ts
Outdated
return false; | ||
} | ||
|
||
logger.debug(`Connectivity check failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delayMs}ms`); |
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.
For better observability and easier debugging, it's a good practice to include the actual error in the log message when a connectivity check fails.
logger.debug(`Connectivity check failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delayMs}ms`); | |
logger.debug(`Connectivity check failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delayMs}ms. Error: ${error}`); |
commit: |
ad82e21
to
2e75792
Compare
2e75792
to
c7906cf
Compare
5798e12
to
2b29dbe
Compare
2b29dbe
to
57ff86b
Compare
* embed instance through an identifier contained in the payload, | ||
* and executes the registered callbacks accordingly. | ||
*/ | ||
private subscribeToEvents() { |
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.
why do we need this if we are calling network events function and message events function seperately?
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.
Calling From showPreRender function
src/embed/ts-embed.ts
Outdated
window.addEventListener('online', onlineEventListener); | ||
|
||
const offlineEventListener = (e: Event) => { | ||
const offlineWarning = |
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.
Move error message to error file
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.
Done
SonarQube Quality Gate
|
Enhance event listener management in TsEmbed: