📕
Dan Fitz's Notes
  • README
  • Ai
    • Supervised Machine Learning
      • Introduction To Machine Learning
      • Regression With Multiple Input Variables
      • Classification
  • Csharp
    • C Sharp Advanced
      • Generics
      • Delegates
      • Lambda Expressions
      • Events
    • C Sharp Fundamentals
      • Intro To C
      • Primitive Types And Expressions
      • Non Primitive Types
      • Control Flow
      • Arrays And Lists
      • Working With Dates
      • Working With Text
      • Working With Files
      • Debugging Applications
    • C Sharp Intermediate
      • Classes
      • Association Between Classes
      • Inheritance
      • Polymorphism
      • Interfaces
  • Java
    • Inheritance Data Structures Java
      • Inheritance Polymorphism Using Overriding And Access Modifiers
      • Abstract Classes And Debugging
      • File I O And Exceptions
      • Collections Maps And Regular Expressions
    • Intro To Java
      • Introduction To Java Classes And Eclipse
      • Unit Testing Arrays And Array Lists
      • Static Variables Methods And Polymorphism Using Overloading
  • Javascript
    • Algorithms Data Structures
      • Big O Notation
      • Analyzing Performance Of Arrays And Objects
      • Problem Solving Approach
      • Problem Solving Patterns
      • Recursion
      • Searching Algorithms
      • Bubble Selection And Insertion Sort
      • Merge Sort
      • Quick Sort
      • Radix Sort
      • Data Structures Introduction
      • Singly Linked Lists
      • Doubly Linked Lists
      • Stacks And Queues
      • Binary Search Trees
      • Tree Traversal
      • Binary Heaps
    • Complete Nodejs
      • Understanding Node.js
      • REST AP Is And Mongoose
      • API Authentication And Security
      • Node.js Module System
      • File System And Command Line Args
      • Debugging Node.js
      • Asynchronous Node.js
      • Web Servers
      • Accessing API From Browser
      • Application Deployment
      • Mongo DB And Promises
    • Complete React Native
      • Working With Content
      • Building Lists
      • Navigating Users Between Screens
      • State Management
      • Handling Screen Layout
      • Setting Up An App
      • More On Navigation
      • Advanced Statement Management With Context
      • Building A Custom Express API
      • In App Authentication
    • Epic React
      • React Fundamentals
      • React Hooks
      • Advanced React Hooks
      • Advanced React Patterns
      • React Performance
    • Fireship Firestore
      • Firestore Queries And Data Modeling Course
      • Model Relational Data In Firestore No SQL
    • Functional Light Javascript
      • Intro
      • Function Purity
      • Argument Adapters
      • Point Free
      • Closure
      • Composition
      • Immutability
      • Recursion
      • List Operations
      • Transduction
      • Data Structure Operations
      • Async
    • Js Weird Parts
      • Execution Contexts And Lexical Environments
      • Types And Operators
      • Objects And Functions
      • Object Oriented Java Script And Prototypal Inheritance
      • Defining Objects
    • Mastering Chrome Dev Tools
      • Introduction
      • Editing
      • Debugging
      • Networking
      • Auditing
      • Node.js Profiling
      • Performance Monitoring
      • Image Performance
      • Memory
    • React Complete Guide
      • What Is React
      • React Basics
      • Rendering Lists And Conditionals
      • Styling React Components
      • Debugging React Apps
      • Component Deep Dive
      • Building A React App
      • Reaching Out To The Web
      • Routing
    • React Testing
      • Intro To Jest Enzyme And TDD
      • Basic Testing
      • Redux Testing
      • Redux Thunk Testing
    • Serverless Bootcamp
      • Introduction
      • Auction Service Setup
      • Auction Service CRUD Operations
      • Auction Service Processing Auctions
    • Testing Javascript
      • Fundamentals Of Testing
      • Static Analysis Testing
      • Mocking Fundamentals
      • Configuring Jest
      • Test React Components With Jest And React Testing Library
    • Typescript Developers Guide
      • Getting Started With Type Script
      • What Is A Type System
      • Type Annotations In Action
      • Annotations With Functions And Objects
      • Mastering Typed Arrays
      • Tuples In Type Script
      • The All Important Interface
      • Building Functionality With Classes
    • Web Performance With Webpack
      • Intro
      • Code Splitting
      • Module Methods Magic Comments
  • Other
    • Algo Expert
      • Defining Data Structures And Complexity Analysis
      • Memory
      • Big O Notation
      • Logarithm
      • Arrays
      • Linked Lists
      • Hash Tables
      • Stacks And Queues
      • Strings
      • Graphs
      • Trees
    • Aws Solutions Architect
      • AWS Fundamentals IAM EC 2
    • Fundamentals Math
      • Numbers And Negative Numbers
      • Factors And Multiples
      • Fractions
    • Mysql Bootcamp
      • Overview And Installation
      • Creating Databases And Tables
      • Inserting Data
      • CRUD Commands
      • The World Of String Functions
      • Refining Our Selections
      • The Magic Of Aggregate Functions
    • Random Notes
      • Understanding React Hooks
  • Python
    • Data Analysis Using Python
      • Loading Querying And Filtering Data Using The Csv Module
      • Loading Querying Joining And Filtering Data Using Pandas
      • Summarizing And Visualizing Data
    • Intro To Python
      • Course Introduction Intro To Programming And The Python Language Variables Conditionals Jupyter Notebook And IDLE
      • Intro To Lists Loops And Functions
      • More With Lists Strings Tuples Sets And Py Charm
      • Dictionaries And Files
