Skip to content

Commit 4e2ee67

Browse files
committed
load the new featureFlags into global state and allow updating via query params (prefix: pinboardFeatureFlag_)
1 parent a4c4519 commit 4e2ee67

File tree

6 files changed

+115
-52
lines changed

6 files changed

+115
-52
lines changed

cdk/lib/__snapshots__/stack.test.ts.snap

+28-24
Original file line numberDiff line numberDiff line change
@@ -2491,9 +2491,13 @@ type Subscription {
24912491
pinboardId: String!
24922492
): LastItemSeenByUser @aws_subscribe(mutations: [\\"seenItem\\"])
24932493
2494-
onManuallyOpenedPinboardIdsChanged(
2494+
onMyUserChanges(
24952495
email: String! # unfortunately this can't be done via 'identity' in the resolver
2496-
): MyUser @aws_subscribe(mutations: [\\"addManuallyOpenedPinboardIds\\", \\"removeManuallyOpenedPinboardIds\\"])
2496+
): MyUser @aws_subscribe(mutations: [
2497+
\\"addManuallyOpenedPinboardIds\\",
2498+
\\"removeManuallyOpenedPinboardIds\\",
2499+
\\"changeFeatureFlag\\"
2500+
])
24972501
}
24982502
24992503
type MentionHandle {
@@ -2671,7 +2675,7 @@ type PinboardIdWithItemCounts {
26712675
"DataSourceName": "database_bridge_lambda_ds",
26722676
"FieldName": "addManuallyOpenedPinboardIds",
26732677
"Kind": "UNIT",
2674-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2678+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
26752679
$util.toJson($ctx.result)",
26762680
"TypeName": "Mutation",
26772681
},
@@ -2692,7 +2696,7 @@ $util.toJson($ctx.result)",
26922696
"DataSourceName": "database_bridge_lambda_ds",
26932697
"FieldName": "changeFeatureFlag",
26942698
"Kind": "UNIT",
2695-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2699+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
26962700
$util.toJson($ctx.result)",
26972701
"TypeName": "Mutation",
26982702
},
@@ -2713,7 +2717,7 @@ $util.toJson($ctx.result)",
27132717
"DataSourceName": "database_bridge_lambda_ds",
27142718
"FieldName": "claimItem",
27152719
"Kind": "UNIT",
2716-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2720+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
27172721
$util.toJson($ctx.result)",
27182722
"TypeName": "Mutation",
27192723
},
@@ -2734,7 +2738,7 @@ $util.toJson($ctx.result)",
27342738
"DataSourceName": "database_bridge_lambda_ds",
27352739
"FieldName": "createItem",
27362740
"Kind": "UNIT",
2737-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2741+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
27382742
$util.toJson($ctx.result)",
27392743
"TypeName": "Mutation",
27402744
},
@@ -2755,7 +2759,7 @@ $util.toJson($ctx.result)",
27552759
"DataSourceName": "database_bridge_lambda_ds",
27562760
"FieldName": "deleteItem",
27572761
"Kind": "UNIT",
2758-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2762+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
27592763
$util.toJson($ctx.result)",
27602764
"TypeName": "Mutation",
27612765
},
@@ -2776,7 +2780,7 @@ $util.toJson($ctx.result)",
27762780
"DataSourceName": "database_bridge_lambda_ds",
27772781
"FieldName": "editItem",
27782782
"Kind": "UNIT",
2779-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2783+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
27802784
$util.toJson($ctx.result)",
27812785
"TypeName": "Mutation",
27822786
},
@@ -2797,7 +2801,7 @@ $util.toJson($ctx.result)",
27972801
"DataSourceName": "database_bridge_lambda_ds",
27982802
"FieldName": "removeManuallyOpenedPinboardIds",
27992803
"Kind": "UNIT",
2800-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2804+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
28012805
$util.toJson($ctx.result)",
28022806
"TypeName": "Mutation",
28032807
},
@@ -2818,7 +2822,7 @@ $util.toJson($ctx.result)",
28182822
"DataSourceName": "database_bridge_lambda_ds",
28192823
"FieldName": "seenItem",
28202824
"Kind": "UNIT",
2821-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2825+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
28222826
$util.toJson($ctx.result)",
28232827
"TypeName": "Mutation",
28242828
},
@@ -2839,7 +2843,7 @@ $util.toJson($ctx.result)",
28392843
"DataSourceName": "database_bridge_lambda_ds",
28402844
"FieldName": "setWebPushSubscriptionForUser",
28412845
"Kind": "UNIT",
2842-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2846+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
28432847
$util.toJson($ctx.result)",
28442848
"TypeName": "Mutation",
28452849
},
@@ -2860,7 +2864,7 @@ $util.toJson($ctx.result)",
28602864
"DataSourceName": "database_bridge_lambda_ds",
28612865
"FieldName": "visitTourStep",
28622866
"Kind": "UNIT",
2863-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2867+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
28642868
$util.toJson($ctx.result)",
28652869
"TypeName": "Mutation",
28662870
},
@@ -2881,7 +2885,7 @@ $util.toJson($ctx.result)",
28812885
"DataSourceName": "database_bridge_lambda_ds",
28822886
"FieldName": "getGroupPinboardIds",
28832887
"Kind": "UNIT",
2884-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2888+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
28852889
$util.toJson($ctx.result)",
28862890
"TypeName": "Query",
28872891
},
@@ -2902,7 +2906,7 @@ $util.toJson($ctx.result)",
29022906
"DataSourceName": "database_bridge_lambda_ds",
29032907
"FieldName": "getItemCounts",
29042908
"Kind": "UNIT",
2905-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2909+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
29062910
$util.toJson($ctx.result)",
29072911
"TypeName": "Query",
29082912
},
@@ -2923,7 +2927,7 @@ $util.toJson($ctx.result)",
29232927
"DataSourceName": "database_bridge_lambda_ds",
29242928
"FieldName": "getMyUser",
29252929
"Kind": "UNIT",
2926-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2930+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
29272931
$util.toJson($ctx.result)",
29282932
"TypeName": "Query",
29292933
},
@@ -2944,7 +2948,7 @@ $util.toJson($ctx.result)",
29442948
"DataSourceName": "database_bridge_lambda_ds",
29452949
"FieldName": "getUsers",
29462950
"Kind": "UNIT",
2947-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2951+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
29482952
$util.toJson($ctx.result)",
29492953
"TypeName": "Query",
29502954
},
@@ -2965,7 +2969,7 @@ $util.toJson($ctx.result)",
29652969
"DataSourceName": "database_bridge_lambda_ds",
29662970
"FieldName": "listItems",
29672971
"Kind": "UNIT",
2968-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2972+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
29692973
$util.toJson($ctx.result)",
29702974
"TypeName": "Query",
29712975
},
@@ -2986,7 +2990,7 @@ $util.toJson($ctx.result)",
29862990
"DataSourceName": "database_bridge_lambda_ds",
29872991
"FieldName": "listLastItemSeenByUsers",
29882992
"Kind": "UNIT",
2989-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
2993+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
29902994
$util.toJson($ctx.result)",
29912995
"TypeName": "Query",
29922996
},
@@ -3007,7 +3011,7 @@ $util.toJson($ctx.result)",
30073011
"DataSourceName": "database_bridge_lambda_ds",
30083012
"FieldName": "searchMentionableUsers",
30093013
"Kind": "UNIT",
3010-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
3014+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
30113015
$util.toJson($ctx.result)",
30123016
"TypeName": "Query",
30133017
},
@@ -3136,7 +3140,7 @@ $util.toJson($ctx.result)",
31363140
"DataSourceName": "grid_bridge_lambda_ds",
31373141
"FieldName": "asGridPayload",
31383142
"Kind": "UNIT",
3139-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
3143+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
31403144
$util.toJson($ctx.result)",
31413145
"TypeName": "Query",
31423146
},
@@ -3157,7 +3161,7 @@ $util.toJson($ctx.result)",
31573161
"DataSourceName": "grid_bridge_lambda_ds",
31583162
"FieldName": "getGridSearchSummary",
31593163
"Kind": "UNIT",
3160-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
3164+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
31613165
$util.toJson($ctx.result)",
31623166
"TypeName": "Query",
31633167
},
@@ -3286,7 +3290,7 @@ $util.toJson($ctx.result)",
32863290
"DataSourceName": "workflow_bridge_lambda_ds",
32873291
"FieldName": "getPinboardByComposerId",
32883292
"Kind": "UNIT",
3289-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
3293+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
32903294
$util.toJson($ctx.result)",
32913295
"TypeName": "Query",
32923296
},
@@ -3307,7 +3311,7 @@ $util.toJson($ctx.result)",
33073311
"DataSourceName": "workflow_bridge_lambda_ds",
33083312
"FieldName": "getPinboardsByIds",
33093313
"Kind": "UNIT",
3310-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
3314+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
33113315
$util.toJson($ctx.result)",
33123316
"TypeName": "Query",
33133317
},
@@ -3328,7 +3332,7 @@ $util.toJson($ctx.result)",
33283332
"DataSourceName": "workflow_bridge_lambda_ds",
33293333
"FieldName": "listPinboards",
33303334
"Kind": "UNIT",
3331-
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
3335+
"ResponseMappingTemplate": "## schema checksum : 117bac3c96ba985bef3ad1486ee0eb07
33323336
$util.toJson($ctx.result)",
33333337
"TypeName": "Query",
33343338
},

