Skip to content

Commit

Permalink
πŸͺŸ πŸŽ‰ Fetch LaunchDarkly flags & experiments scoped to a workspace (#22638
Browse files Browse the repository at this point in the history
)

* identify users by workspace

* refactor useCurrentWorkspaceId

* remove duplicate useEffect

* remove unused enum
  • Loading branch information
josephkmh authored and sh4sh committed Feb 10, 2023
1 parent cc5c33e commit 4505b4a
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 39 deletions.
2 changes: 1 addition & 1 deletion airbyte-webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"framer-motion": "^6.3.11",
"js-yaml": "^4.1.0",
"json-schema": "^0.4.0",
"launchdarkly-js-client-sdk": "^2.22.1",
"launchdarkly-js-client-sdk": "^3.1.0",
"lodash": "^4.17.21",
"monaco-editor": "^0.34.1",
"query-string": "^6.13.1",
Expand Down
21 changes: 10 additions & 11 deletions airbyte-webapp/pnpm-lock.yaml

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

1 change: 0 additions & 1 deletion airbyte-webapp/src/packages/cloud/cloudRoutePaths.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ export enum CloudRoutes {
AuthFlow = "/auth_flow",

Metrics = "metrics",
SelectWorkspace = "workspaces",
Credits = "credits",

// Auth routes
Expand Down
2 changes: 1 addition & 1 deletion airbyte-webapp/src/packages/cloud/cloudRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ const MainViewRoutes = () => {
{[CloudRoutes.Login, CloudRoutes.Signup, CloudRoutes.FirebaseAction].map((r) => (
<Route key={r} path={`${r}/*`} element={query.from ? <Navigate to={query.from} replace /> : <DefaultView />} />
))}
<Route path={CloudRoutes.SelectWorkspace} element={<WorkspacesPage />} />
<Route path={RoutePaths.Workspaces} element={<WorkspacesPage />} />
<Route path={CloudRoutes.AuthFlow} element={<CompleteOauthRequest />} />
<Route
path={`${RoutePaths.Workspaces}/:workspaceId/*`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type { Experiments } from "hooks/services/Experiment/experiments";
import { FeatureSet, FeatureItem, useFeatureService } from "hooks/services/Feature";
import { User } from "packages/cloud/lib/domain/users";
import { useAuthService } from "packages/cloud/services/auth/AuthService";
import { useCurrentWorkspaceId } from "services/workspaces/WorkspacesService";
import { rejectAfter } from "utils/promises";

/**
Expand Down Expand Up @@ -51,19 +52,29 @@ type LDInitState = "initializing" | "failed" | "initialized";
*/
const INITIALIZATION_TIMEOUT = 5000;

function mapUserToLDUser(user: User | null, locale: string): LDClient.LDUser {
return user
? {
key: user.userId,
email: user.email,
name: user.name,
custom: { intercomHash: user.intercomHash, locale },
anonymous: false,
}
: {
anonymous: true,
custom: { locale },
};
function mapUserToLDUser(user: User | null, locale: string, workspaceId: string | null): LDClient.LDUser {
if (!user) {
return {
anonymous: true,
custom: { locale },
};
}
/**
* Currently we can identify that a user is in a workspace with an optional workspaceId custom attribute.
* Once the LD Contexts feature is GA, we can upgrade the SDK and refactor this to support contexts:
* https://docs.launchdarkly.com/sdk/client-side/javascript/migration-2-to-3
*/
const custom: Record<string, string> = { intercomHash: user.intercomHash, locale };
if (workspaceId) {
custom.workspace = workspaceId;
}
return {
key: user.userId,
email: user.email,
name: user.name,
custom,
anonymous: false,
};
}

const LDInitializationWrapper: React.FC<React.PropsWithChildren<{ apiKey: string }>> = ({ children, apiKey }) => {
Expand All @@ -75,6 +86,7 @@ const LDInitializationWrapper: React.FC<React.PropsWithChildren<{ apiKey: string
const { locale } = useIntl();
const { setMessageOverwrite } = useI18nContext();
const { trackAction } = useAppMonitoringService();
const workspaceId = useCurrentWorkspaceId();

/**
* This function checks for all experiments to find the ones beginning with "i18n_{locale}_"
Expand Down Expand Up @@ -111,7 +123,7 @@ const LDInitializationWrapper: React.FC<React.PropsWithChildren<{ apiKey: string
};

if (!ldClient.current) {
ldClient.current = LDClient.initialize(apiKey, mapUserToLDUser(user, locale));
ldClient.current = LDClient.initialize(apiKey, mapUserToLDUser(user, locale, null));
// Wait for either LaunchDarkly to initialize or a specific timeout to pass first
Promise.race([
ldClient.current.waitForInitialization(),
Expand Down Expand Up @@ -150,10 +162,10 @@ const LDInitializationWrapper: React.FC<React.PropsWithChildren<{ apiKey: string
return () => ldClient.current?.off("change", onFeatureFlagsChanged);
});

// Whenever the user should change (e.g. login/logout) we need to reidentify the changes with the LD client
// Whenever the user, locale or workspaceId changes, we need to re-identify with launchdarkly
useEffect(() => {
ldClient.current?.identify(mapUserToLDUser(user, locale));
}, [locale, user]);
ldClient.current?.identify(mapUserToLDUser(user, locale, workspaceId || null));
}, [workspaceId, locale, user]);

// Show the loading page while we're still waiting for the initial set of feature flags (or them to time out)
if (state === "initializing") {
Expand Down
5 changes: 1 addition & 4 deletions airbyte-webapp/src/packages/cloud/views/DefaultView.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Navigate } from "react-router-dom";

import { RoutePaths } from "../../../pages/routePaths";
import { CloudRoutes } from "../cloudRoutePaths";
import { useListCloudWorkspaces } from "../services/workspaces/CloudWorkspacesService";

export const DefaultView: React.FC = () => {
Expand All @@ -12,9 +11,7 @@ export const DefaultView: React.FC = () => {
return (
<Navigate
to={
workspaces.length !== 1
? `/${CloudRoutes.SelectWorkspace}`
: `/${RoutePaths.Workspaces}/${workspaces[0].workspaceId}`
workspaces.length !== 1 ? `/${RoutePaths.Workspaces}` : `/${RoutePaths.Workspaces}/${workspaces[0].workspaceId}`
}
replace
/>
Expand Down
7 changes: 3 additions & 4 deletions airbyte-webapp/src/services/workspaces/WorkspacesService.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useCallback, useContext, useMemo } from "react";
import { useMutation, useQueryClient } from "react-query";
import { useNavigate, useParams } from "react-router-dom";
import { useNavigate, useMatch } from "react-router-dom";

import { Workspace, WorkspaceService } from "core/domain/workspace";
import { RoutePaths } from "pages/routePaths";
Expand Down Expand Up @@ -76,9 +76,8 @@ function useWorkspaceApiService() {
}

export const useCurrentWorkspaceId = () => {
const params = useParams<{ workspaceId: string }>();

return params.workspaceId as string;
const match = useMatch(`/${RoutePaths.Workspaces}/:workspaceId/*`);
return match?.params.workspaceId || "";
};

export const useCurrentWorkspace = () => {
Expand Down

0 comments on commit 4505b4a

Please sign in to comment.