Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dynamo db): integrate with dynamo db #770

Conversation

kishore03109
Copy link
Contributor

@kishore03109 kishore03109 commented May 18, 2023

Problem

This is the first PR in the effort to remove the usage of queues in our backend.

Doesn't fully close IS-186, but am putting a feature flag in the spirit of merging some work into prod first.

Solution

The flag ARE_QUEUES_DEPRECIATED in InfraService.ts will determine whether or not to use the existing queues or use the dynamodbs vs queues for the site launch process. Idea is after the integration work in the infra side + enough testing, we can swap swap the value of the flag for one site launch process, and then if there are no issues for a while in production, we can remove this feature flag + queues related code altogether.

Breaking Changes

  • Yes - this PR contains breaking changes
    • Details ...
  • No - this PR is backwards compatible

Reviewer Notes
I am not sure if its only me but the typing given in the AWS SDK for dynamo DB is abit off ._.
I have given a screenshot in the related comment below + added test cases to explicitly codify the expected behaviour that we expect from the dynamoDBDocClient.send(new ScanCommand(params)) call. Open to feedback on this.

Steps to replicate the error thrown by ts

  1. Add this code in server.js:
import DynamoDBService from "@root/services/infra/DynamoDBService"
const dynamoDbService = new DynamoDBService(new DynamoDBDocClient())
const dynamoDBTests = async () => {
  // put item in dynamoDb
  const createResult = await dynamoDbService.createItem({
    repoName: "my-repo",
    appId: "my-app",
    primaryDomainSource: "example.com",
    primaryDomainTarget: "myapp.example.com",
    domainValidationSource: "example.com",
    domainValidationTarget: "myapp.example.com",
    requestorEmail: "[email protected]",
    agencyEmail: "[email protected]",
    githubRedirectionUrl: "https://github.com/my-repo",
    redirectionDomain: [
      {
        source: "example.com",
        target: "myapp.example.com",
        type: "A",
      },
    ],
    status: { state: "pending", message: "PENDING_DURING_SITE_LAUNCH" },
  })

  const updateResult = await dynamoDbService.getAllCompletedLaunches()
  console.log("result: ", updateResult.$metadata.httpStatusCode)
  // delete item from dynamoDB
}
dynamoDBTests()
  .then(() => {
    logger.info("Successfully connected to DynamoDB")
  })
  .catch((err) => {
    logger.error(`Unable to connect to DynamoDB: ${err}`)
  })

  1. Log over the returned entry in DynamoDBService.ts