client/gql.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,9 @@ export const gqlRemoveManuallyOpenedPinboardIds = gql`
180180
}
181181
`;
182182

183-
export const gqlOnManuallyOpenedPinboardIdsChanged = (userEmail: string) => gql`
184-
subscription OnManuallyOpenedPinboardIdsChanged {
185-
onManuallyOpenedPinboardIdsChanged(email: "${userEmail}") {
183+
export const gqlOnMyUserChanges = (userEmail: string) => gql`
184+
subscription onMyUserChanges {
185+
onMyUserChanges(email: "${userEmail}") {
186186
${myUserReturnFields}
187187
}
188188
}
@@ -275,3 +275,11 @@ export const gqlVisitTourStep = gql`
275275
}
276276
}
277277
`;
278+
279+
export const gqlChangeFeatureFlag = gql`
280+
mutation changeFeatureFlag($flagId: String!, $newValue: Boolean!) {
281+
changeFeatureFlag(flagId: $flagId, newValue: $newValue) {
282+
${myUserReturnFields}
283+
}
284+
}
285+
`;

client/src/app.tsx

+25-15
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
gqlVisitTourStep,
1919
gqlGetMyUser,
2020
gqlGetUsers,
21-
gqlOnManuallyOpenedPinboardIdsChanged,
21+
gqlOnMyUserChanges,
2222
gqlSetWebPushSubscriptionForUser,
2323
} from "../gql";
2424
import { Item, MyUser, User } from "shared/graphql/graphql";
@@ -45,6 +45,10 @@ import { getAgateFontFaceIfApplicable } from "../fontNormaliser";
4545
import { Global } from "@emotion/react";
4646
import { TourStateProvider } from "./tour/tourState";
4747
import { demoMentionableUsers, demoUser } from "./tour/tourConstants";
48+
import {
49+
consumeFeatureFlagQueryParamsAndUpdateAccordingly,
50+
extractFeatureFlags,
51+
} from "./featureFlags";
4852

