May 6, 2020

SNS

SNS is the notification service provided by AWS, which manages the delivery of a message to any number of subscribers. It uses the publisher/subscriber model for push delivery of messages. Subscribers are notified using following supported protocols - SQS, lambda, http/s, email, SMS. 

To use SNS, you create a topic and define a policy that dictates who can publish and subscribe to it. You can define policy by configuring the condition to give cross-account access. An SNS request has a Topic where you want to publish to, Subject, Message, MessageAttributes, MessageStructure. 

The subscriber can define subscription filter policy and dead-letter queues. By configuring the subscription filter policy, you can filter the message to be sent to the subscriber based on rules defined on the message attribute. You can assign a redrive policy to Amazon SNS subscriptions by specifying the Amazon SQS queue that captures messages that can't be delivered to subscribers successfully. You can test this by deleting the endpoint like lambda function. 

When you configure dead letter Q, you need to make sure, that SNS has the necessary permission to publish the message to the Q, by adding permission policy in SQS with SNS earn. Once a message is in dead letter Q, you can either have lambda configured to process them and also use cloud watch metrics to monitor dead letter Q.

SNS -> Lambda vs SNS -> SQS -> Lambda

If you have SQS in between SNS and Lambda, it can give you the flexibility of reprocessing. You may be able to set Redrive policy for SQS and set Maximum Receives, which essentially means the message will be received by lambda that many numbers of times before being sent to the dead letter Q. If no Redrive policy is set, then after every visibility timeout, the message will be sent to the lambda, until the message retention period. In case when SNS directly sends the message to lambda, its only one time, and if it fails it will get sent to the dead letter Q if Redrive policy is set. With SQS you can have a retention period of at least up to 14 days.

SQS retry happens after the visibility timeout occurs and the visibility timeout should be more than lambda timeout which essentially makes sure the message is sent to lambda only after lambda processing is completely done, which prevents duplicate processing of the message.

In Sqs (Pull Mechanism) messages are persisted for some (configurable) duration if no consumer is available, whereas in Sns (Push Mechanism) messages are sent to the subscribers which are there at the time when the message arrives.


Apr 14, 2020

React Introduction

React helps you build encapsulated components that manage their state, then compose them to make complex UI. The component has Props & State which represents its model. The data flow one way down the component hierarchy. 

state => view => action => state => view

View


The view is the direct result of rendering DOM using ReactDOM.render from the react-dom package. For a given model the DOM will always be the same, so the only way to change DOM is to change the model. Once a model is rendered in DOM, it can generate events that feedback into the state and trigger another render cycle. Once a state is changed react will render DOM. A state is always owned by one Component. Any data that’s affected by this state can only affect Components and its children. Changing state on a Component will never affect its parent, or its siblings, or any other Component in the application.

For efficient rendering, React maintain its document obstruction. A component render function updates this fake document object model known as the virtual DOM which is extremely fast. Once that happens react compares the fake document object model to the real document object model and update the real document object model in the most efficient way possible. Updating DOM is an expensive operation as redrawing large sections of DOM is inefficient. The comparison of virtual DOM with a real document happens in memory. 

ReactDOM takes two arguments: the first argument is JSX expression and the 2nd argument is dom element, this is the place where the react component will be inserted into the DOM element.

JSX


It's an XML like syntax extension to javascript which is used to describe how UI will look like. You can put any valid JavaScript expression inside the curly braces in JSX. Since the browser doesn't understand JSX, so it must be compiled to javascript, which is handled by bable. You may have an option to write directly the javascript and not JSX, but that may not be easier to write/read/maintain. If you are interested you can use https://babeljs.io/ to see how JSX is compiled to javascript. Writing HTML in javascript looked a little weird if you come from the angular background, but if you really think even in angular you write javascript in angular HTML like ngFor, etc. So either way, you have one of the two options - write js in HTML or HTML in js. One advantage I see with HTML in js is that at compile time you can catch an error. There are few minor differences between JSX and HTML like className for class and htmlFor for for. JSX can represent two types of element

  • DOM tag like div, dom tags are written in lower case, attributes passed to these elements are set on rendered DOM
  • User definer element must be starting with a capital letter. attributes to user-defined elements are passed to the component as a single object, usually referred to as props. All react components must act like pure functions with respect to their props, for a given prop output should be same and component needs to be rendered only if prop changes

Props and State


Props is short for properties. It allows you to pass data to the child component. Props are immutable as they are passed down from parent to child, so they are owned by the parent, so you cannot change it. On the other hand, the state is used to hold data that your component need to change for example value of the text field. To update state you use setState

Event


React events (called synthetic event) are very similar to dom events, with few minor differences like name with camel case compare to lower case and function being passed as event handler rather than string. To prevent default you need to call preventDefault on the event object. SyntheticEvent are cross-browser wrapper around the browser’s native event. You can access browser native event by accessing nativeEvent. Since data flow one way, the only way to pass data is to raise event and update state which will eventually trigger view update. The same way you can pass data to the parent component, by calling function passed in the props.

Angular vs React

Both are component-based platform-agnostic rendering frameworks/tools, which you can write using typescript or javascript.

