Skip to content

feat: typing ingest lambda and related files, app entry, adjusting types as needed#1087

Open
theodorehreuter wants to merge 4 commits intotr/drop-908/type-api-layerfrom
tr/drop-909/type-ingest-and-lambda-entry
Open

feat: typing ingest lambda and related files, app entry, adjusting types as needed#1087
theodorehreuter wants to merge 4 commits intotr/drop-908/type-api-layerfrom
tr/drop-909/type-ingest-and-lambda-entry

Conversation

@theodorehreuter
Copy link
Copy Markdown
Collaborator

Related Issue(s):
Typing the lambda entry points, index files, and continuing to refine types as necessary for the typescript migration.

Proposed Changes:

  1. Typing the lambda index files and api files, the main app file itself
  2. Adjusting types as necessary.

PR Checklist:

  • I have added my changes to the CHANGELOG or a CHANGELOG entry is not required.

@theodorehreuter theodorehreuter marked this pull request as draft April 2, 2026 16:28
@theodorehreuter theodorehreuter marked this pull request as ready for review April 7, 2026 14:54
Comment thread .vscode/settings.json
},
"editor.tabSize": 2,
"files.insertFinalNewline": true,
"typescript.tsserver.maxTsServerMemory": 4096,
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

temporary as it needs more memory in the mixed memory codebase, will remove on final PR to reduce this allocation once it's all typescript

Copy link
Copy Markdown
Collaborator

@pjhartzell pjhartzell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a few comments, the most important of which relates to the API app being re-created on each Lambda handler invocation.

const isSqsEvent = (event: SQSEvent | ApiRecord): event is SQSEvent => 'Records' in event

const isSnsMessage = (record) => record.Type === 'Notification'
const isSnsMessage = (record): record is SNSMessage => record.Type === 'Notification'
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we type record here in a manner similar to how it is done in isStacRecordRef above?

const isSnsMessage = (record: unknown): record is SNSMessage =>
  typeof record === 'object'
  && record !== null
  && 'Type' in record
  && record.Type === 'Notification'

Comment thread src/lambdas/api/index.ts
event: APIGatewayProxyEvent,
context: Context
): Promise<APIGatewayProxyResult> => {
const appInstance = await createApp()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want to move app creation from module scope (where it gets created once and reused across every warm Lambda invocation) to inside of callServerlessApp here, because callServerlessApp is called inside the handler function, which means the app gets created on every invocation (the handler function is run on every invocation) for a warm Lambda. I'm guessing that warm Lambda invocations are more the rule than the exception for the api. This is likely a non-trivial performance hit at scale.

The ingest lambda uses a pattern in index.ts that caches at the module level on the first call (see assetProxy and getAssetProxy) that could be a solution. Or not.

Comment thread src/lib/s3-utils.ts
getObjectBody(s3Location).then((b) => b.transformToString())

const getObjectJson = (s3Location: {bucket: string, key: string}): Promise<unknown> =>
const getObjectJson = (s3Location: {bucket: string, key: string}): Promise<StacItem> =>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without validation, I don't think we should use StacItem in the return. The function is a rather generic parsing of text to json. I think we should keep it as unknown here, and cast (or validate) to what we think it should be in the calling function. So this function just returns what its name (getObjectJson) indicates—some unknown json.

This function is currently called in only one place: src/lambdas/ingest/index.ts. Perhaps just add as StacRecord to the call site?

Comment thread src/lambdas/api/index.ts
Comment on lines +152 to +154
const parseEvent = (
rawEvent: APIGatewayProxyEvent
): APIGatewayProxyEvent => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the purpose of parseEvent is to validate that some untrusted (unknown) input and validate that it is an APIGatewayProxyEvent. So the input rawEvent should not be typed as an APIGatewayProxyEvent—only the output should be. The follow-on from this is that the call to parseEvent in the handler should likely not be passing something already typed as APIGatewayProxyEvent (which the handler event arg is typed as).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants