Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Portable Serverless Apps

Portable Serverless Apps

ServerlessDays, London, July 6th, 2018

Can you design serverless applications that run in multiple environments, for example having the same code executed in AWS Lambda and Docker containers? Or the same business logic being triggered via an API or while processing a real-time stream of data? In this session, we’ll review some best practices that make serverless development more readable, testable and reusable.

Danilo Poccia

July 06, 2018
Tweet

More Decks by Danilo Poccia

Other Decks in Programming

Transcript

  1. Portable Serverless Apps
    Danilo Poccia
    Evangelist, Serverless
    Amazon Web Services
    @danilop
    danilop
    [email protected]

    View full-size slide

  2. Serverless is for Builders

    View full-size slide

  3. How to Build a
    Serverless “Hello World” ?

    View full-size slide

  4. "use strict";
    console.log('Loading function');
    exports.handler = async (event, context) => {
    console.log('request: ' + JSON.stringify(event));
    let name; // default value is undefined
    if (event.queryStringParameters != null) {
    name = event.queryStringParameters.name;
    }
    console.log('name: ', name);
    if ((name == undefined) || (name == '')) {
    name = 'World';
    }
    const greetings = 'Hello ' + name + '!';
    console.log('greetings: ', greetings);
    const responseCode = 200;
    const responseBody = {
    message: greetings;
    };
    const response = {
    statusCode: responseCode,
    headers: {
    'Content-Type': 'application/json'
    },
    body: JSON.stringify(responseBody)
    };
    console.log('response: ' + JSON.stringify(response));
    return buildResponse();
    };
    { “message": "Hello Danilo!” }
    { “message": "Hello World!” }

    View full-size slide

  5. Event Function
    Your
    Business
    Logic
    Share
    Result

    View full-size slide

  6. “use strict";
    console.log('Loading function');
    // Your business logic
    function greetingsFor(name) {
    console.log('name: ', name);
    if ((name == undefined) || (name == '')) {
    name = 'World';
    }
    const greetings = 'Hello ' + name + '!';
    console.log('greetings: ', greetings);
    return greetings;
    }
    // Event wrapper for Amazon API Gateway
    exports.handler = async (event, context) => {
    let buildResponse = (message) => {
    const responseCode = 200;
    const responseBody = {
    message: message
    };
    const response = {
    statusCode: responseCode,
    headers: {
    'Content-Type' : 'application/json'
    },
    body: JSON.stringify(responseBody)
    };
    console.log('response: ' +
    JSON.stringify(response));
    return response;
    };
    console.log('request: ' + JSON.stringify(event));
    let name; // default value is undefined
    if (event.queryStringParameters != null) {
    name = event.queryStringParameters.name;
    }
    return buildResponse(greetingsFor(name));
    };
    // If not running on AWS Lambda, use Express
    if (!(process.env.LAMBDA_TASK_ROOT &&
    process.env.AWS_EXECUTION_ENV)) {
    const express = require('express');
    const app = express();
    let buildResponse = (message) => {
    const responseBody = {
    message: message
    };
    const response = JSON.stringify(responseBody);
    console.log('response: ' + response);
    return response;
    };
    app.get('/', function (req, res) {
    res.send(
    buildResponse(greetingsFor(req.query.name))
    );
    });
    console.log("Listening...");
    app.listen(process.env.PORT || 3000);
    }
    Business Logic Event Wrapper Web Interface

    View full-size slide

  7. Business Logic
    Docker
    Container
    AWS Lambda

    View full-size slide

  8. "use strict";
    console.log('Loading function');
    // Your business logic
    function greetingsFor(name) {
    console.log('name: ', name);
    if ((name == undefined) || (name == '')) {
    name = 'World';
    }
    const greetings = 'Hello ' + name + '!';
    console.log('greetings: ', greetings);
    return greetings;
    }
    "use strict";
    const app = require('../../app.js');
    const chai = require('chai');
    const expect = chai.expect;
    var event, context;
    describe('Tests index', function () {
    it('verifies successful response', async () => {
    const result = await app.lambda_handler(event, context, (err, result) => {
    expect(result).to.be.an('object');
    expect(result.statusCode).to.equal(200);
    expect(result.body).to.be.an('string');
    let response = JSON.parse(result.body);
    expect(response).to.be.an('object');
    expect(response.message).to.be.equal("Hello World!”);
    expect(response.location).to.be.an("string");
    });
    });
    });
    Business Logic Unit Tests

    View full-size slide

  9. Event
    Context
    Function
    Your
    Business
    Logic
    Share
    Result
    Unit Test

    View full-size slide

  10. greetingsFor.js
    event_APIGateway.js
    event_Kinesis.js
    app.js
    Platform Business Logic
    Adapter
    Amazon

    API Gateway
    Kinesis
    Data Stream
    Users
    Docker
    Container

    View full-size slide

  11. Portable App
    Clean Code
    Segregation of Concerns
    Adapter Pattern

    View full-size slide

  12. Portable Serverless Apps
    Danilo Poccia
    Evangelist, Serverless
    Amazon Web Services
    @danilop
    danilop
    [email protected]

    View full-size slide