Skip to content

Commit

Permalink
add featureFlags JSONB column to database, added to the MyUser ty…
Browse files Browse the repository at this point in the history
…pe (as json string) and updated via new mutation `changeFeatureFlag`
  • Loading branch information
twrichards committed Nov 4, 2024
1 parent df69b6d commit c844f2a
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 22 deletions.
65 changes: 44 additions & 21 deletions cdk/lib/__snapshots__/stack.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2475,6 +2475,7 @@ type Mutation {
addManuallyOpenedPinboardIds(pinboardId: String!, maybeEmailOverride: String): MyUser
removeManuallyOpenedPinboardIds(pinboardIdToClose: String!): MyUser
visitTourStep(tourStepId: String!): MyUser
changeFeatureFlag(flagId: String!, newValue: Boolean!): MyUser
}
type Subscription {
Expand Down Expand Up @@ -2539,6 +2540,7 @@ type MyUser {
hasWebPushSubscription: Boolean
manuallyOpenedPinboardIds: [String!]
hasEverUsedTour: Boolean!
featureFlags: AWSJSON
}
type Group {
Expand Down Expand Up @@ -2669,7 +2671,28 @@ type PinboardIdWithItemCounts {
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "addManuallyOpenedPinboardIds",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
"Type": "AWS::AppSync::Resolver",
},
"pinboardappsyncapidatabasebridgelambdadsMutationchangeFeatureFlagResolver77AF20F3": Object {
"DependsOn": Array [
"pinboardappsyncapidatabasebridgelambdads970CB9A7",
"pinboardappsyncapiSchema868D9F5B",
],
"Properties": Object {
"ApiId": Object {
"Fn::GetAtt": Array [
"pinboardappsyncapi9D519400",
"ApiId",
],
},
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "changeFeatureFlag",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2690,7 +2713,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "claimItem",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2711,7 +2734,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "createItem",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2732,7 +2755,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "deleteItem",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2753,7 +2776,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "editItem",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2774,7 +2797,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "removeManuallyOpenedPinboardIds",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2795,7 +2818,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "seenItem",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2816,7 +2839,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "setWebPushSubscriptionForUser",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2837,7 +2860,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "visitTourStep",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Mutation",
},
Expand All @@ -2858,7 +2881,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "getGroupPinboardIds",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -2879,7 +2902,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "getItemCounts",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -2900,7 +2923,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "getMyUser",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -2921,7 +2944,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "getUsers",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -2942,7 +2965,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "listItems",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -2963,7 +2986,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "listLastItemSeenByUsers",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -2984,7 +3007,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "database_bridge_lambda_ds",
"FieldName": "searchMentionableUsers",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand Down Expand Up @@ -3113,7 +3136,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "grid_bridge_lambda_ds",
"FieldName": "asGridPayload",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -3134,7 +3157,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "grid_bridge_lambda_ds",
"FieldName": "getGridSearchSummary",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand Down Expand Up @@ -3263,7 +3286,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "workflow_bridge_lambda_ds",
"FieldName": "getPinboardByComposerId",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -3284,7 +3307,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "workflow_bridge_lambda_ds",
"FieldName": "getPinboardsByIds",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand All @@ -3305,7 +3328,7 @@ $util.toJson($ctx.result)",
"DataSourceName": "workflow_bridge_lambda_ds",
"FieldName": "listPinboards",
"Kind": "UNIT",
"ResponseMappingTemplate": "## schema checksum : aa02bae16942e48366fa36a1cd643d16
"ResponseMappingTemplate": "## schema checksum : 7988db64c71d520310206ab1f55f3ca3
$util.toJson($ctx.result)",
"TypeName": "Query",
},
Expand Down
1 change: 1 addition & 0 deletions client/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ const myUserReturnFields = `${userReturnFields}
hasWebPushSubscription
manuallyOpenedPinboardIds
hasEverUsedTour
featureFlags
`;

export const gqlSearchMentionableUsers = (prefix: string) => gql`
Expand Down
3 changes: 3 additions & 0 deletions database-bridge-lambda/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Sql } from "../../shared/database/types";
import { listLastItemSeenByUsers, seenItem } from "./sql/LastItemSeenByUser";
import {
addManuallyOpenedPinboardIds,
changeFeatureFlag,
getMyUser,
getUsers,
removeManuallyOpenedPinboardIds,
Expand Down Expand Up @@ -66,6 +67,8 @@ const run = (
return getItemCounts(sql, args, userEmail);
case "visitTourStep":
return visitTourStep(sql, args, userEmail);
case "changeFeatureFlag":
return changeFeatureFlag(sql, args, userEmail);
}

throw Error(
Expand Down
24 changes: 23 additions & 1 deletion database-bridge-lambda/src/sql/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const getUsers = (sql: Sql, args: { emails: string[] }) =>
`;

const fragmentMyUserWithoutPushSubscriptionSecrets = (sql: Sql) =>
sql`"email", "firstName", "lastName", "avatarUrl", "manuallyOpenedPinboardIds", "visitedTourSteps" IS NOT NULL AS "hasEverUsedTour", "webPushSubscription" IS NOT NULL AS "hasWebPushSubscription"`;
sql`"email", "firstName", "lastName", "avatarUrl", "manuallyOpenedPinboardIds", "visitedTourSteps" IS NOT NULL AS "hasEverUsedTour", "webPushSubscription" IS NOT NULL AS "hasWebPushSubscription", "featureFlags"`;

export const getMyUser = (sql: Sql, userEmail: string) =>
sql`
Expand Down Expand Up @@ -112,3 +112,25 @@ export const visitTourStep = async (
WHERE "email" = ${userEmail}
RETURNING ${fragmentMyUserWithoutPushSubscriptionSecrets(sql)}
`.then((rows) => rows[0]);

export const changeFeatureFlag = async (
sql: Sql,
args: { flagId: string; newValue: boolean },
userEmail: string
) =>
sql`
UPDATE "User"
SET "featureFlags" = jsonb_set(
COALESCE("featureFlags", '{}'::jsonb),
${[args.flagId]},
jsonb_set(
COALESCE("featureFlags" -> ${args.flagId}, '{}'::jsonb),
NOW(),
to_jsonb(${args.newValue}),
true
)
true
)
WHERE "email" = ${userEmail}
RETURNING ${fragmentMyUserWithoutPushSubscriptionSecrets(sql)}
`.then((rows) => rows[0]);
2 changes: 2 additions & 0 deletions shared/database/local/runDatabaseSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ const runSetupTriggerSqlFile = (
getEmailLambdaFunctionName(stage),
EMAIL_DATABASE_TRIGGER_NAME
),
"add featureFlags column to User table": () =>
runSetupSqlFile(sql, "020-AddFeatureFlagsColumnToUserTable.sql"),
};

const allSteps = async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE "User" ADD COLUMN "featureFlags" JSONB;
1 change: 1 addition & 0 deletions shared/graphql/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const MUTATIONS = {
"addManuallyOpenedPinboardIds",
"removeManuallyOpenedPinboardIds",
"visitTourStep",
"changeFeatureFlag",
] as const,
} as const;

Expand Down
2 changes: 2 additions & 0 deletions shared/graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Mutation {
addManuallyOpenedPinboardIds(pinboardId: String!, maybeEmailOverride: String): MyUser
removeManuallyOpenedPinboardIds(pinboardIdToClose: String!): MyUser
visitTourStep(tourStepId: String!): MyUser
changeFeatureFlag(flagId: String!, newValue: Boolean!): MyUser
}

type Subscription {
Expand Down Expand Up @@ -96,6 +97,7 @@ type MyUser {
hasWebPushSubscription: Boolean
manuallyOpenedPinboardIds: [String!]
hasEverUsedTour: Boolean!
featureFlags: AWSJSON
}

type Group {
Expand Down

0 comments on commit c844f2a

Please sign in to comment.