Data Binding
Angular uses two-way data binding which helps write less boilerplate code to have a model and view in sync. React supports one-way data binding which makes debugging easier and maybe help in performance

Architecture
Angular is a full-blown framework that includes DI, forms, routing, navigation, HTTP implementation, directives, modules, decorators, services, pipes, templates with few advanced features like change detection, Ahead-of-Time compilation, lazy loading,  and Rx.js. This is built into core of the framework. React is much simple and you will have to use other libraries like redux, react-router, etc to make a complex application. React has a wider range of material design component libraries available.

CLI
Angular cli is a powerful command-line interface that assists in creating apps, adding files, testing, debugging, and deployment. Create React App is a CLI utility for React to quickly set up new projects


Mar 11, 2020

Running .NET Core 3.1 on AWS Lambda

AWS Lambda supports multiple languages through the use of runtimes. To use languages that are not natively supported, you can implement custom runtime, which is a program that invokes the lambda function's handler method. The runtime should be included in the deployment package in the form of an executable file named bootstrap. Here is the list of things which you need to do in order to run a .NET Core 3.1 on AWS lambda.

bootstrap

Since this is not a supported runtime, you need to include a bootstrap file which is a shell script that Lambda host calls to start the custom runtime.
#!/bin/sh
/var/task/YourApplicationName

Changes to project file

You need a couple of NuGet packages from Amazon.LambdaAspNetCoreServer and RuntimeSupport. AspNetCoreServer provides the functionality to convert API Gateway’s request and responses to ASP.NET Core’s request and responses and RuntimeSupport provides support for using custom .NET Core Lambda runtimes in Lambda

<PackageReference Include="Amazon.Lambda.AspNetCoreServer" Version="4.1.0" />
<PackageReference Include="Amazon.Lambda.RuntimeSupport" Version="1.1.0" /> 

Apart from that, you need to make sure to include bootstrap in the package and change the project output type to exe.

<OutputType>Exe</OutputType>

<ItemGroup>
    <Content Include="bootstrap">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
</ItemGroup> 

Add Lambda entry point

This class extends from APIGatewayProxyFunction which contains the method FunctionHandlerAsync which is the actual Lambda function entry point. In this class override the init method where you need to configure startup class using the UseStartup<>() method. If you have any special requirements, you can use FunctionHandlerAsync, where you can write your own handler. One example will be lambda warmer, where you don't want the actual code to be executed, rather you would want to respond directly from this method. The following code snippet is just for reference purpose, with provisioned concurrency supported in AWS lambda, you can achieve the same


public override async Task<APIGatewayProxyResponse> FunctionHandlerAsync(APIGatewayProxyRequest request, ILambdaContext lambdaContext)
        {
            if (request.Resource == "WarmingLambda")
            {
                if (string.IsNullOrEmpty(containerId)) containerId = lambdaContext.AwsRequestId;
                Console.WriteLine($"containerId - {containerId}");

                var concurrencyCount = 1;
                int.TryParse(request.Body, out concurrencyCount);

                Console.WriteLine($"Warming instance { concurrencyCount}.");
                if (concurrencyCount > 1)
                {
                    var client = new AmazonLambdaClient();
                    await client.InvokeAsync(new Amazon.Lambda.Model.InvokeRequest
                    {
                        FunctionName = lambdaContext.FunctionName,
                        InvocationType = InvocationType.RequestResponse,
                        Payload = JsonConvert.SerializeObject(new APIGatewayProxyRequest
                        {
                            Resource = request.Resource,
                            Body = (concurrencyCount - 1).ToString()
                        })
                    });
                }
                
                return new APIGatewayProxyResponse { };
            }
        
            return await base.FunctionHandlerAsync(request, lambdaContext);

        }

Update Main function

In NET Core 2.1 which is native Lambda runtime, the LambdaEntryPoint is loaded by Lambda through reflection(through the handler configuration) but with custom runtime, this needs to be loaded by the main function. To make sure the ASP.NET Core project works locally using Kestrel, you can check if AWS_LAMBDA_FUNCTION_NAME environment variable exists.


if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("AWS_LAMBDA_FUNCTION_NAME")))
{
CreateHostBuilder(args).Build().Run();
}
else
{
var lambdaEntry = new LambdaEntryPoint();
var functionHandler = (Func<APIGatewayProxyRequest, ILambdaContext, Task<APIGatewayProxyResponse>>)(lambdaEntry.FunctionHandlerAsync);
using (var handlerWrapper = HandlerWrapper.GetHandlerWrapper(functionHandler, new JsonSerializer()))
using (var bootstrap = new LambdaBootstrap(handlerWrapper))
{
bootstrap.RunAsync().Wait();
}
}

Add defaults file

.NET Lambda command-line tools and VS deployment wizard use a file called aws-lambda-tools-defaults.json for settings to use for packaging Lambda project into a zip file ready for deployment and for deployment. Deployment under the hood uses cloud formation. Run following to explore more about tool
dotnet lambda help

Cli Command

dotnet lambda package --output-package lambda-build/deploy-package.zip
dotnet lambda help