Skip to content

Commit af98f37

Browse files
committed
call out to Octopus Imaging API from database-bridge-lambda in createItem mutation if the type is imaging-request
1 parent 0d7dd60 commit af98f37

File tree

11 files changed

+166
-14
lines changed

11 files changed

+166
-14
lines changed

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

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4007,6 +4007,39 @@ $util.toJson($ctx.result)",
40074007
"Endpoint",
40084008
],
40094009
},
4010+
"OCTOPUS_API_LAMBDA_FUNCTION_NAME": Object {
4011+
"Fn::Select": Array [
4012+
6,
4013+
Object {
4014+
"Fn::Split": Array [
4015+
":",
4016+
Object {
4017+
"Fn::Join": Array [
4018+
"",
4019+
Array [
4020+
"arn:",
4021+
Object {
4022+
"Ref": "AWS::Partition",
4023+
},
4024+
":lambda:",
4025+
Object {
4026+
"Ref": "AWS::Region",
4027+
},
4028+
":",
4029+
Object {
4030+
"Ref": "AWS::AccountId",
4031+
},
4032+
":function:",
4033+
Object {
4034+
"Fn::ImportValue": "octopus-api-TEST-function-name",
4035+
},
4036+
],
4037+
],
4038+
},
4039+
],
4040+
},
4041+
],
4042+
},
40104043
"STACK": "workflow",
40114044
"STAGE": "TEST",
40124045
},
@@ -4166,6 +4199,59 @@ $util.toJson($ctx.result)",
41664199
],
41674200
},
41684201
},
4202+
Object {
4203+
"Action": "lambda:InvokeFunction",
4204+
"Effect": "Allow",
4205+
"Resource": Array [
4206+
Object {
4207+
"Fn::Join": Array [
4208+
"",
4209+
Array [
4210+
"arn:",
4211+
Object {
4212+
"Ref": "AWS::Partition",
4213+
},
4214+
":lambda:",
4215+
Object {
4216+
"Ref": "AWS::Region",
4217+
},
4218+
":",
4219+
Object {
4220+
"Ref": "AWS::AccountId",
4221+
},
4222+
":function:",
4223+
Object {
4224+
"Fn::ImportValue": "octopus-api-TEST-function-name",
4225+
},
4226+
],
4227+
],
4228+
},
4229+
Object {
4230+
"Fn::Join": Array [
4231+
"",
4232+
Array [
4233+
"arn:",
4234+
Object {
4235+
"Ref": "AWS::Partition",
4236+
},
4237+
":lambda:",
4238+
Object {
4239+
"Ref": "AWS::Region",
4240+
},
4241+
":",
4242+
Object {
4243+
"Ref": "AWS::AccountId",
4244+
},
4245+
":function:",
4246+
Object {
4247+
"Fn::ImportValue": "octopus-api-TEST-function-name",
4248+
},
4249+
":*",
4250+
],
4251+
],
4252+
},
4253+
],
4254+
},
41694255
],
41704256
"Version": "2012-10-17",
41714257
},

cdk/lib/stack.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,12 @@ export class PinBoardStack extends GuStack {
277277
`Allow ${databaseSecurityGroupName} to connect to the ${databaseProxy.dbProxyName}`
278278
);
279279

280+
const octopusApiLambda = lambda.Function.fromFunctionName(
281+
this,
282+
"OctopusApiLambda",
283+
Fn.importValue(`octopus-api-${this.stage}-function-name`)
284+
);
285+
280286
const pinboardDatabaseBridgeLambda = new lambda.Function(
281287
this,
282288
DATABASE_BRIDGE_LAMBDA_BASENAME,
@@ -290,6 +296,8 @@ export class PinBoardStack extends GuStack {
290296
STACK: this.stack,
291297
APP,
292298
[ENVIRONMENT_VARIABLE_KEYS.databaseHostname]: databaseHostname,
299+
[ENVIRONMENT_VARIABLE_KEYS.octopusApiLambdaFunctionName]:
300+
octopusApiLambda.functionName,
293301
},
294302
functionName: getDatabaseBridgeLambdaFunctionName(this.stage as Stage),
295303
code: lambda.Code.fromBucket(
@@ -302,6 +310,7 @@ export class PinBoardStack extends GuStack {
302310
}
303311
);
304312
databaseProxy.grantConnect(pinboardDatabaseBridgeLambda);
313+
octopusApiLambda.grantInvoke(pinboardDatabaseBridgeLambda);
305314

306315
const databaseJumpHostASGName = getDatabaseJumpHostAsgName(
307316
this.stage as Stage

client/src/app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
gqlSetWebPushSubscriptionForUser,
2323
} from "../gql";
2424
import { Item, MyUser, User } from "shared/graphql/graphql";
25-
import { ItemWithParsedPayload } from "./types/ItemWithParsedPayload";
25+
import { ItemWithParsedPayload } from "shared/types/ItemWithParsedPayload";
2626
import { HiddenIFrameForServiceWorker } from "./pushNotificationPreferences";
2727
import { GlobalStateProvider } from "./globalState";
2828
import { Floaty } from "./floaty";

client/src/push-notifications/serviceWorker.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { ItemWithParsedPayload } from "../types/ItemWithParsedPayload";
1+
import { ItemWithParsedPayload } from "shared/types/ItemWithParsedPayload";
22
import {
33
EXPAND_PINBOARD_QUERY_PARAM,
44
OPEN_PINBOARD_QUERY_PARAM,
55
PINBOARD_ITEM_ID_QUERY_PARAM,
6-
} from "../../../shared/constants";
7-
import { extractNameFromEmail } from "../../../shared/util";
6+
} from "shared/constants";
7+
import { extractNameFromEmail } from "shared/util";
88