Powered by GitBook
On this page
  • Creating Scheduled Events
  • Viewing logs from terminal
  • Executing functions manually for testing
  • Adding a Global Secondary Index
  • Updating key definitions in serverless.yml
  • Querying by Global Secondary Index
  • Setup
  • Query syntax
  • Processing auctions by closing them
  • JSON Schema Validation
  1. Javascript
  2. Serverless Bootcamp

Auction Service Processing Auctions

PreviousAuction Service CRUD OperationsNextTesting Javascript

Last updated 3 years ago

Creating Scheduled Events

We want to process auctions that have hit their deadline (like an eBay auction).

You can do this by creating a lambda function that triggers on a scheduled event. In your serverless.yml, you just add this:

processAuctions:
  handler: src/handlers/processAuctions.handler
  events:
    - schedule: rate(1 minute)

Notes:

  • We're using the rate expression to set up the scheduling rules. You can also use the cron syntax. Amazon explains both .

  • schedule uses AWS EventBridge behind the scenes.

Viewing logs from terminal

Serverless gives you the sls log command to be able to view CloudWatch logs from your terminal.

To view a trailing number of logs for your lambda function:

sls logs -f processAuctions -t

To view logs from a chunk of the past:

sls logs -f processAuctions --startTime 1h

Executing functions manually for testing

Scheduled events are not always great for development. It's therefore better to comment out the events part of your lambda function and then trigger the function manually instead.

To trigger a function manually, just type this in the terminal:

sls invoke -f processAuctions -l

Note: -l just returns the logs for the function.

Adding a Global Secondary Index

As of right now, our application can only identify auctions in DynamoDB using the id primary partition key.

For processAuctions, we want to close auctions that have a status: 'OPEN' and an endingAt that is in the past.

Therefore, to query these auctions in a performant way, we want to make status into a partition key and endingAt into a sort key.

Updating key definitions in serverless.yml

To add a global secondary index, we add this under Properties in the DynamoDB setup:

AttributeDefinitions:
  - AttributeName: id
    AttributeType: S # string
  - AttributeName: status
    AttributeType: S
  - AttributeName: endingAt
    AttributeType: S
KeySchema:
  - AttributeName: id
    KeyType: HASH
GlobalSecondaryIndexes:
  - IndexName: statusAndEndDate
    KeySchema:
      - AttributeName: status
        KeyType: HASH
      - AttributeName: endingAt
        KeyType: RANGE
    Projection:
      ProjectionType: ALL

The main thing to note in this config is that we set the global secondary index in GlobalSecondaryIndexes and create a custom IndexName.

Things to note:

  • AttributeDefinitions declares the attributes that will be used as keys

  • KeySchema is where we define the primary key

  • HASH sets the attribute to a partition key (or hash attribute)

  • RANGE sets the attribute to a sort key (where the database stores items in sorted order)

  • ProjectionType: ALL projects all attributes into the global secondary index.

Pro tip: Behind the scenes, when you create a global secondary index, DynamoDB creates a virtual copy of your table, making it possible to query efficiently based on the global secondary index.

Querying by Global Secondary Index

Setup

We now can begin using Query to efficiently get auctions that we want to close.

To begin, we need to (1) give query permissions in IAM and (2) add the new table used by the global secondary index statusAndEndDate.

AuctionsTableIAM:
  Effect: Allow
  Action:
    # ...
    - dynamodb:Query
  Resource:
    - ${self:custom.AuctionsTable.arn}
    # The ARN for a GSI table is usually the main ARN
    # ending with /index/globalSecondaryIndexName
    - !Join [
        '/',
        ['${self:custom.AuctionsTable.arn}', 'index', 'statusAndEndDate'],
      ]

Query syntax

The actual query has a few parts:

const params = {
  TableName: process.env.AUCTIONS_TABLE_NAME,
  IndexName: 'statusAndEndDate',
  KeyConditionExpression: '#status = :status AND endingAt <= :now',
  ExpressionAttributeValues: {
    ':status': 'OPEN',
    ':now': new Date().toISOString(),
  },
  ExpressionAttributeNames: {
    '#status': 'status',
  },
};

const result = await dynamoDb.query(params).promise();

Things to note:

  • KeyConditionExpression uses DynamoDB's query syntax

  • The variables :status and :now are set inside ExpressionAttributeValues

  • #status begins with a # because status is a reserved keyword; we resolve #status to mean status in ExpressionAttributeNames

Processing auctions by closing them

Now that we have a list of auctions that we want to close, we can flesh out our processAuctions handler/lambda.

async function processAuctions(event, context) {
  try {
    const auctionsToClose = await getEndedAuctions();
    const closePromises = auctionsToClose.map(closeAuction);
    await Promise.all(closePromises);
    return { closed: closePromises.length };
  } catch (error) {
    console.error(error);
    throw new createError.InternalServerError(error);
  }
}

High-level, here's what processAuctions is doing:

  1. Gets all auctions to close

  2. Asynchronously closes each auction.

  3. Waits for all closures to resolve.

  4. Returns number of closed auctions.

    • Notice that the return object isn't an HTTP response. That's because this lambda isn't triggered by API Gateway.

To flesh out closeAuction some more, it just contains an Update operation to the DynamoDB table. Specifically, it sets status to 'CLOSED'.

async function closeAuction(auction) {
  const params = {
    TableName: process.env.AUCTIONS_TABLE_NAME,
    Key: { id: auction.id },
    UpdateExpression: 'set #status = :status',
    ExpressionAttributeValues: {
      ':status': 'CLOSED',
    },
    ExpressionAttributeNames: {
      '#status': 'status',
    },
  };

  return await dynamoDb.update(params).promise();
}

JSON Schema Validation

The course spends some time explaining how to use @middy/validator to create schemas that help you error handle missing user inputs for API endpoints.

The documentation explains it well enough.

here
@middy/validator