-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[dashboard/protocol] Pass slow-database
Sec-WebSocket-Protocol
header to websocket connections from dashboard
#14752
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
e61b8ba
to
280e49e
Compare
280e49e
to
719ec50
Compare
719ec50
to
07a8d16
Compare
8297a02
to
152a132
Compare
/hold for dependency |
Pass the options into createWebSocket and use it to decide what value should be sent as the `Sec-WebSocket-Protocol` header when creating the websocket connection.
152a132
to
46c6722
Compare
function initGitPodService(useSlowDatabase: boolean) { | ||
const w = window as any; | ||
const _gp = w._gp || (w._gp = {}); | ||
if (window.location.search.includes("service=mock")) { | ||
_gp.gitpodService = require("./service-mock").gitpodServiceMock; | ||
} | ||
_gp.gitpodService = createGitpodService(useSlowDatabase); | ||
} | ||
|
||
export { getGitpodService, initGitPodService }; |
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.
Would you be able to explain why we're doing this?
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.
This function re-initializes the websocket connection - ie makes a new connection.
The getGitpodService
function above lazily creates a ws connection, ie it will create on the first time it is called if there is no connection yet.
We want to be able to create a brand new connection on demand when the value of the slow-database
feature flag changes.
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.
Thanks. Do we need the mock logic in there?
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.
Probably not - I took it from getGitpodService
function above. I'm inclined to keep it.
useEffect(() => { | ||
initGitPodService(useSlowDatabase); | ||
}, [useSlowDatabase]); |
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.
This seems to cause a bootstrap problem. We don't know who the user is (to evaluate the feature flag), but we're creating the connection which is parametrized on the feature flag (by user). I suspect this would result in always using "false" for the slow database argument
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 value of useSlowDatabase
is taken from the FeatureFlagContext
. All feature flags are re-evaluated when the value of user
changes (the dependency array in the effect includes user
):
gitpod/components/dashboard/src/contexts/FeatureFlagContext.tsx
Lines 47 to 85 in 46c6722
useEffect(() => { | |
if (!user) return; | |
(async () => { | |
const featureFlags: FeatureFlagConfig = { | |
persistent_volume_claim: { defaultValue: true, setter: setShowPersistentVolumeClaimUI }, | |
usage_view: { defaultValue: false, setter: setShowUsageView }, | |
showUseLastSuccessfulPrebuild: { defaultValue: false, setter: setShowUseLastSuccessfulPrebuild }, | |
publicApiExperimentalTeamsService: { defaultValue: false, setter: setUsePublicApiTeamsService }, | |
personalAccessTokensEnabled: { defaultValue: false, setter: setPersonalAccessTokensEnabled }, | |
useSlowDatabase: { defaultValue: false, setter: setUseSlowDatabase }, | |
}; | |
for (const [flagName, config] of Object.entries(featureFlags)) { | |
if (teams) { | |
for (const team of teams) { | |
const flagValue = await getExperimentsClient().getValueAsync(flagName, config.defaultValue, { | |
user, | |
projectId: project?.id, | |
teamId: team.id, | |
teamName: team?.name, | |
}); | |
// We got an explicit override value from ConfigCat | |
if (flagValue !== config.defaultValue) { | |
config.setter(flagValue); | |
return; | |
} | |
} | |
} | |
const flagValue = await getExperimentsClient().getValueAsync(flagName, config.defaultValue, { | |
user, | |
projectId: project?.id, | |
teamId: team?.id, | |
teamName: team?.name, | |
}); | |
config.setter(flagValue); | |
} | |
})(); | |
}, [user, teams, team, project]); |
Whenever the context sets the value of useSlowDatabase
(as it will whenever the effect runs) it causes any component that consumes the context to re-render, and the dependency array in the useEffect
here ensures that we re-initialize the websocket connection whenever App
renders.
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 guess with this change, we might see nearly double the WS connections being created. Just something we should be aware of from ops side
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 think we'll only see two connections for the small subset of users for which the feature flag is enabled.
For everyone else, the value of useSlowDatabase
will never change and the connection will never be re-initialized.
Use the name that matches the flag as defined in ConfigCat.
Description
Allow websocket connections from the dashboard to the server to specify a Sec-WebSocket-Protocol header indicating whether the connection should use a high-latency database connection, according to the value of a feature flag.
At a high level, the architecture looks like this:
Together with the dependency #14778 which handles the proxying of websocket upgrade requests to the
slow-server
backend based on the presence of theSec-WebSocket-Protocol
header, this PR gives us a means to roll out higher-latency dashboard to server websocket connections to selected internal users.Related Issue(s)
Part of #9198
How to test
Release Notes
Documentation
Werft options:
If enabled this will build
install/preview
Valid options are
all
,workspace
,webapp
,ide
,jetbrains
,vscode
,ssh