99
const toolsDomain = self.location.hostname.replace("pinboard.", "");
1010

client/src/types/ItemWithParsedPayload.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

database-bridge-lambda/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"watch": "ts-node-dev --respawn run.ts"
1111
},
1212
"devDependencies": {
13+
"@aws-sdk/client-lambda": "^3.299.0",
1314
"ts-node-dev": "^1.0.0"
1415
},
1516
"dependencies": {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { getEnvironmentVariableOrThrow } from "shared/environmentVariables";
2+
import { ItemWithParsedPayload } from "shared/types/ItemWithParsedPayload";
3+
import { InvokeCommand, LambdaClient, LogType } from "@aws-sdk/client-lambda";
4+
import { standardAwsConfig } from "shared/awsIntegration";
5+
6+
const lambda = new LambdaClient(standardAwsConfig);
7+
const textEncoder = new TextEncoder();
8+
9+
export const performImagingRequest = async (item: ItemWithParsedPayload) => {
10+
const gridId = (item.payload?.embeddableUrl as string)?.split("/").pop();
11+
if (!gridId) {
12+
throw new Error(`Couldn't extract grid ID from payload: ${item.payload}`);
13+
}
14+
const imagingRequestBody = {
15+
workflowId: item.pinboardId,
16+
pinboardItemId: item.id,
17+
lastUser: item.userEmail,
18+
notes: item.message, //TODO check for 256 max (probably limit in UI too)
19+
requestType: item.payload?.requestType, // TODO tighten this up
20+
gridId,
21+
// composerId: TODO lookup somehow
22+
// pubDate TODO scheduled launch vs some date field in workflow - what's worse wrong date or no date?
23+
// section TODO lookup somehow
24+
// story group name TODO (synced from InCopy most likely, if available)
25+
};
26+
console.log("Performing imaging request", imagingRequestBody);
27+
28+
const octopusLambdaFunctionName = getEnvironmentVariableOrThrow(
29+
"octopusApiLambdaFunctionName"
30+
);
31+
32+
const octopusResponse = await lambda.send(
33+
new InvokeCommand({
34+
FunctionName: octopusLambdaFunctionName,
35+
Payload: textEncoder.encode(JSON.stringify(imagingRequestBody)),
36+
LogType: LogType.None, //TODO consider whether we tail the octopus logs as pinboard logs
37+
})
38+
);
39+
40+
// FIXME return something from octopusResponse.Payload
41+
};

database-bridge-lambda/src/sql/Item.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ import {
33
EditItemInput,
44
Item,
55
PinboardIdWithClaimCounts,
6-
} from "../../../shared/graphql/graphql";
7-
import { Sql } from "../../../shared/database/types";
8-
import { Range } from "../../../shared/types/grafanaType";
6+
} from "shared/graphql/graphql";
7+
import { Sql } from "shared/database/types";
8+
import { Range } from "shared/types/grafanaType";
9+
import { performImagingRequest } from "../imagingRequestCallout";
10+
import { IMAGING_REQUEST_ITEM_TYPE } from "shared/octopusImaging";
11+
import { ItemWithParsedPayload } from "shared/types/ItemWithParsedPayload";
912

1013
const fragmentIndividualMentionsToMentionHandles = (
1114
sql: Sql,
@@ -59,10 +62,20 @@ export const createItem = async (
5962
args: { input: CreateItemInput },
6063
userEmail: string
6164
) =>
62-
sql`
65+
sql.begin(async (sql) => {
66+
const insertResult = (await sql`
6367
INSERT INTO "Item" ${sql({ userEmail, ...args.input })}
6468
RETURNING ${fragmentItemFields(sql, userEmail)}
65-
`.then((rows) => rows[0]);
69+
`.then((rows) => rows[0])) as ItemWithParsedPayload;
70+
if (
71+
insertResult.type === IMAGING_REQUEST_ITEM_TYPE &&
72+
insertResult.payload
73+
) {
74+
// if this throws, the SQL transaction should be rolled back
75+
await performImagingRequest(insertResult); //TODO return/store octopus ID
76+
}
77+
return insertResult;
78+
});
6679

6780
export const editItem = async (
6881
sql: Sql,

shared/environmentVariables.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export const ENVIRONMENT_VARIABLE_KEYS = {
33
graphqlEndpoint: "GRAPHQL_ENDPOINT",
44
sentryDSN: "SENTRY_DSN",
55
databaseHostname: "DATABASE_HOSTNAME",
6+
octopusApiLambdaFunctionName: "OCTOPUS_API_LAMBDA_FUNCTION_NAME",
67
};
78

89
export const getEnvironmentVariableOrThrow = (
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { Item } from "../graphql/graphql";
2+
3+
export type ItemWithParsedPayload = Omit<Item, "payload"> & {
4+
payload: Record<string, unknown> | null | undefined;
5+
};

0 commit comments

Comments
 (0)