Skip to content

Commit

Permalink
load the new featureFlags into global state and allow updating via qu…
Browse files Browse the repository at this point in the history
…ery params (prefix: `pinboardFeatureFlag_`)
  • Loading branch information
twrichards committed Nov 5, 2024
1 parent a4c4519 commit 4e2ee67
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 52 deletions.
52 changes: 28 additions & 24 deletions cdk/lib/__snapshots__/stack.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2491,9 +2491,13 @@ type Subscription {
pinboardId: String!
): LastItemSeenByUser @aws_subscribe(mutations: [\\"seenItem\\"])
onManuallyOpenedPinboardIdsChanged(
onMyUserChanges(
email: String! # unfortunately this can't be done via 'identity' in the resolver
): MyUser @aws_subscribe(mutations: [\\"addManuallyOpenedPinboardIds\\", \\"removeManuallyOpenedPinboardIds\\"])
): MyUser @aws_subscribe(mutations: [
\\"addManuallyOpenedPinboardIds\\",
\\"removeManuallyOpenedPinboardIds\\",
\\"changeFeatureFlag\\"
])
}
type MentionHandle {
Expand Down Expand Up @@ -2671,7 +2675,7 @@ type PinboardIdWithItemCounts {
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "addManuallyOpenedPinboardIds",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2692,7 +2696,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "changeFeatureFlag",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2713,7 +2717,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "claimItem",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2734,7 +2738,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "createItem",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2755,7 +2759,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "deleteItem",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2776,7 +2780,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "editItem",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2797,7 +2801,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "removeManuallyOpenedPinboardIds",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2818,7 +2822,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "seenItem",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2839,7 +2843,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "setWebPushSubscriptionForUser",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2860,7 +2864,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "visitTourStep",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2881,7 +2885,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "getGroupPinboardIds",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -2902,7 +2906,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "getItemCounts",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -2923,7 +2927,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "getMyUser",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -2944,7 +2948,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "getUsers",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -2965,7 +2969,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "listItems",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -2986,7 +2990,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "listLastItemSeenByUsers",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -3007,7 +3011,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "searchMentionableUsers",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand Down Expand Up @@ -3136,7 +3140,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "grid_bridge_lambda_ds",
"FieldName": "asGridPayload",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -3157,7 +3161,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "grid_bridge_lambda_ds",
"FieldName": "getGridSearchSummary",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand Down Expand Up @@ -3286,7 +3290,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "workflow_bridge_lambda_ds",
"FieldName": "getPinboardByComposerId",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -3307,7 +3311,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "workflow_bridge_lambda_ds",
"FieldName": "getPinboardsByIds",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -3328,7 +3332,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "workflow_bridge_lambda_ds",
"FieldName": "listPinboards",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand Down
14 changes: 11 additions & 3 deletions client/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,9 @@ export const gqlRemoveManuallyOpenedPinboardIds = gql`
}
`;

export const gqlOnManuallyOpenedPinboardIdsChanged = (userEmail: string) => gql`
subscription OnManuallyOpenedPinboardIdsChanged {
onManuallyOpenedPinboardIdsChanged(email: "${userEmail}") {
export const gqlOnMyUserChanges = (userEmail: string) => gql`
subscription onMyUserChanges {
onMyUserChanges(email: "${userEmail}") {
${myUserReturnFields}
}
}
Expand Down Expand Up @@ -275,3 +275,11 @@ export const gqlVisitTourStep = gql`
}
}
`;

export const gqlChangeFeatureFlag = gql`
mutation changeFeatureFlag($flagId: String!, $newValue: Boolean!) {
changeFeatureFlag(flagId: $flagId, newValue: $newValue) {
${myUserReturnFields}
}
}
`;
40 changes: 25 additions & 15 deletions client/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
gqlVisitTourStep,
gqlGetMyUser,
gqlGetUsers,
gqlOnManuallyOpenedPinboardIdsChanged,
gqlOnMyUserChanges,
gqlSetWebPushSubscriptionForUser,
} from "../gql";
import { Item, MyUser, User } from "shared/graphql/graphql";
Expand All @@ -45,6 +45,10 @@ import { getAgateFontFaceIfApplicable } from "../fontNormaliser";
import { Global } from "@emotion/react";
import { TourStateProvider } from "./tour/tourState";
import { demoMentionableUsers, demoUser } from "./tour/tourConstants";
import {
consumeFeatureFlagQueryParamsAndUpdateAccordingly,
extractFeatureFlags,
} from "./featureFlags";

const PRESELECT_PINBOARD_HTML_TAG = "pinboard-preselect";
const PRESET_UNREAD_NOTIFICATIONS_COUNT_HTML_TAG = "pinboard-bubble-preset";
Expand Down Expand Up @@ -206,7 +210,7 @@ export const PinBoardApp = ({
const me = meQuery.data?.getMyUser;

const manuallyOpenedPinboardIds = me?.manuallyOpenedPinboardIds;
const setManuallyOpenedPinboardIds = (newMyUser: MyUser) => {
const updateUserWithChanges = (newMyUser: MyUser) => {
meQuery.updateQuery(() => ({ getMyUser: newMyUser }));
};

Expand All @@ -225,18 +229,13 @@ export const PinBoardApp = ({
meQuery.updateQuery(() => ({ getMyUser: data.visitTourStep }));
});

useSubscription<{ onManuallyOpenedPinboardIdsChanged: MyUser }>(
gqlOnManuallyOpenedPinboardIdsChanged(userEmail),
{
client: apolloClient,
onSubscriptionData: ({ subscriptionData }) => {
subscriptionData.data &&
setManuallyOpenedPinboardIds(
subscriptionData.data?.onManuallyOpenedPinboardIdsChanged
);
},
}
);
useSubscription<{ onMyUserChanges: MyUser }>(gqlOnMyUserChanges(userEmail), {
client: apolloClient,
onSubscriptionData: ({ subscriptionData }) => {
subscriptionData.data &&
updateUserWithChanges(subscriptionData.data?.onMyUserChanges);
},
});

const rawHasWebPushSubscription = me?.hasWebPushSubscription;

Expand Down Expand Up @@ -357,6 +356,16 @@ export const PinBoardApp = ({

const hasApolloAuthError = useReactiveVar(hasApolloAuthErrorVar);

const featureFlags = useMemo(
() => extractFeatureFlags(me?.featureFlags),
[me?.featureFlags]
);
consumeFeatureFlagQueryParamsAndUpdateAccordingly(apolloClient);

useEffect(() => {
console.log("test feature flag:", featureFlags["test"]);
}, [featureFlags]);

return (
<TelemetryContext.Provider value={sendTelemetryEvent}>
<ApolloProvider client={apolloClient}>
Expand All @@ -373,13 +382,14 @@ export const PinBoardApp = ({
addEmailsToLookup={addEmailsToLookup}
hasWebPushSubscription={hasWebPushSubscription}
manuallyOpenedPinboardIds={manuallyOpenedPinboardIds || []}
setManuallyOpenedPinboardIds={setManuallyOpenedPinboardIds}
updateUserWithChanges={updateUserWithChanges}
showNotification={showDesktopNotification}
clearDesktopNotificationsForPinboardId={
clearDesktopNotificationsForPinboardId
}
hasEverUsedTour={me?.hasEverUsedTour}
visitTourStep={visitTourStep}
featureFlags={featureFlags}
>
<TourStateProvider>
<Global styles={agateFontFaceIfApplicable} />
Expand Down
34 changes: 34 additions & 0 deletions client/src/featureFlags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { readAndThenSilentlyDropQueryParamFromURL } from "./util";
import { ApolloClient } from "@apollo/client";
import { gqlChangeFeatureFlag } from "../gql";

export const ALLOWED_FEATURE_FLAGS = ["test"] as const;
export type AllowedFeatureFlags = (typeof ALLOWED_FEATURE_FLAGS)[number];

export type FeatureFlags = Partial<Record<AllowedFeatureFlags, boolean>>;

export const extractFeatureFlags = (
featureFlagsStr: string | null | undefined
): FeatureFlags =>
featureFlagsStr ? (JSON.parse(featureFlagsStr) as FeatureFlags) : {};

export const consumeFeatureFlagQueryParamsAndUpdateAccordingly = (
apolloClient: ApolloClient<unknown>
) =>
ALLOWED_FEATURE_FLAGS.forEach((flagId) => {
const flagStringValue = readAndThenSilentlyDropQueryParamFromURL(
`pinboardFeatureFlag_${flagId}`
);
if (flagStringValue !== null) {
apolloClient
.mutate({
mutation: gqlChangeFeatureFlag,
variables: {
flagId,
newValue: flagStringValue === "true",
},
})
.catch(console.error);
// we rely on the subscription 'updateUserWithChanges'
}
});
Loading

0 comments on commit 4e2ee67

Please sign in to comment.