async getAllCompletedLaunches(): Promise<SiteLaunchMessage[]> {
    const entries = ((await this.dynamoDBClient.getAllItems(this.TABLE_NAME))
      .Items as unknown) as SiteLaunchMessage[]
    const entriesWithSDKTypeCast : Record<string, AttributeValue>[] | undefined= (
      await this.dynamoDBClient.getAllItems(this.TABLE_NAME)
    ).Items

    console.log("entries", entries)
    console.log("entriesWithSDKTypeCast", entriesWithSDKTypeCast)

Note that the returned object is not of the declared type Record<string, AttributeValue>[] | undefined
Screenshot 2023-05-22 at 9 25 28 AM

New environment variables:

  • STEP_FUNCTIONS_ARN : arn for step functions //todo add in 1pw post-approval of this PR
  • ARE_QUEUES_DEPRECATED: Whether the queues are deprecated //todo add in 1pw post-approval of this PR

Tests

added a file DynamoDBService.spec.ts for tests

return this.dynamoDBClient.getItem(this.TABLE_NAME, MOCK_LAUNCH.appId)
}
async getAllSuccessOrFailureLaunches(): Promise<SiteLaunchMessage[]> {
const entries = ((await this.dynamoDBClient.getAllItems(this.TABLE_NAME))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Screenshot 2023-05-18 at 8 27 55 AM Somehow the typing that the SDK defines the object to have the [DynamoDB types](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html), but the return value already has returned the object of our desired shape O.o Since we are the only ones adding the items to the table, the risk of the shape being different from expected is low. Open to feedback on this !

Copy link
Contributor

@seaerchin seaerchin May 19, 2023

Choose a reason for hiding this comment

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

how do we replicate this behaviour (or if difficult, could you just attach an ss of the stringified Item itself so that we can see in entirety the properties)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Have updated the PR desc to include the steps, but the TLDR when logging the result over is:

Screenshot 2023-05-22 at 9 28 07 AM

For context, we should instead expect an object of a shape something similar to this:

{
  "appId": {
    "S": "my-app"
  },
  "agencyEmail": {
    "S": "[email protected]"
  },
  "domainValidationSource": {
    "S": "example.com"
  },
  "domainValidationTarget": {
    "S": "myapp.example.com"
  },
  "githubRedirectionUrl": {
    "S": "https://github.com/my-repo"
  },
  "primaryDomainSource": {
    "S": "example.com"
  },
  "primaryDomainTarget": {
    "S": "myapp.example.com"
  },
  "PRIMARY_KEY": {
    "S": "my-app"
  },
  "redirectionDomain": {
    "L": [
      {
        "M": {
          "source": {
            "S": "example.com"
          },
          "target": {
            "S": "myapp.example.com"
          },
          "type": {
            "S": "A"
          }
        }
      }
    ]
  },
  "repoName": {
    "S": "my-repo"
  },
  "requestorEmail": {
    "S": "[email protected]"
  },
  "status": {
    "M": {
      "message": {
        "S": "PENDING_DURING_SITE_LAUNCH"
      },
      "state": {
        "S": "pending"
      }
    }
  }
}

@kishore03109 kishore03109 marked this pull request as ready for review May 18, 2023 03:40
@kishore03109 kishore03109 force-pushed the IS-186-Backend-Add-in-integration-with-site-launch-and-dynamo-DB branch from 7acaebe to b109eed Compare May 19, 2023 07:29
@@ -52,6 +54,7 @@ type CreateSiteParams = {
isEmailLogin: boolean
}

const ARE_QUEUES_DEPRECIATED = false
Copy link
Contributor

Choose a reason for hiding this comment

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

if this is meant for feature flagging, then it should be an env var. this is because setting this to true still involves a code deployment to our backend (during which we might as well just change the actual code).

changing it to env vars allows us to deploy the required code without an associated code change (ie, we can deploy first and delete later)

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes that's right. Feature flags modifications shouldn't require a full re-deploy. Hence it shld be in the env vars

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, modified to use env vars instead here faed0d0

Copy link
Contributor

Choose a reason for hiding this comment

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

shall we impose a standard to prefix all feature flags with a FF_ARE_QUEUES_DEPRECATED?

This will allow us to quickly understand an env var is a feature flag toggle

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: the flag should be something like a verb instead of a question

like DISABLE_SITE_LAUNCH_QUEUES or DEPRECATE_SITE_QUEUES

Copy link
Contributor Author

Choose a reason for hiding this comment

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

microservices/site-launch/shared/types.ts Outdated Show resolved Hide resolved
microservices/site-launch/shared/types.ts Show resolved Hide resolved
src/config/config.ts Outdated Show resolved Hide resolved
src/config/config.ts Outdated Show resolved Hide resolved
src/services/infra/InfraService.ts Outdated Show resolved Hide resolved
src/services/infra/DynamoDBService.ts Show resolved Hide resolved
@kishore03109 kishore03109 requested a review from seaerchin May 22, 2023 08:18
src/services/infra/DynamoDBService.ts Outdated Show resolved Hide resolved
src/services/infra/InfraService.ts Outdated Show resolved Hide resolved
src/services/infra/InfraService.ts Outdated Show resolved Hide resolved
src/services/infra/InfraService.ts Outdated Show resolved Hide resolved
src/services/infra/InfraService.ts Outdated Show resolved Hide resolved
@@ -387,7 +404,9 @@ export default class InfraService {
}

siteUpdate = async () => {
const messages = await this.queueService.pollMessages()
const messages = DEPRECATE_SITE_QUEUES
? await this.dynamoDBService.getAllCompletedLaunches()
Copy link
Contributor

Choose a reason for hiding this comment

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

if any of this throws, are the errors caught appropriately?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

using a trivial try-catch wrapper here. Understand that we have an error handling portion to standardise the error formatting, will modify that when the scaffolding work for the error formatting is up! 0fa7912

private client: StepFunctions

constructor(private stateMachineArn: string) {
this.client = new StepFunctions({ region: "ap-southeast-1" })
Copy link
Contributor

Choose a reason for hiding this comment

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

should the region come from env vars?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, modified here ca073d1

Copy link
Contributor

Choose a reason for hiding this comment

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

@harishv7 out of curiosity - why inject it from env vars? my understanding is that it's a constant (as we aren't gonna change region) so i'd be more inclined to export it from a constants file

Copy link
Contributor

Choose a reason for hiding this comment

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

@seaerchin I am fine with a constants file too. I suggested env vars, because we are building this open source, for people to try this, they would need to know exactly what are the config they need to provide. Which would be better to come from an env-var or an explicit config.js file

@kishore03109 kishore03109 requested a review from harishv7 May 24, 2023 03:15
@kishore03109 kishore03109 merged commit b768fea into develop May 24, 2023
@kishore03109
Copy link
Contributor Author

@seaerchin Hey, let me know if you have any concerns regarding this PR via slack, happy to discuss / create new tickets if needed!

@mergify mergify bot deleted the IS-186-Backend-Add-in-integration-with-site-launch-and-dynamo-DB branch May 24, 2023 06:19
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.

3 participants