4953
const PRESELECT_PINBOARD_HTML_TAG = "pinboard-preselect";
5054
const PRESET_UNREAD_NOTIFICATIONS_COUNT_HTML_TAG = "pinboard-bubble-preset";
@@ -206,7 +210,7 @@ export const PinBoardApp = ({
206210
const me = meQuery.data?.getMyUser;
207211

208212
const manuallyOpenedPinboardIds = me?.manuallyOpenedPinboardIds;
209-
const setManuallyOpenedPinboardIds = (newMyUser: MyUser) => {
213+
const updateUserWithChanges = (newMyUser: MyUser) => {
210214
meQuery.updateQuery(() => ({ getMyUser: newMyUser }));
211215
};
212216

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

228-
useSubscription<{ onManuallyOpenedPinboardIdsChanged: MyUser }>(
229-
gqlOnManuallyOpenedPinboardIdsChanged(userEmail),
230-
{
231-
client: apolloClient,
232-
onSubscriptionData: ({ subscriptionData }) => {
233-
subscriptionData.data &&
234-
setManuallyOpenedPinboardIds(
235-
subscriptionData.data?.onManuallyOpenedPinboardIdsChanged
236-
);
237-
},
238-
}
239-
);
232+
useSubscription<{ onMyUserChanges: MyUser }>(gqlOnMyUserChanges(userEmail), {
233+
client: apolloClient,
234+
onSubscriptionData: ({ subscriptionData }) => {
235+
subscriptionData.data &&
236+
updateUserWithChanges(subscriptionData.data?.onMyUserChanges);
237+
},
238+
});
240239

241240
const rawHasWebPushSubscription = me?.hasWebPushSubscription;
242241

@@ -357,6 +356,16 @@ export const PinBoardApp = ({
357356

358357
const hasApolloAuthError = useReactiveVar(hasApolloAuthErrorVar);
359358

359+
const featureFlags = useMemo(
360+
() => extractFeatureFlags(me?.featureFlags),
361+
[me?.featureFlags]
362+
);
363+
consumeFeatureFlagQueryParamsAndUpdateAccordingly(apolloClient);
364+
365+
useEffect(() => {
366+
console.log("test feature flag:", featureFlags["test"]);
367+
}, [featureFlags]);
368+
360369
return (
361370
<TelemetryContext.Provider value={sendTelemetryEvent}>
362371
<ApolloProvider client={apolloClient}>
@@ -373,13 +382,14 @@ export const PinBoardApp = ({
373382
addEmailsToLookup={addEmailsToLookup}
374383
hasWebPushSubscription={hasWebPushSubscription}
375384
manuallyOpenedPinboardIds={manuallyOpenedPinboardIds || []}
376-
setManuallyOpenedPinboardIds={setManuallyOpenedPinboardIds}
385+
updateUserWithChanges={updateUserWithChanges}
377386
showNotification={showDesktopNotification}
378387
clearDesktopNotificationsForPinboardId={
379388
clearDesktopNotificationsForPinboardId
380389
}
381390
hasEverUsedTour={me?.hasEverUsedTour}
382391
visitTourStep={visitTourStep}
392+
featureFlags={featureFlags}
383393
>
384394
<TourStateProvider>
385395
<Global styles={agateFontFaceIfApplicable} />

client/src/featureFlags.ts

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { readAndThenSilentlyDropQueryParamFromURL } from "./util";
2+
import { ApolloClient } from "@apollo/client";
3+
import { gqlChangeFeatureFlag } from "../gql";
4+
5+
export const ALLOWED_FEATURE_FLAGS = ["test"] as const;
6+
export type AllowedFeatureFlags = (typeof ALLOWED_FEATURE_FLAGS)[number];
7+
8+
export type FeatureFlags = Partial<Record<AllowedFeatureFlags, boolean>>;
9+
10+
export const extractFeatureFlags = (
11+
featureFlagsStr: string | null | undefined
12+
): FeatureFlags =>
13+
featureFlagsStr ? (JSON.parse(featureFlagsStr) as FeatureFlags) : {};
14+
15+
export const consumeFeatureFlagQueryParamsAndUpdateAccordingly = (
16+
apolloClient: ApolloClient<unknown>
17+
) =>
18+
ALLOWED_FEATURE_FLAGS.forEach((flagId) => {
19+
const flagStringValue = readAndThenSilentlyDropQueryParamFromURL(
20+
`pinboardFeatureFlag_${flagId}`
21+
);
22+
if (flagStringValue !== null) {
23+
apolloClient
24+
.mutate({
25+
mutation: gqlChangeFeatureFlag,
26+
variables: {
27+
flagId,
28+
newValue: flagStringValue === "true",
29+
},
30+
})
31+
.catch(console.error);
32+
// we rely on the subscription 'updateUserWithChanges'
33+
}
34+
});

0 commit comments

Comments
 (0)