text:
# Dexih.Utils.ManagedTasks

[build]:    https://ci.appveyor.com/project/dataexperts/dexih-utils-managedtasks
[build-img]: https://ci.appveyor.com/api/projects/status/txclrfnvgcgvomj7?svg=true
[nuget]:     https://www.nuget.org/packages/Dexih.Utils.ManagedTasks
[nuget-img]: https://badge.fury.io/nu/Dexih.Utils.ManagedTasks.svg
[nuget-name]: Dexih.Utils.ManagedTasks
[dex-img]: https://dataexpertsgroup.com/assets/img/dex_web_logo.png
[dex]: https://dataexpertsgroup.com

[![][dex-img]][dex]

[![Build status][build-img]][build] [![Nuget][nuget-img]][nuget]

The `ManagedTasks` library is a simple and flexible library for scheduling and executing multiple tasks within a .net application.

The primary benefits:

 * Orchestrate a large number of simultaneous tasks.
 * Allow tasks to provide progress.
 * Allow tasks to be cancelled.
 * Allow tasks to be schedule once off, and on a recurring schedule.
 * Allow tasks to be started based on a file watcher event.
 * Start a task when one or more tasks complete.
 * Tasks can run sequentially or in parallel.
 * Get snapshots of running and completed tasks
 * Events to provide task status changes.

---

## Installation

Add the [latest version][nuget] of the package "Dexih.Utils.ManagedTasks" to a .net core/.net project.  This requires .net standard framework 2.0 or newer, or the .net framework 4.6 or newer.

---

## Getting started

To initialize the scheduler simply create an instance of the `ManagedTasks` class, and connect the `OnProgress` and `OnStatus` events.

```csharp
var managedTasks = new ManagedTasks();
managedTasks.OnProgress += Progress;
managedTasks.OnStatus += Status;

void Progress(ManagedTask managedTask, ManagedTaskProgressItem progressItem)
{
    // progress tasks
}

void Status(ManagedTask managedTask, EManagedTaskStatus status)
{
    // status
}
```

The `OnProgress` event will be called whenever a task reports a progress event.
The `OnStatus` event will be called whenever a task reports a progress event.  The events which trigger this are Created, FileWatching, Scheduled, Queued, Running, Cancelled, Error, Completed.

Tasks need to be wrapped in a task derived from the `ManagedObject` class or `IManagedObject` interface.

```csharp
// task counts to 5 in 5 seconds.
public class CountTask : ManagedObject
{
    public override async Task StartAsync(ManagedTaskProgress progress, CancellationToken cancellationToken = default)
    {
        for (var i = 0; i < 5; i++)
        {
            await Task.Delay(1000, cancellationToken);
            var percent = (i+1) * 5;

            // report progress every second
            progress.Report( $"step: {i+1}");
        }
    }
}
```

To run the task, use the `Add` function to added it to the `ManagedTasks` instance.

```csharp
var countTask = new CountTask();

Console.WriteLine("Run one task.");
managedTasks.Add(new ManagedTask()
{
    TaskId = Guid.NewGuid().ToString(),
    Name = "count to 5",
    ManagedObject = countTask
});
```

To wait for all the tasks to complete, use the `WhenAll()` function.

```csharp
await managedTasks.WhenAll();
```

## Scheduling Tasks

Tasks can be scheduled by adding triggers to the `ManagedTask`.

A simple trigger to schedule once off can be created.

```csharp
// trigger will be started 5 seconds from now.
var trigger = new ManagedTaskTrigger(DateTime.Now.AddSeconds(5);
```

Another simple trigger can be created to run a job multiple times based on an interval.

```csharp
// trigger will execute every 5 seconds, a maximum of 10 times.
var trigger = new ManagedTaskTrigger(TimeSpan.FromSeconds(5), 10)
```

To use a trigger, add it to the `Triggers` property of the `ManagedTask`.

```csharp
var managedTask = new ManagedTask()
{
    TaskId = Guid.NewGuid().ToString(),
    Name = "count to 5",
    ManagedObject = countTask,
    Triggers = new [] { new ManagedTaskTrigger(TimeSpan.FromSeconds(6), 2)}
};
```

When multiple triggers are added to the `Triggers` property, the job will run on the next trigger of any of the triggers.

Advanced triggers can be created by setting the following properties within the `ManagedTaskTrigger`.

|Property|Description|
|-|-|
|StartDate|The earliest date to start the task.  Note, the time component is ignored, use the StartTime.|
|EndDate|The last date to start the task.  Note, the time component is ignored, use the StartTime.|
|StartTime|The earliest time of the day the job will start.  If null, the starttime will be default to the next second.
|EndTime|The latest time of the day the job will start.
|MaxRecurs|The maximum number of time to recur in an interval.
|IntervalType|The type of interval.  Once = no interval, Interval = Run every `IntervalTime`, Daily = Run every day, Monthly = Run every month.
|IntervalTime|If the `IntervalType` is set to `Interval`, the time between intervals.  Note, the interval time is based on the starting time of the previous job.  For example if the interval time is 60 seconds, the job will run every 60 seconds, irregardless of the time the job takes to execute.
|DaysOfWeek|Array containing the days of the week to run the job.  If empty/null the job will run on any day of week.
|DaysOfMonth|Array containing the days of the month to run the job.  If empty/null the job will run on any day of month.
|WeeksOfMonth|Array containing the weeks of the month to run the job.  If empty/null the job will run on any week of the month
|SkipDates|Array containing specific dates (such as public holidays) to skip.

## File Watching

Tasks can be triggered based on the creation of a file.

Use the `ManagedTaskFileWatcher` class to create file watching trigger based on a path and with a file pattern.

```csharp
var fileWatch = new ManagedTaskFileWatcher('/data/', "trigger_file_*");

var managedTask = new ManagedTask()
{
    TaskId = Guid.NewGuid().ToString(),
    Name = "start on file",
    ManagedObject = countTask,
    FileWatchers = new [] { fileWatch }
};
```
## Task Concurrency

Tasks that have the same `Category` and `CategoryKey` are grouped for the purposes of concurrency.

If a task if part of the same category is added `ConcurrentTaskAction` determines the concurrency:
* Parallel - Runs the tasks in parallel based on their schedule.
* Sequence - Runs the tasks of the same category in sequence.
* Abend - Throws an exception when tasks of the same category are run simultaneously.

The following sample will run the two tasks in sequence:

```csharp
var managedTasks = new ManagedTasks();

var task1 = new ManagedTask
{
    TaskId = Guid.NewGuid().ToString(),
    Name = "test",
    Category = "category",
    CategoryKey = 1,
    ManagedObject =  new ProgressTask(20, 1),
    ConcurrentTaskAction = EConcurrentTaskAction.Sequence
};

var task2 = new ManagedTask
{
    TaskId = Guid.NewGuid().ToString(),
    Name = "test",
    Category = "category",
    CategoryKey = 1,
    ManagedObject =  new ProgressTask(0, 1),
    ConcurrentTaskAction = EConcurrentTaskAction.Sequence
};

managedTasks.Add(task1);
managedTasks.Add(task2);

await managedTasks.WhenAll();
```

## Task Dependencies

Tasks can be executed based on the outcome of another task or tasks.

In order to set dependent tasks on a task use the `DependentTaskIds` property to specify the `TaskId` of the dependent tasks.

The following example will run task1 until completion, and then task2.

```csharp
var managedTasks = new ManagedTasks();

managedTasks.Add(new ManagedTask()
{
    TaskId = "ref1",
    Name = "task1",
    ManagedObject = countTask
});

managedTasks.Add(new ManagedTask()
{
    TaskId = "ref2",
    Name = "task2",
    ManagedObject = countTask,
    DependentTaskIds = new []{"ref1"}
});

await managedTasks.WhenAll();
```

## Task / Scheduler Communication

The `ManagedObject` class is used to wrap a task.  The following method can be overrided in this class to communicate between the task and the scheduler:

|Method|Description|
|-|-|
|StartAsync|(Mandatory) Executed when the task is started|
|Schedule|Executed when a task is scheduled|
|Cancel|Called when a cancel request is made for the class through the ManagedTask.Cancel() or ManagedTasks.Cancel() functions.|
|Dispose|Called when a task is finished|
|Data|Any object data that is automatically mapped to the `ManagedTask` object.|

The following skeleton shows how to construct a managed object.
```csharp
// task counts to 5 in 5 seconds.
public class CustomTask : ManagedObject
{
    public override async Task StartAsync(ManagedTaskProgress progress, CancellationToken cancellationToken = default)
    {
        // run task actions

        // use progress to send progress updates
        progress.Report("progress details");
    }

    public override void Cancel()
    {
        // cancel actions
    }

    public override void Dispose()
    {
        // dispose actions
    }

    public override void Schedule(DateTime startsAt, CancellationToken cancellationToken = default)
    {
        // schedule actions
    }
}
```

## Task Management

The `ManagedLibrary` has a number of methods and properties that can be used to manage tasks.

The following examples show how to interact with the managed tasks.

```csharp
var managedTasks = new ManagedTasks();

//
// add tasks to schedule
//

// iterate through active tasks (includes running, scheduled)
foreach(var managedTask in managedTasks)
{
    // review task
}

// iterate through all scheduled (but not running tasks)
foreach(var managedTask in managedTasks.GetScheduledTasks())
{
    // review task
}

// iterate through all running tasks
foreach(var managedTask in managedTasks.GetRunningTasks())
{
    // review task
}

// iterate through all completed tasks
foreach(var managedTask in managedTasks.GetCompletedTasks())
{
    // review task
}

// iterate through all tasks which changed status since last call
foreach(var managedTask in managedTasks.GetTaskChanges())
{
    // review task
}

// cancel all tasks
await CancelAsync();

// wait for all active tasks to finish
await managedTasks.WhenAll();

```

## Managed Task Properties

The `ManagedTask` class is used by the managed tasks.  The class has the following properties which should be set prior to starting the task.

|Property|Description|
|-|-|
|TaskId|A unique id representing the task.|
|Name|A name for the task|
|Description|Any description for the task|
|Category|A category used to group tasks types.|
|CategoryKey|A key used to determine related tasks when using the ConcurrentAction setting.
|ConcurrentTaskAction|Concurrency option when starting more than one task that has the same Category/CategoryKey.  The options are Abend - throws exception, Parallel - runs in parallel, and Sequential - waits for related task to complete first.
|Triggers|An array containing the `ManagedTaskTrigger` which determine the schedule fo the task.
|FileWatchers|An array containing the `ManagedTaskFileWatcher`
|DependentTaskIds|
|ManagedObject|A reference to an instance of a class derived from `ManagedObject`.  This contains the task logic to execute.
|Data|Object which can be use to pack any required data onto the task|
|ReferenceKey|Long which can be used for any purpose|
|ReferenceId|String which can be used for any purpose|

The following properties should not be manually changed, however can be used to determine the status of a task.

|Property|Description|
|-|-|
|Status|The current status of the task.  Valid status' are Created, FileWatching, Scheduled, Queued, Running, Cancelled, Error, Completed|
|Percentage|The percentage complete the task is.  This is set through the `ManagedTaskProgress` class passed to the `StartAsync` function in the `ManagedObject`.
|Counter|A counter which can be used to indicate progress.  This is update through the `ManagedTaskProgress` class.
|StepName|A string value which be used to indicate progress.  This is update through the `ManagedTaskProgress` class.
|StartTime|Date/Time the task started|
|EndTime|Date/Time the task finished|
|NextTriggerTime|The date/time the task will be next triggered.
|RunCount|The number of times the task has been run

## Complete Demo

The following example is a complete sample application that uses the `HostBuilder` to start a console service, and then schedules a managed task that reports progress.

[Dotnet Fiddle Example](https://dotnetfiddle.net/ZLhpLf)

```csharp
using System;
using System.Threading;
using System.Threading.Tasks;
using Dexih.Utils.ManagedTasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace ManagedTaskDemo
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var hostBuilder = new HostBuilder()
                .ConfigureServices((hostContext, services) =>
                {
                    // add a singleton to host the ManagedTasks service
                    services.AddSingleton<IManagedTasks, ManagedTasks>();

                    // add a hosted service, which will kick off some scheduled tasks.
                    services.AddHostedService<TaskService>();
                });

            var host = hostBuilder.Build();
            await host.RunAsync();
        }
    }

    public class TaskService : IHostedService
    {
        private readonly IManagedTasks _managedTasks;

        public TaskService(IManagedTasks managedTasks)
        {
            _managedTasks = managedTasks;

            // track status changes
            managedTasks.OnStatus += TaskStatusChange;

            // track progress changes
            managedTasks.OnProgress += TaskProgressChange;
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            // add a new count task that reruns every 10 seconds.
            _managedTasks.Add(new ManagedTask()
            {
                TaskId = Guid.NewGuid().ToString(),
                Name = "count to 5",
                ManagedObject = new CountTask(),
                Triggers = new [] { new ManagedTaskTrigger(TimeSpan.FromSeconds(10), 1000)}
            });

            return Task.CompletedTask;
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            return Task.CompletedTask;
        }
        private void TaskStatusChange(ManagedTask value, EManagedTaskStatus managedTaskStatus)
        {
            Console.WriteLine($"Task Status: {value.Name}, Status: {managedTaskStatus}");
        }

        private void TaskProgressChange(ManagedTask value, ManagedTaskProgressItem progressItem)
        {
            Console.WriteLine($"Task Progress: {value.Name}, Step: {progressItem.StepName}");
        }
    }

    // task counts to 5 in 5 seconds.
    public class CountTask : ManagedObject
    {
        public override async Task StartAsync(ManagedTaskProgress progress, CancellationToken cancellationToken = default)
        {
            for (var i = 0; i < 5; i++)
            {
                await Task.Delay(1000, cancellationToken);
                var percent = (i+1) * 5;

                // report progress every second
                progress.Report( $"step: {i+1}");
            }
        }
    }
}
```

This will output as follows
```
Task Status: count to 5, Status: Scheduled
Task Status: count to 5, Status: Running
Task Progress: count to 5, Step: step: 1
Task Progress: count to 5, Step: step: 2
Task Progress: count to 5, Step: step: 3
Task Progress: count to 5, Step: step: 4
Task Progress: count to 5, Step: step: 5
Task Status: count to 5, Status: Completed
Task Status: count to 5, Status: Scheduled
... continues to repeat
```

## Issues and Feedback

This library is provided free of charge under the MIT licence and is actively maintained by the [Data Experts Group](https://dataexpertsgroup.com)

Raise issues or bugs through the issues section of the git hub repository ([here](https://github.com/DataExperts/Dexih.Utils.ManagedTasks/issues))

gha_language: C#


text:
# swift-button

WekanButton is a custom button with different types and styles. You can also customise it.

![alt text](https://github.com/WekanCompany/swift-button/blob/master/readme_screenshot.png)

## How to use ##

* Drag-drop the ```` WekanButton.swift```` class to your project.

* Declare the button as WekanButton
 ````
 @IBOutlet weak var loginButton: WekanButton!
````

* When adding UIButton in storyboard, change class to ```` WekanButton ````, and change the button type to ````custom````.  Set the requitred constraints.

* Configure the buttons as shown in the sample ViewController
````
loginButton.configure(withContent: .textOnly,
                          backgroundType: .outlined,
                          cornerType: .smooth,
                          text: "Login")
````

## Supports ##

* Corners/Edges - Sharp edge, smooth edge, rounded
* Outlines/Borders
* Background colors
* Background colors with gradient - horizontal and vertical gradients
* Shadows
* Buttons with content as text, icons and their combinations

license: MIT

repository: WekanCompany/swift-button

branch_name: refs/heads/master

extension: md

license_type: permissive

repo_name: WekanCompany/swift-button


text:
---
title: FaaS comes to Fargate: OpenFaaS with AWS Fargate
description: Edward Wilde introduces faas-fargate, or OpenFaaS for AWS Fargate. Learn about a simple, low-cost way to deploy and run OpenFaaS functions on AWS without managing servers
date: 2019-02-12
image: /images/openfaas-on-fargate/astronomy-atmosphere-earth-220201.jpg
categories:
  - fargate
  - automation
  - tutorial
author_staff_member: ed
dark_background: true
---

How to run OpenFaaS on AWS Fargate with economical, auto-scaling containers. A low friction AWS
native deployment using VPCs, ECS, security groups, ALBs, AWS Secrets Manager and AWS Route 53 for
DNS, load-balancing and service discovery.

Experience required:

* Basic-level OpenFaaS
* Intermediate-level AWS

This article will explain why I've chosen to run OpenFaaS on AWS Fargate. We then move on to explore
how to deploy a fully working environment and run our first function.

For me, one of the best things about OpenFaaS is how portable it is. You can run OpenFaaS out of the box using
officially supported platforms like Kubernetes and Docker Swarm . The [community](https://github.com/openfaas/faas/blob/master/community.md)
has added many other platforms, that allow you to run OpenFaaS in more places. A good example of this is deploying OpenFaaS
on Hashicorp's [nomad](https://www.hashicorp.com/blog/functions-as-a-service-with-nomad) application scheduler.

### Why use AWS Fargate?
Your reasons for choosing AWS Fargate are likely to vary depending on your
experience, knowledge and goals. At [form3](https://form3.tech) we use AWS ECS to schedule Docker containers.
We decided to build an OpenFaaS provider to run on ECS so we could leverage all of our existing knowledge and infrastructure code.
Perhaps you too work in a team that uses AWS ECS? You may also work in a company that hasn't adopted Kubernetes and doesn't plan to in the immediate
future. So if you fit that in that camp, how do you leverage the advantage of serverless computing? A good choice would
be to look at a managed serverless platform like [AWS Lambda](https://aws.amazon.com/lambda/). In this article we examine
another option, running OpenFaaS on Fargate, which I believe gives you some of the benefits of a managed service like
Lambda with the flexibility of an open-source serverless platform like OpenFaaS.

## Architecture
OpenFaaS functions are built as Docker images and deployed as Docker containers. This approach may be very familiar to
developers using microservices. The platform is composed of `gateway`, `provider` and `monitoring` components. The
gateway delegates the deployment and invoking of functions to the `provider`. The provider in our case is `faas-fargate`,
which has been specifically designed to run and invoke functions using AWS Fargate containers.

The diagram below shows how each of these components interact:

![openfaas-fargate](/images/openfaas-on-fargate/openfaas-fargate-component-architecture.png)

Each of the components are created and deployed as Fargate containers.

### Architecture features:

* **\[networking\]** we restrict traffic between containers using [AWS security groups](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html)
* **\[networking\]** ingress traffic from the Internet is terminated in a `public subnet`. Container workloads are
scheduled in a `private subnet` that has no access to the Internet
* **\[discovery\]** all workloads use [Amazon Route 53 auto naming](https://docs.aws.amazon.com/Route53/latest/APIReference/overview-service-discovery.html)
to manage service registration / de-registration
* **\[logging\]** we configure each container workload to log to [AWS cloudwatch](https://aws.amazon.com/cloudwatch).
* **\[secrets\]** managed using [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) and assigned access to functions
in the `stack.yml`
* **\[tls\]** ingress TLS is automatically provisioned using [Certbot](https://certbot.eff.org/) and the
[Let's Encrypt](https://letsencrypt.org/) certificate authority.

## Run OpenFaaS on Fargate

The easiest way to run [OpenFaaS on Fargate](https://github.com/ewilde/faas-fargate) is to use the
[terraform module](https://github.com/ewilde/terraform-aws-openfaas-fargate) I developed to deploy all the necessary components:

 * [OpenFaaS gateway](https://github.com/openfaas/faas)
 * [FaaS-Fargate provider](https://github.com/ewilde/faas-fargate)
 * [Prometheus](https://github.com/prometheus/prometheus)
 * [Prometheus alert manager](https://github.com/prometheus/alertmanager)
 * [NATS messaging server](https://github.com/nats-io/gnatsd)

Simply run the following commands:

> Disclaimer: as you would expect creating resources in AWS will incur charges. Please follow the tear-down instructions
below when you have finished.

### Mac
```shell
$ brew install terraform # or upgrade
git clone https://github.com/ewilde/terraform-aws-openfaas-fargate
cd terraform-aws-openfaas-fargate

cat > ./terraform.tfvars <<EOF
acme_enabled           = "1"
acme_email_address     =<EMAIL_ADDRESS>alb_logs_bucket        = "my-logs"
aws_region             = "eu-west-1"
debug                  = "0"
developer_ip           = "<IP_ADDRESS>"
route53_zone_name      = "openfaas.my-domain.com"
self_signed_enabled    = "0"
EOF

terraform apply

```

### Linux
```shell
$ wget https://releases.hashicorp.com/terraform/0.11.7/terraform_0.11.7_linux_amd64.zip
unzip terraform_0.11.7_linux_amd64.zip
sudo mv terraform /usr/local/bin

git clone https://github.com/ewilde/terraform-aws-openfaas-fargate
cd terraform-aws-openfaas-fargate

cat > ./terraform.tfvars <<EOF
acme_enabled           = "1"
acme_email_address     =<EMAIL_ADDRESS>alb_logs_bucket        = "my-logs"
aws_region             = "eu-west-1"
debug                  = "0"
developer_ip           = "<IP_ADDRESS>"
route53_zone_name      = "openfaas.my-domain.com"
self_signed_enabled    = "0"
EOF

terraform apply
```

### Configuration options explained

| Name                | Description                                                                                |
|---------------------|----------------------------------------------------------------------------------------------------------------------------------|
| acme_enabled        | (Recommended)`1` to use the official [acme](https://www.terraform.io/docs/providers/acme/index.html) terraform provider to create TLS certificates. Defaults to `0`                       |
| acme_email_address  | (Recommended) Email address used to register TLS account, used in conjunction with `acme_enabled`                                  |
| aws_region          | (Required) The aws region to create the openfaas ecs cluster in                                                                  |
| alb_logs_bucket     | (Required) S3 bucket to store alb logs                                                                                |
| debug               | (Optional) `1` to create an ec2 bastion in the external subnet and a test instance in the internal subnet. Defaults to `0`       |
| developer_ip        | your IP address, used to whitelist incoming SSH to the bastion, debug is enabled                                                 |
| route53_zone_name   | (Recommended) a Route 53 zone to create DNS records for the OpenFaaS gateway, i.e. openfaas.example.com, requires `acme_enabled` |
| self_signed_enabled | (Not recommended) Use a self-signed TLS certificate for the OpenFaaS gateway if not using `acme_enabled`. Defaults to `0`        |

Once terraform has finished creating the resources you should see success message, which looks similar to:
```shell
Apply complete! Resources: 133 added, 0 changed, 0 destroyed.

Outputs:

alb_uri = openfaas-1918537172.eu-west-1.elb.amazonaws.com
bastion_ip = []
login = echo -n "t6UbsFKnjgtv4KLF3Uw5llN6fyONE6nV" | faas-cli login --gateway https://openfaas-1918537172.eu-west-1.elb.amazonaws.com --username=admin --password-stdin --tls-no-verify
login_secure = echo -n "t6UbsFKnjgtv4KLF3Uw5llN6fyONE6nV" | faas-cli login --gateway https://gateway.openfaas.12factor.io --username=admin --password-stdin
openfass_uri = https://gateway.openfaas.12factor.io/ui/
service_security_group = sg-0ff75545f2d542c4e
servicebox_ip = []
```

### Verifying the installation
When the gateway is running you can start deploying and running functions.
You can tell if it's ready by calling the `healthz` endpoint and waiting for a `200` http status code

```shell
$ curl https://openfaas.{your-domain}.com/healthz -i

HTTP/1.1 200 OK
Content-Length: 0
Date: Sat, 22 Dec 2018 10:39:17 GMT
Content-Type: text/plain; charset=utf-8
```

You can also see the services running in the ECS console:

```shell

$ aws ecs list-services  --cluster openfaas
{
    "serviceArns": [
        "arn:aws:ecs:eu-west-1:122668425727:service/gateway",
        "arn:aws:ecs:eu-west-1:122668425727:service/prometheus",
        "arn:aws:ecs:eu-west-1:122668425727:service/nats",
        "arn:aws:ecs:eu-west-1:122668425727:service/alertmanager"
    ]
}
```

## Deploying a function
We can deploy functions to AWS Fargate the same way we would with another other OpenFaaS provider, through the CLI, UI or REST API.

Let's configure the `faas-cli` to point at our OpenFaaS cluster:

```shell
export OPENFAAS_URL=https://openfaas.{your-domain}.com
```

1\. Lets create and deploy a function to our new stack using the CLI:

```shell
$ faas new hello-world --lang go -p ewilde

2018/12/22 10:29:03 No templates found in current directory.
2018/12/22 10:29:03 Attempting to expand templates from https://github.com/openfaas/templates.git
2018/12/22 10:29:05 Fetched 14 template(s) : [csharp dockerfile go go-armhf java8 node node-arm64 node-armhf php7 python python-armhf python3 python3-armhf ruby] from https://github.com/openfaas/templates.git
Folder: hello-world created.
  ___                   _____           ____
 / _ \ _ __   ___ _ __ |  ___|_ _  __ _/ ___|
| | | | '_ \ / _ \ '_ \| |_ / _` |/ _` \___ \
| |_| | |_) |  __/ | | |  _| (_| | (_| |___) |
 \___/| .__/ \___|_| |_|_|  \__,_|\__,_|____/
      |_|

Function created in folder: hello-world
Stack file written: hello-world.yml
```
In the command above `--prefix` corresponds to my username on the Docker Hub.
The function will be built into a Docker image and then pushed there through the `faas-cli up` command.
You can also use your own self-hosted registry.

2\. Open `./hello-world/handler.go` to see the function entry point

```golang
package function

import (
	"fmt"
)

// Handle a serverless request
func Handle(req []byte) string {
	return fmt.Sprintf("Hello, Go. You said: %s", string(req))
}
```

3\. Now let's build and deploy the function to our new environment
```shell
$ faas up -f hello-world.yml

... <- lots of lovely build output from Docker

Successfully built f9833391f176
Successfully tagged ewilde/hello-world:latest
Image: ewilde/hello-world:latest built.
[0] < Building hello-world done.
[0] worker done.

[0] > Pushing hello-world [ewilde/hello-world:latest].
The push refers to repository [docker.io/ewilde/hello-world]
d1307abdafe5: Mounted from ewilde/hello-paris
9808cfceb9f2: Mounted from ewilde/hello-paris
a0db5d04a9ae: Mounted from ewilde/hello-paris
39c32d89aeac: Mounted from ewilde/hello-paris
c198ae36274e: Mounted from ewilde/hello-paris
b01940cbde37: Mounted from ewilde/hello-paris
df64d3292fd6: Mounted from ewilde/env
latest: digest: sha256:e0dbd58d58880e0771c3ab36cdcbd7a371fa80d91894f9e845f5f54132124586 size: 1785
[0] < Pushing hello-world [ewilde/hello-world:latest] done.
[0] worker done.

Deploying: hello-world.

Deployed. 202 Accepted.
URL: https://openfaas.{your-domain}.com/function/hello-world
```

### Removing the installation
* Firstly, remove any functions that you have deployed using `faas-cli remove FUNCTION_NAME`
* Run `make destroy`. This can take between 5-10 minutes.  (ID: sg-0a84a6bd951bacb6d, 1m50s elapsed)
aws_security_group.alb: Destruction complete after 1m51s
aws_vpc.default: Destroying... (ID: vpc-0220284dd7ba01f58)
aws_vpc.default: Destruction complete after 0s

Destroy complete! Resources: 133 destroyed.
```

## Wrapping up

We've seen how the OpenFaaS provider architecture makes it easy to extend the platform and
run serverless functions on AWS Fargate. Then we deployed a complete OpenFaaS stack using terraform
on to AWS Fargate and secured the transport layer using the ACME provider and Let's Encrypt.

My code:

- [faas-fargate](https://github.com/ewilde/faas-fargate): OpenFaaS provider for AWS Fargate
- [Terraform installer for faas-fargate](https://github.com/ewilde/terraform-aws-openfaas-fargate): Installs the
OpenFaaS platform for AWS Fargate using Terraform

### What's next for faas-fargate

* Support _scale to zero_ using the [faas-idler](https://github.com/openfaas-incubator/faas-idler).
* Provide better _observability_ for users and integrate Grafana with the standard deployment to surface function metrics.

### Get connected

Get connected, ask questions, make comments and suggestions on:

* [openfaas/faas](https://github.com/openfaas/faas)
* [Slack](https://docs.openfaas.com/community)
* [Twitter](https://twitter.com/openfaas)

**New:** Join the [OpenFaaS #TeamServerless LinkedIn Group](https://www.linkedin.com/groups/13670843/).

gha_language: HTML

gha_license_id: MIT


text:
---
name: Support request
about: Ask for help
title: ''
labels: ''
assignees: ''

---

👋 Hello! If you have a question like "How do I do X with `transitions`" or "I have the following problem... Can `transitions` help me with that?", please consider [Stack Overflow](https://stackoverflow.com/questions/tagged/pytransitions) first.

Your question gains higher visibility since most developers look for help there.
The targeted community is larger; Some people will even help you to formulate a good question.
People get 'rewarded' with 'reputation' to help you. You also gain reputation in case this questions pops up more frequently. It's a win-win situation. Tag your question with `[pytransitions]` to make sure, that users of transitions will receive a notification. If the SO community cannot answer you question within a week, you can notify us by opening an issue here. Make sure to link your Stack Overflow post.  We'd rather answer questions there.

**Checklist**

- [ ] I checked the [README](https://github.com/pytransitions/transitions/blob/master/README.md) and the [issue tracker](https://github.com/pytransitions/transitions/issues) but did not find an answer.
- [ ] I posted my question on Stack Overflow [here](enter link here) but received no answer after a week.

repository: pytransitions/transitions

gha_language: Python

repo_name: pytransitions/transitions


text:
- Start Date: 2018-03-21
- RFC PR: (leave this empty)
- React Navigation Issue: (leave this empty)

# Summary

Support the horizontal side transition in Android settings.

I see we took from android core these transitions - https://github.com/react-navigation/react-navigation/blob/3c3668c95295eb34e52ccdc46824753924be1396/src/views/CardStack/TransitionConfigs.js#L55

* Standard Android navigation transition when opening an Activity - http://androidxref.com/7.1.1_r6/xref/frameworks/base/core/res/res/anim/activity_open_enter.xml

        transitionSpec: {
            duration: 350,
            easing: Easing.out(Easing.poly(5)), // decelerate
            timing: Animated.timing,
        },

* Standard Android navigation transition when closing an Activity - http://androidxref.com/7.1.1_r6/xref/frameworks/base/core/res/res/anim/activity_close_exit.xml

        transitionSpec: {
            duration: 230,
            easing: Easing.in(Easing.poly(4)), // accelerate
            timing: Animated.timing,
        },

However I cannot find the "Standard Android More Settings" transition config which we see in settings page as a horizontal translate. And previous screen gets a black dimmer on it.

### Here is a screen recording of it:

* Here is HD - https://gfycat.com/ShyFlusteredChanticleer
* Here is gif:

     ![](https://thumbs.gfycat.com/ShyFlusteredChanticleer-size_restricted.gif)

### Here it is slowed down by 4x:

* Here is HD - https://gfycat.com/SecondhandIcyIberianemeraldlizard
* Here is gif:

    ![](https://thumbs.gfycat.com/SecondhandIcyIberianemeraldlizard-size_restricted.gif)

We should support this please.

# Basic example

Please see screen recordings.

# Motivation

True to native, as the core animations are.

# Detailed design

Transition config. And options to support it.

# Drawbacks

Why should we *not* do this? Please consider:

- No reasons not to match Android.

There are tradeoffs to choosing any path. Attempt to identify them here.

# Alternatives

Continue using the vertical transition.

# Adoption strategy

Add to docs.

# How we teach this

Docs.

# Unresolved questions

repository: Noitidart/rfcs

repo_name: Noitidart/rfcs


text:
---
layout: post
title: "Architecture of My Project"
description: ""
category: tech
tags: [Python, NLP, Data Mining, Text Classification, Sentiment Analysis]
---
{% include JB/setup %}

Just want to take some high level notes about my project architecture. No tech details, no code.

# Service

## Client

PHP code, input is the raw social post extracted from our Chrome extensioin. It will send this data to the NLP server via socket and wait for the result.

## Server

Main thread is listening on **WORK_PORT** and waiting for the input data. It will create a new thread to handle the input request when received the new data.

For the processing part, there are two steps: preprocessing and classification.

### Preprocessing

I have already talked something about the preprocessing. Basically there are three steps:

*	Normalization
*	Tokenize
*	Lemmatization

The details can be found in the [previous blog](http://starcroce.github.io/tech/2014/10/07/text-sentiment-analysis/).

### Classification

Load the binay file of classifier and some other objects, read the preprocessed input, classify it.

Well, seems very simple, ah? Just like Howard Wolowitz said:

>how to fly an airplane: get in the airplane, know where you want to go and fly it.

Come on...

# Binary Object

Since I have told my manager that our online service don't need any third party library, I have to save all the objects depending on NLTK or sklearn as a binary file.

Basically what we need are the following objects:

*	Classifier
*	Lemmatization tokenizer
*	Target result (not sure if we must need that)
*	The current training result shows that removing stopwords may decrease the accuracy

# File Issue

When I am trying to load the training set in my local machine, it will always run into some problem. But it works fine if I run it on the server. The result may be the `.DS_Store` file created by Mac.

---

# Parameters (updates)

LinearSVM, SVM, Naive Bayes (sklearn, nltk), SGDClassifier,

max_df: 0.0 - 1.0

stopwords: none, english

max_feature: none, 5000, 10000, 50000

ngram: 1, 2, 3

sublinear_tf: true, false

tokenizer: stem, lemma, other

classifier parameters:

*	SVM: C
*	SGDClassifier: alpha, penalty, n_iter


text:
---
id: 26
title: 'Application Virtualization – Windows User Group'
date: 2010-02-25T10:33:20+02:00
author: Jan Marek
layout: post
guid: http://jmarek.wordpress.com/2010/02/25/application-virtualization-windows-user-group
permalink: /2010/02/25/application-virtualization-windows-user-group/
spaces_1d3f038117de6df561f7bf0516bb226c_permalink:
  - "http://cid-6e7b9216726d07b8.users.api.live.net/Users(7961117391414167480)/Blogs('6E7B9216726D07B8!242')/Entries('6E7B9216726D07B8!257')?authkey=EpZNAU0huAk%24"
  - "http://cid-6e7b9216726d07b8.users.api.live.net/Users(7961117391414167480)/Blogs('6E7B9216726D07B8!242')/Entries('6E7B9216726D07B8!257')?authkey=EpZNAU0huAk%24"
categories:
  - App-V
  - Nezařazené
tags:
  - App-V
---

  Our seminar about Application Virtualization was moved on March 18th 2010. For more information go to WUG. See you there!


text:
# `WETH9`

A wrapper to use ETH as collateral

## Functions:

- `receive() (external)`

- `deposit() (public)`

- `withdraw(uint256 _wad) (public)`

- `totalSupply() (public)`

- `approve(address _guy, uint256 _wad) (public)`

- `transfer(address _dst, uint256 _wad) (public)`

- `transferFrom(address _src, address _dst, uint256 _wad) (public)`

## Events:

- `Approval(address src, address guy, uint256 wad)`

- `Transfer(address src, address dst, uint256 wad)`

- `Deposit(address dst, uint256 wad)`

- `Withdrawal(address src, uint256 wad)`

### Function `receive() external`

fallback function that receives ETH

will get called in a tx with ETH

### Function `deposit() public`

wrap deposited ETH into WETH

### Function `withdraw(uint256 _wad) public`

withdraw ETH from contract

Unwrap from WETH to ETH

#### Parameters:

- `_wad`: amount WETH to unwrap and withdraw

### Function `totalSupply() → uint256 public`

get ETH total supply

#### Return Values:

- total supply

### Function `approve(address _guy, uint256 _wad) → bool public`

approve transfer

#### Parameters:

- `_guy`: address to approve

- `_wad`: amount of WETH

#### Return Values:

- True if tx succeeds, False if not

### Function `transfer(address _dst, uint256 _wad) → bool public`

transfer WETH

#### Parameters:

- `_dst`: destination address

- `_wad`: amount to transfer

#### Return Values:

- True if tx succeeds, False if not

### Function `transferFrom(address _src, address _dst, uint256 _wad) → bool public`

transfer from address

#### Parameters:

- `_src`: source address

- `_dst`: destination address

- `_wad`: amount to transfer

#### Return Values:

- True if tx succeeds, False if not

### Event `Approval(address src, address guy, uint256 wad)`

emits an event when a sender approves WETH

### Event `Transfer(address src, address dst, uint256 wad)`

emits an event when a sender transfers WETH

### Event `Deposit(address dst, uint256 wad)`

emits an event when a sender deposits ETH into this contract

### Event `Withdrawal(address src, uint256 wad)`

emits an event when a sender withdraws ETH from this contract

license: Unlicense

gha_license_id: Unlicense


text:
# Npm-run-timer

This tool is a convenience wrapper for timing your npm scripts. From the command-line you can can call anything you would normally call with npm with npm-run-timer. When the script is finished, the runtime will be logged at the bottom of the console.

## Examples:

```
npm-run-timer run translations
```

```
npm-run-timer test
```

## Output:

*npm runtime: 1.67 minutes*

repository: manda-linda/npm-run-timer

repo_name: manda-linda/npm-run-timer


text:
---
layout: default
title: Doom Binaries
nav_order: 2
---

# Included executables
{: .no_toc }

Doom Emacs comes with a set of binaries to aid us in it's installation process
as well as maintaining our installation.
{: .fs-6 .fw-300 }

## Table of contents
{: .no_toc .text-delta }

1. TOC
{:toc}

---

## Doom

Develop
{: .label .label-purple}

This is the default doom binary.

A command line interface for managing Doom Emacs; including:

* Package management

* Diagnostics

* Unit Tests

* byte-compilation

This tool also makes it trivial to launch Emacs out of a different folder or
with a different private module.

* **Available commands**
  * `doom install`
  * `doom help update`
  * `doom compile :core lang/php lang/python`
  * `doom run`
  * `doom run -nw file.txt file2.el`
  * `doom run -p ~/.other.doom.d -e ~/.other.emacs.d .nw file.txt`
* **Format commands**
  * `-h` / `--h`  Help Command
  * `-d` / `--debug`  Turn on doom-debug-mode
  * `-e` / `--emacsd`   Use the emacs config at DIR
  * `-i` / `--insecure`  Disable TLS/SSL validation (**Not recommended**)
  * `-p` / `--private`   Use the private module at DIR
  * `-y` / `--yes`  Auto-accept all confirmation prompts

---

## doom-doctor

Develop
{: .label .label-purple}

The Doom Doctor is essentially one big, self-contained elisp shell script that
uses a series of simple heuristics to diagnose common issues on your system.

Issues that could interfere with Doom Emacs.

Any Doom Module may optionally have a `doctor.el** file to run their own
heuristics in. Doctor scripts may run in versions of emacs 23, so you are
limited to very basic standard library calls.

**Usage:**
* `doom doctor`

---
## doom.cmd

Windows
{: .label .label-blue}

This `.cmd` script just adds the ability to pass additional args to `doom run`

---

## org-capture

Develop
{: .label .label-purple**

This opens and org-capture popup frame from the shell and a temporary emacs
daemon if emacs isn't already running.

**Usage:**
* `org-capture [key] [message...]`

---

## org-tangle

Develop
{: .label .label-purple}

This script tangles the source blocks from org files.

Debug/info messages are directed to stderr and can be ignored

* **Available Commands**
  * `-l` / `--lang` Only include blocks in the specified language
  * `-a` / `--all` Tangle all blocks by default
  * `-t` / `--tag` Only include blocks in trees that have these tags. Combine
    multiple --and and --or's ot just use --tag
  * `-p` / `--print` Prints tangled code to stdout instead of to files

repository: VentGrey/doom-emacs-docs

gha_language: SCSS

repo_name: VentGrey/doom-emacs-docs


text:
---
title: Textarea
description: Textareas allow users to enter multiple lines of text.
header: true
---

import { Tab, TabSet, Formik as FormComponents } from '@royalnavy/react-component-library'
import { Field, Formik, Form } from 'formik'
import DataTable from '../../../../components/presenters/data-table'
import CodeHighlighter from '../../../../components/presenters/code-highlighter'
import SketchWidget from '../../../../components/presenters/sketch-widget'
import TextareaComponent from '../../../images/components/forms/textarea/Component'
import TextareaAnatomy from '../../../images/components/forms/textarea/Anatomy'
import TextareaStates from '../../../images/components/forms/textarea/States'
import TextareaVariations from '../../../images/components/forms/textarea/Variations'

# Textarea
The textarea component lets users enter and edit multiple lines of text.

<TextareaComponent />

## Usage
The Textarea component should be used to let users enter multiple lines of text. It typically appears in Forms and Modals, however can be used wherever the requirement for multiple lines of text exists. If you require the user to enter a single line of text, use the [Text Input component](/components/form/input) instead.

<TabSet>

<Tab title="Design">

<SketchWidget name="Textarea" href="/design-system.sketch" />

The textarea should contain a concise message, communicating to the user the expected content. To ensure there is appropriate readability of the entered content, try to make the Textarea container stretch to the full width of its parent.

### Anatomy

<TextareaAnatomy />

1. **Label**. The Label should be used to describe to the user what the desired input should be. Every textarea should have a text label.
2. **User Input**. The User Input is the text the user has entered into the Textarea.
3. **Container**. The Container wraps the entire component.

### States

<TextareaStates />

The Textarea has 3 states - default, active, and filled.

### Variations

<TextareaVariations />

The textarea comes in _two_ variations - fixed and resizable. The fixed version of the Textarea cannot be resized by the user, whereas the resizable one can. **Note:** Whilst the resizable Textarea can be resized by the user, it can only be changed on the `y-axis`. This is to prevent the interface breaking when the textarea is stretched outside of its parent container.

</Tab>

<Tab title="Develop">
The `TextArea` component can be used to capture multiline text a form. Like other form components, this component can be used
either on it's own with values and onChange handlers passed to it, or with Formik by using the variation of the component enhanced to with it.

### Example with Formik
<CodeHighlighter source={`<Formik
  initialValues={initialValues}
  onSubmit={onSubmit}
  validationSchema={validationSchema}
>
<Form>
   <Field
      name="description"
      component={FormComponents.TextArea}
      label="Description"
    />
</Form>
</Formik>`} language="javascript">
  <Formik initialValues={{description: ''}} onBlur={() => {}} onChange={(data) => {console.log}}>
  <Form>
     <Field
        name="description"
        component={FormComponents.TextArea}
        label="Description"
      />
  </Form>
  </Formik>
</CodeHighlighter>

### Properties
The `TextArea` component simply displays a field with the specified value. In order ot allow the user to make changes to
the field content a 'onChange' property must accept the new field value and update the state for the form it belongs to and
cause a re-render to take place with the updated value passed back to the field to display.

<DataTable caption="TextArea" data={[
  {
    Name: 'autoFocus',
    Type: 'boolean',
    Required: 'False',
    Default: '',
    Description: 'Mark the field with the autofocus property causing the browser to focus on the field when the page loads.',
  },
  {
    Name: 'className',
    Type: 'string',
    Required: 'False',
    Default: '',
    Description: 'Optional additional css class to associate with the component wrapper',
  },
  {
    Name: 'isDisabled',
    Type: 'boolean',
    Required: 'False',
    Default: 'false',
    Description: 'Mark the field as disabled/inactive',
  },
  {
    Name: 'footnote',
    Type: 'string',
    Required: 'False',
    Default: '',
    Description: 'A message to display below the field'
  },
  {
    Name: 'id',
    Type: 'string',
    Required: 'False',
    Default: 'unique id',
    Description: 'Provide the ID for a field and tie it to its label. If one is not provided then a unique id will be created',
  },
  {
    Name: 'label',
    Type: 'string',
    Required: 'False',
    Default: '',
    Description: 'Ideally a field should include a label to help the user understand what the field is for and help screen readers',
  },
  {
    Name: 'name',
    Type: 'string',
    Required: 'False',
    Default: '',
    Description: 'The field name',
  },
  {
    Name: 'onBlur',
    Type: 'React.FormEvent<Element>',
    Required: 'True',
    Default: '',
    Description: 'Called when the field loses focus',
  },
  {
    Name: 'onChange',
    Type: 'React.ChangeEvent <HTMLTextAreaElement>',
    Required: 'True',
    Default: '',
    Description: 'Called when the field value changes',
  },
  {
    Name: 'placeholder',
    Type: 'string',
    Required: 'False',
    Default: '',
    Description: 'If a label is not provided then a placeholder should be.',
  },
  {
    Name: 'value',
    Type: 'string',
    Required: 'False',
    Default: '',
    Description: 'The field current value',
  },
]} />
</Tab>
</TabSet>

gha_language: TypeScript


text:
##### Closure delegation strategies

Ref : [link](#https://stackoverflow.com/questions/47994435/groovy-closure-delegate-only-and-delegate-first-strategy-not-working)

```groovy
groovy -e 'def x=12; def y=10; def data = [ x: 10, y: 20 ]; def cl ={x,y=16-> y=x+y}; cl.delegate=new A(); cl.resolveStrategy = Closure.DELEGATE_ONLY; println cl.call(1); class A { def x = 1; def y = 2}'
```


text:
# TestyTs
[![Build Status](https://travis-ci.org/Testy/TestyTs.svg?branch=master)](https://travis-ci.org/Testy/TestyTs)

TestyTs is a modern TypeScript testing framework.

## Why?
Writing tests should be fun. The other testing framework solutions do not make use of the full power of TypeScript. This one uses decorators and OOP and stuff. Therefore, it makes writing tests fun.

## Installation

```
$ npm install --save-dev testyts
$ npm install -g testyts
```

## Setup

To generate a testy.json configuration file, use the following cmmand:

```
$ testyts init
```

## Write some tests

### The basics
Writing tests with Testy is simple. Don't forget to export your test suites though. Otherwise, they won't be discovered by the test runner.

```ts
@testSuite('Sum Test Suite')
export class MyTestSuite {

    @test('One plus one, should equal two')
    onePlusOne() {
        // Act
        const result = 1 + 1;

        // Assert
        expect.toBeEqual(result, 2);
    }
}
```

### Setup and teardown

Testy provides setup and teardown hooks.

```ts
@testSuite('Sum Test Suite')
export class MyTestSuite {

    @beforeAll()
    beforeAll() {
        // This is executed before all the tests
    }

    @beforeEach()
    beforeEach() {
        // This is executed before each test
    }

    @afterEach()
    afterEach() {
        // This is executed after each test
    }

    @afterAll()
    afterAll() {
        // This is executed after all the tests
    }
}
```

### Reuse code!

This is where stuff gets interesting. Testy allows you to use base test classes. The base test can have setup and teardown methods. Your child test suite may also have setup and teardown methods. In that case, the base test methods are executed first.

```ts
class MyBaseTestSuite{
    // Setup/teardown extravaganza
}

@testSuite('My Test Suite')
class MyTestSuite extends MyBaseTestSuite {
    // My tests
}
```

### Test cases

```ts
@testSuite('Sum Test Suite')
export class MyTestSuite {
    @test('Addition', [
          new TestCase('Two plus two is four', 2, 2, 4),
          new TestCase(`Minus one that's three`, 4, -1, 3)
    ])
    onePlusOne(a: number, b: number, result: number) {
        expect.toBeEqual(a + b, result);
    }
}
```

### Asserting

There's a whole bunch of assertion methods and also a dash of syntactic sugar sexyness in the expect class.

```ts
expect.toBeTrue(2 > 1);
expect.toBeEqual('a', 'a');
expect.not.toBeEqual('p', 'np');
expect.toThrow(() => someNastyMethod());
expect.toBeSorted.inAscendingOrder([0, 1, 1, 2, 3, 5, 8]);
// More!
```

### Ignoring or focusing some tests

You can ignore tests by adding an `x` before a test suite or a specific test decorator. Ignored tests will still show up in the test report, but they will be marked as ignored.

```ts
@xtestSuite('Sum Test Suite') // This test suite will be ignored
export class MyTestSuite {
// Your tests
}

@testSuite('Sum Test Suite')
export class MyTestSuite {
    @xtest('One plus one, should equal two') // This test will be ignored
    onePlusOne() {
       // Some test
    }
}
```

You can also focus tests by adding an `f` before a test suite or a specific test decorator. If one test or test suites are focused, only those will be runned. The others will be reported as ignored.

```ts
@ftestSuite('Sum Test Suite') // This test suite will be focused.
export class MyTestSuite {
...
}

@testSuite('Sum Test Suite')
export class MyTestSuite {
    @ftest('One plus one, should equal two') // This test will be focused
    onePlusOne() {
       // Your test
    }
}
```

## Run the tests

To run the tests, use the following command

```
$ testyts
$ testyts --config custom/config/file.json // To specify a custom configuration file
```

## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

## License
[ISC](./LICENSE)

license: ISC

repository: bryanmenard/TestyTs

gha_license_id: ISC

repo_name: bryanmenard/TestyTs


text:
# Slot: has biomarker

holds between a disease or phenotypic feature and a measurable molecular entity that is used as an indicator of the presence or state of the disease or feature.

URI: [biolink:has_biomarker](https://w3id.org/biolink/vocab/has_biomarker)

## Domain and Range

[DiseaseOrPhenotypicFeature](DiseaseOrPhenotypicFeature.md) →  0..\* [MolecularEntity](MolecularEntity.md)

## Parents

 *  is_a: [correlated with](correlated_with.md)

## Children

## Used by

## Other properties

|  |  |  |
| --- | --- | --- |
| **In Subsets:** | | translator_minimal |
| **Narrow Mappings:** | | NCIT:disease_has_finding |
|  | | NCIT:disease_has_molecular_abnormality |
|  | | NCIT:disease_is_marked_by_gene |

repository: linkml/linkml

branch_name: refs/heads/main

repo_name: linkml/linkml


text:
# Android Bootcamp Pre-work - *Balanced*

**Balanced** is a basic Android Todo list with Dwight Eisenhower’s urgency-importance decision matrix to help you with your ToDos decision making.

Submitted by: **Ernest Semerda**
Portfolio: http://www.ernestsemerda.com

## User Stories

The following **required** functionality is completed:

* [x] User can **successfully add and remove items** from the todo list
* [x] User can **tap a todo item in the list and bring up an edit screen for the todo item** and then have any changes to the text reflected in the todo list.
* [x] User can **persist todo items** and retrieve them properly on app restart

The following **optional** features are implemented:

* [x] Persist the todo items [into SQLite](http://guides.codepath.com/android/Persisting-Data-to-the-Device#sqlite) instead of a text file
* [x] Add support for completion due dates for todo items
* [x] Use a [DialogFragment](http://guides.codepath.com/android/Using-DialogFragment) to Delete Item
* [x] Added Dwight Eisenhower’s urgency-importance decision matrix focusing on the classification of items as Important and/or Urgent. This is a better version of priority ranking. The outcome of this classification is then visible through "advise" (next steps) and color codes in the main listview. More on this type of classification can be read on my blog here: http://www.gsdfaster.com/blog/how-to/dwight-eisenhowers-urgency-importance-decision-matrix/
* [x] Tweak the style improving the UI / UX, play with colors, images or backgrounds

## Android Bootcamp Prework assignment

Video Walkthrough:

<img src='https://raw.githubusercontent.com/semerda/balanced-todo-list/master/screenshots/ezgif-780332820.gif' title='Video Walkthrough' width='' alt='Video Walkthrough' />

Screenshots of the implemented prework:

![alt tag](https://raw.githubusercontent.com/semerda/balanced-todo-list/master/screenshots/Screen%20Shot%202016-06-27%20at%2012.45.28%20AM.png) ![alt tag](https://raw.githubusercontent.com/semerda/balanced-todo-list/master/screenshots/Screen%20Shot%202016-06-27%20at%2012.45.41%20AM.png) ![alt tag](https://raw.githubusercontent.com/semerda/balanced-todo-list/master/screenshots/Screen%20Shot%202016-06-27%20at%2012.45.44%20AM.png)

## Notes

This was fun! I am still a fan boy of iOS/Xcode development but maybe in due time I will cross to the Android side ;-)

## License

    Copyright 2016 esemerda

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

repository: semerda/balanced-todo-list

repo_name: semerda/balanced-todo-list


text:
# hibernate-postgresql-patch
Provides a custom extended PostgreSQL dialect for Hibernate 4.x

Currently it constists only of a fix for mapping the native `java.util.UUID` to the `pg-uuid` type without adding
JPA's `@Type` annotation at entity field level. This will be fixed as soon as Hibernate 5.x is released (and can
be used in your project). For further information also see [HH-9562](https://hibernate.atlassian.net/browse/HHH-9562).

[![Build Status](https://api.travis-ci.org/CPGFinanceSystems/hibernate-postgresql-patch.svg?branch=master)]
(https://travis-ci.org/CPGFinanceSystems/hibernate-postgresql-patch)

## Usage

Use `de.cpg.oss.hibernate.CustomPostgreSQL9Dialect` instead of standard `org.hibernate.dialect.PostgreSQL9Dialect`
in your application's hibernate configuration an you're done.

## Download

Binaries will be available on maven central with following GAV:

- groupId: `de.cpg.oss`
- artifactId: `hibernate-postgresql-patch`
- version: `1.0.0`


text:
# PikesPeak
[Link to the challenge](https://ctflearn.com/challenge/935)

Data is hidden in the image.

## Step 1
We are given a jpg file.

I downloaded it and viewed it. Nothing interesting.

Then I used some basic commands (`file` and `strings`).

The output of `strings PikesPeak.jpg | grep CTFlearn` gave me the flag.

Note:
I could have used `grep -i ctf` and get the flag. Even if there's a lot of fake flags, the only one respecting the format is `CTFlearn{Gandalf}`

## Solution
The flag is `CTFlearn{Gandalf}`

repository: MathisEngels/CTFlearn-Writeups

repo_name: MathisEngels/CTFlearn-Writeups


text:
---
title: "Adding a new REST endpoint to elasticsearch"
#description:
toc: true
authors:
  - David Pilato
tags:
  - java
  - elasticsearch
  - plugin
categories:
  - tutorial
series:
  - plugin for elasticsearch v5
date: 2016-07-30 14:50:00 +0200
lastmod: 2016-10-19 14:50:00 +0200
# featuredImage: assets/images/covers/new/logstash.png
draft: false
aliases:
  - /blog/2016/07/30/adding-a-new-rest-endpoint-to-elasticsearch/
  - /blog/2016/10/19/adding-a-new-rest-endpoint-to-elasticsearch-updated-for-ga/
---

This blog post is part of a series which will teach you:

* [How to write a plugin for elasticsearch 5.0 using Maven]({{< ref "2016-07-27-creating-a-plugin-for-elasticsearch-5-dot-0-using-maven" >}}).
* How to add a new REST endpoint plugin to elasticsearch 5.0 (what you are reading now).
* How I wrote the `ingest-bano` plugin which will be hopefully released soonish. In this plugin, new REST endpoints have been added.

Imagine that you wish to add a new REST endpoint so you can send requests like:

```sh
curl -XGET "http://localhost:9200/_hello?name=David&pretty"

# Or

curl -XGET "http://localhost:9200/_hello/David&pretty"

# Or

curl -XGET "http://localhost:9200/_hello?pretty" -d '{
    "name": "David"
}'

# Or

curl -XPOST "http://localhost:9200/_hello?pretty" -d '{
    "name": "David"
}'
```

And you want to get back something like:

```json
{
    "message": "Hello David!"
}
```

Without any parameter:

```sh
curl -XGET "http://localhost:9200/_hello?pretty"
```

It should return:

```json
{
    "message": "Hello World!"
}
```

Or get back a list of existing indices and the number of documents for a given type of indices with:

```sh
curl -XGET http://localhost:9200/_bano
```

Let's see how to implement that!

<!-- more -->

With what we saw [in the previous article]({{< ref "2016-07-27-creating-a-plugin-for-elasticsearch-5-dot-0-using-maven" >}}), we now have a Plugin skeleton ready to host our REST endpoint code.
We also have seen [how to create real integration tests]({{< ref "2016-07-29-elasticsearch-real-integration-tests" >}}).

We are now all set to implement the REST endpoint and be able to test it with a REST Client.

## Rest Handler

### Rest Handler skeleton

Basically, we will extend the `BaseRestHandler` class. Let's create a `HelloRestAction` in `src/main/java/org/elasticsearch/ingest/bano/`:

```java
public class HelloRestAction extends BaseRestHandler {

    @Inject
    public HelloRestAction(Settings settings, RestController controller) {
        super(settings);
        // Register your handlers here
    }

    @Override
    protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException {
        // Implement the REST logic here
    }
}
```

### Register endpoints

In the constructor, we can define when this class will be called:

```java
@Inject
public HelloRestAction(Settings settings, RestController controller) {
    super(settings);
    controller.registerHandler(GET, "/_hello", this);
}
```

Here we are expecting a `GET` request on `/_hello` endpoint.

### Register the REST handler

We need to define the REST handler in the plugin:

```java
@Override
public List<Class<? extends RestHandler>> getRestHandlers() {
    return Collections.singletonList(HelloRestAction.class);
}
```

### Test the endpoint

We have to add some "hacks" to the default integration tests. Let's create a `BanoRestIT` in
`src/test/java/org/elasticsearch/ingest/bano/`. Note that it extends `AbstractITCase`, which we have
have seen [previously]({{< ref "2016-07-29-elasticsearch-real-integration-tests" >}}):

```java
public class BanoRestIT extends AbstractITCase {
}
```

Let's now implement our first test:

```java
public void testHelloWorld() throws Exception {
    Response response = client.performRequest("GET", "/_hello");
    assertThat(entityAsMap(response), hasEntry("message", "Hello World!"));
}
```

### Implement handleRequest

As we did not implemented the REST logic yet, this test will obviously fail. Let's fix that in `HelloRestAction`.

First, we will send back a JSON object to the user. Elasticsearch provides `XContent` classes to deal
with this.
We can create a class which will represent our response:

```java
class Message implements ToXContent {

    private final String name;

    public Message(String name) {
        if (name == null) {
            this.name = "World";
        } else {
            this.name = name;
        }
    }

    @Override
    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
        return builder.field("message", "Hello " + name + "!");
    }
}
```

This class implements `ToXContent` so it provides a `toXContent` method where we build the actual JSON response.

Then, we implement `prepareRequest` method:

```java
@Override
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException {
    String name = restRequest.param("name");
    return channel -> {
        Message message = new Message(name);
        XContentBuilder builder = channel.newBuilder();
        builder.startObject();
        message.toXContent(builder, restRequest);
        builder.endObject();
        channel.sendResponse(new BytesRestResponse(RestStatus.OK, builder));
    };
}
```

This code is usig a lambda which builds a new `Message` object.
Then we create our JSON document. Basically `builder.startObject()` and `builder.endObject()` create a JSON object `{}`. `message.toXContent(builder, restRequest)` will fill this object with a JSON representation of the `Message` object: `"message": "Hello name!"`.
At the end, this code will produce:

```json
{
    "message": "Hello name!"
}
```

Then we send the JSON response over the wire.

## Dealing with parameters

### Query Parameters

We want to support:

```sh
curl -XGET "http://localhost:9200/_hello?name=David&pretty"
```

Let's first implement a test for it (yeah! I love test driven development):

```java
public void testHelloDaviddWithQueryParameters() throws Exception {
    Response response = client.performRequest("GET", "/_hello?name=David");
    assertThat(entityAsMap(response), hasEntry("message", "Hello David!"));
}
```

And fix the test in `handleRequest` method...

```java
protected void handleRequest(RestRequest request, RestChannel channel, NodeClient client) throws Exception {
    RestToXContentListener<ToXContent> listener = new RestToXContentListener<>(channel);
    String name = request.param("name");
    listener.onResponse(new Message(name));
}
```

### Parameters in URL

We want to support:

```sh
curl -XGET "http://localhost:9200/_hello/David&pretty"
```

Let's again implement a test for it:

```java
public void testHelloDavidWithURLParameters() throws Exception {
    Response response = client.performRequest("GET", "/_hello/David");
    assertThat(entityAsMap(response), hasEntry("message", "Hello David!"));
}
```

It will send back an error `400 (Bad Request)` as this URL pattern does not exist.
Let's add it in the `HelloRestAction` constructor by registering now:

```java
controller.registerHandler(GET, "/_hello/{name}", this);
```

`name` will be the placeholder for this parameter. Well. That's cool. We don't need to change the implementation!

### Parameters as JSON documents

We want to support:

```sh
curl -XGET "http://localhost:9200/_hello?pretty" -d '{
    "name": "David"
}'

# Or

curl -XPOST "http://localhost:9200/_hello?pretty" -d '{
    "name": "David"
}'
```

That's a good practice to support both as some clients don't support `GET` with body.

```java
public void testHelloDavidWithGetBody() throws Exception {
    Response response = client.performRequest("GET", "/_hello",
            Collections.emptyMap(), new StringEntity("{\"name\":\"David\"}"));
    assertThat(entityAsMap(response), hasEntry("message", "Hello David!"));
}

public void testHelloDavidWithPostBody() throws Exception {
    Response response = client.performRequest("POST", "/_hello",
            Collections.emptyMap(), new StringEntity("{\"name\":\"David\"}"));
    assertThat(entityAsMap(response), hasEntry("message", "Hello David!"));
}
```

We need in `prepareRequest` to extract the name from the body:

```java
@Override
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException {
    String name = restRequest.param("name");
    if (name == null && restRequest.content().length() > 0) {
        // Let's try to find the name from the body
        Map<String, Object> map = XContentHelper.convertToMap(restRequest.content(), false).v2();
        if (map.containsKey("name")) {
            name = (String) map.get("name");
        }
    }

    String finalName = name;
    return channel -> {
        Message message = new Message(finalName);
        XContentBuilder builder = channel.newBuilder();
        builder.startObject();
        message.toXContent(builder, restRequest);
        builder.endObject();
        channel.sendResponse(new BytesRestResponse(RestStatus.OK, builder));
    };
}
```

And we also need to register the `POST` request. Let's add it in the `HelloRestAction` constructor by
registering now:

```java
controller.registerHandler(POST, "/_hello", this);
```

Et voilà!

## Calling elasticsearch client

You can also call elasticsearch client to perform some tasks and then send the result back to the caller.

Here for example, we want to call:

```sh
curl -XGET http://localhost:9200/_bano
```

And get back an array containing the list of all indices starting with `.bano` in the cluster:

```json
{
    "bano": [
        ".bano-17",
        ".bano-95",
        ".bano-29"
    ]
}
```

### Add a test

As usual, we start adding a test:

```java
public void testBano() throws Exception {
    // We first create some indices
    int numIndices = randomIntBetween(1, 10);
    for (int i = 0; i < numIndices; i++) {
        client.performRequest("PUT", "/.bano-" + i);
    }
    // We create some other indices
    int numOtherIndices = randomIntBetween(1, 10);
    for (int i = 0; i < numOtherIndices; i++) {
        client.performRequest("PUT", "/" + randomAsciiOfLengthBetween(6, 10).toLowerCase(Locale.getDefault()));
    }

    client.performRequest("GET", "/_cluster/health", Collections.singletonMap("wait_for_status", "yellow"));

    Response response = client.performRequest("GET", "/_bano");
    Map<String, Object> responseMap = entityAsMap(response);
    assertThat(responseMap, hasKey("bano"));
    List<String> bano = (List<String>) responseMap.get("bano");
    for (int i = 0; i < numIndices; i++) {
        assertThat(bano, hasItem(".bano-" + i));
    }
}
```

The test generates a random number of indices starting with `.bano` plus some other unrelated indices.

Let's now create a new `BanoRestAction` as we did for `HelloRestAction`:

```java
public class BanoRestAction extends BaseRestHandler {

    @Inject
    public BanoRestAction(Settings settings, RestController controller) {
        super(settings);
        controller.registerHandler(GET, "/_bano", this);
    }

    @Override
    protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException {
    }
}
```

We register it in the plugin:

```java
public List<Class<? extends RestHandler>> getRestHandlers() {
return Arrays.asList(
        HelloRestAction.class,
        BanoRestAction.class);
}
```

Let's implement the logic in `handleRequest`:

```java
@Override
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException {
    return channel -> client.admin().indices().prepareGetIndex()
        .setIndices(".bano*")
        .execute(new RestBuilderListener<GetIndexResponse>(channel) {
            @Override
            public RestResponse buildResponse(GetIndexResponse getIndexResponse, XContentBuilder builder) throws Exception {
                Indices indices = new Indices();
                for (String index : getIndexResponse.getIndices()) {
                    indices.addIndex(index);
                }
                builder.startObject();
                indices.toXContent(builder, restRequest);
                builder.endObject();
                return new BytesRestResponse(RestStatus.OK, builder);
            }
        });
}
```

As you can see, we don't block the thread here as we are using a Listener which is called once the request in the cluster is over.
This is **extremly important** in the context of elasticsearch as it frees the network socket which can hold other requests and is not blocked by the current one.

If everything goes well, `buildResponse` method will be called. Otherwise any exception will be thrown and elasticsearch REST layer mechanism will send that back to the caller.

`Indices` is a new class as we have seen before which will help us to serialize to JSON the response:

```java
class Indices implements ToXContent {

    private final List<String> indices;

    public Indices() {
        indices = new ArrayList<>();
    }

    public void addIndex(String index) {
        indices.add(index);
    }

    @Override
    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
        builder.startArray("bano");
        for (String index : indices) {
            builder.value(index);
        }
        return builder.endArray();
    }
}
```

## What's next?

In a coming blog post, I'll explain how to create an ingest plugin which will helps you to transform a french postal address to geo coordinates or the other way around. We will use what we have just seen to add some administrative tasks like automatically create our datasources in elasticsearch (download CSV files from bano website, extract, transform to JSON and index in elasticsearch).

Stay tuned!


text:
---
layout: post
title: Largest Contentful Paint (LCP)
authors:
  - philipwalton
date: 2019-08-08
updated: 2020-06-17
description: |
  This post introduces the Largest Contentful Paint (LCP) metric and explains
  how to measure it
tags:
  - performance
  - metrics
---

{% Aside %}
  Largest Contentful Paint (LCP) is an important, user-centric metric for
  measuring [perceived load
  speed](/user-centric-performance-metrics/#types-of-metrics) because it marks
  the point in the page load timeline when the page's main content has likely
  loaded—a fast LCP helps reassure the user that the page is
  [useful](/user-centric-performance-metrics/#questions).
{% endAside %}

Historically, it's been a challenge for web developers to measure how quickly
the main content of a web page loads and is visible to users.

Older metrics like
[load](https://developer.mozilla.org/en-US/docs/Web/Events/load) or
[DOMContentLoaded](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded)
are not good because they don't necessarily correspond to what the user sees on
their screen. And newer, user-centric performance metrics like [First Contentful
Paint (FCP)](/fcp/) only capture the very beginning of the loading experience.
If a page shows a splash screen or displays a loading indicator, this moment is
not very relevant to the user.

In the past we've recommended performance metrics like [First Meaningful Paint
(FMP)](/first-meaningful-paint/) and [Speed Index (SI)](/speed-index/) (both
available in Lighthouse) to help capture more of the loading experience after
the initial paint, but these metrics are complex, hard to explain, and often
wrong—meaning they still do not identify when the main content of the page
has loaded.

Sometimes simpler is better. Based on discussions in the [W3C Web
Performance Working Group](https://www.w3.org/webperf/) and research done at
Google, we've found that a more accurate way to measure when the main content
of a page is loaded is to look at when the largest element was rendered.

## What is LCP?

The Largest Contentful Paint (LCP) metric reports the render time of the largest
[image or text block](#what-elements-are-considered) visible within the
viewport, relative to when the page [first started
loading](https://w3c.github.io/hr-time/#timeorigin-attribute).

<picture>
  <source srcset="{{ "image/tcFciHGuF3MxnTr1y5ue01OGLBn2/elqsdYqQEefWJbUM2qMO.svg" | imgix }}" media="(min-width: 640px)" width="400", height="100">
  {% Img src="image/eqprBhZUGfb8WYnumQ9ljAxRrA72/8ZW8LQsagLih1ZZoOmMR.svg", alt="Good LCP values are 2.5 seconds, poor values are greater than 4.0 seconds and anything in between needs improvement", width="400", height="300", class="w-screenshot w-screenshot--filled width-full" %}
</picture>

### What is a good LCP score?

To provide a good user experience, sites should strive to have Largest
Contentful Paint of **2.5 seconds** or less. To ensure you're hitting this
target for most of your users, a good threshold to measure is the **75th
percentile** of page loads, segmented across mobile and desktop devices.

{% Aside %}
  To learn more about the research and methodology behind this recommendation,
  see: [Defining the Core Web Vitals metrics
  thresholds](/defining-core-web-vitals-thresholds/)
{% endAside %}

### What elements are considered?

As currently specified in the [Largest Contentful Paint
API](https://wicg.github.io/largest-contentful-paint/), the types of elements
considered for Largest Contentful Paint are:

* `<img>` elements
* `<image>` elements inside an `<svg>` element
* `<video>` elements (the poster image is used)
* An element with a background image loaded via the
  [`url()`](https://developer.mozilla.org/en-US/docs/Web/CSS/url()) function
  (as opposed to a
  [CSS gradient](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Images/Using_CSS_gradients))
* [Block-level](https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements)
  elements containing text nodes or other inline-level text elements children.

Note, restricting the elements to this limited set was intentional in order to
keep things simple in the beginning. Additional elements (e.g. `<svg>`,
`<video>`) may be added in the future as more research is conducted.

### How is an element's size determined?

The size of the element reported for Largest Contentful Paint is typically the
size that's visible to the user within the viewport. If the element extends
outside of the viewport, or if any of the element is clipped or has non-visible
[overflow](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow), those
portions do not count toward the element's size.

For image elements that have been resized from their [intrinsic
size](https://developer.mozilla.org/en-US/docs/Glossary/Intrinsic_Size), the
size that gets reported is either the visible size or the intrinsic size,
whichever is smaller. For example, images that are shrunk down to a much
smaller than their intrinsic size will only report the size they're displayed
at, whereas images that are stretched or expanded to a larger size will only
report their intrinsic sizes.

For text elements, only the size of their text nodes is considered (the smallest
rectangle that encompasses all text nodes).

For all elements, any margin, padding, or border applied via CSS is not
considered.

{% Aside %}
  Determining which text nodes belong to which elements can sometimes
  be tricky, especially for elements whose children includes inline elements and
  plain text nodes but also block-level elements. The key point is that every
  text node belongs to (and only to) its closest block-level ancestor element.
  In [spec
  terms](https://wicg.github.io/element-timing/#set-of-owned-text-nodes):
  each text node belongs to the element that generates its [containing
  block](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block).
{% endAside %}

### When is largest contentful paint reported?

Web pages often load in stages, and as a result, it's possible that the largest
element on the page might change.

To handle this potential for change, the browser dispatches a
[`PerformanceEntry`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry)
of type `largest-contentful-paint` identifying the largest contentful element
as soon as the browser has painted the first frame. But then, after rendering
subsequent frames, it will dispatch another
[`PerformanceEntry`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry)
any time the largest contentful element changes.

For example, on a page with text and a hero image the browser may initially just
render the text—at which point the browser would dispatch a
`largest-contentful-paint` entry whose `element` property would likely reference
a `<p>` or `<h1>`. Later, once the hero image finishes loading, a second
`largest-contentful-paint` entry would be dispatched and its `element` property
would reference the `<img>`.

It's important to note that an element can only be considered the largest
contentful element once it has rendered and is visible to the user. Images that
have not yet loaded are not considered "rendered". Neither are text nodes using
web fonts during the [font block
period](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display#The_font_display_timeline).
In such cases a smaller element may be reported as the largest contentful
element, but as soon as the larger element finishes rendering, it'll be
reported via another  `PerformanceEntry` object.

In addition to late-loading images and fonts, a page may add new elements to
the DOM as new content becomes available. If any of these new elements is
larger than the previous largest contentful element, a new `PerformanceEntry`
will also be reported.

If an element that is currently the largest contentful element is removed from
the viewport (or even removed from the DOM), it will remain the largest
contentful element unless a larger element is rendered.

{% Aside %}
  Prior to Chrome 88, removed elements were not considered as largest contentful
  elements, and removing the current candidate would trigger a new
  `largest-contentful-paint` entry to be dispatched. However, due to popular UI
  patterns such as image carousels that often removed DOM elements, the metric
  was updated to more accurately reflect what users experience. See the
  [CHANGELOG](https://chromium.googlesource.com/chromium/src/+/master/docs/speed/metrics_changelog/2020_11_lcp.md)
  for more details.
{% endAside %}

The browser will stop reporting new entries as soon as the user interacts with
the page (via a tap, scroll, or keypress), as user interaction often changes
what's visible to the user (which is especially true with scrolling).

For analysis purposes, you should only report the most recently dispatched
`PerformanceEntry` to your analytics service.

{% Aside 'caution' %}
  Since users can open pages in a background tab, it's possible that the largest
  contentful paint will not happen until the user focuses the tab, which can be
  much later than when they first loaded it.
{% endAside %}

#### Load time vs. render time

For security reasons, the render timestamp of images is not exposed for
cross-origin images that lack the
[`Timing-Allow-Origin`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Timing-Allow-Origin)
header. Instead, only their load time is exposed (since this is already exposed
via many other web APIs).

The [usage example](#measure-lcp-in-javascript)
below shows how to handle elements whose render time is not available. But,
when possible, it's always recommended to set the
[`Timing-Allow-Origin`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Timing-Allow-Origin)
header, so your metrics will be more accurate.

### How are element layout and size changes handled?

To keep the performance overhead of calculating and dispatching new performance
entries low, changes to an element's size or position do not generate new LCP
candidates. Only the element's initial size and position in the viewport is
considered.

This means images that are initially rendered off-screen and then transition
on-screen may not be reported. It also means elements initially rendered in the
viewport that then get pushed down, out of view will still report their
initial, in-viewport size.

### Examples

Here are some examples of when the Largest Contentful Paint occurs on a few
popular websites:

{% Img src="image/admin/bsBm8poY1uQbq7mNvVJm.png", alt="Largest Contentful Paint timeline from cnn.com", width="800", height="311" %}

{% Img src="image/admin/xAvLL1u2KFRaqoZZiI71.png", alt="Largest Contentful Paint timeline from techcrunch.com", width="800", height="311" %}

In both of the timelines above, the largest element changes as content loads.
In the first example, new content is added to the DOM and that changes what
element is the largest. In the second example, the layout changes and content
that was previously the largest is removed from the viewport.

While it's often the case that late-loading content is larger than content
already on the page, that's not necessarily the case. The next two examples
show the Largest Contentful Paint occurring before the page fully loads.

{% Img src="image/admin/uJAGswhXK3bE6Vs4I5bP.png", alt="Largest Contentful Paint timeline from instagram.com", width="800", height="311" %}

{% Img src="image/admin/e0O2woQjZJ92aYlPOJzT.png", alt="Largest Contentful Paint timeline from google.com", width="800", height="311" %}

In the first example, the Instagram logo is loaded relatively early and it
remains the largest element even as other content is progressively shown. In
the Google search results page example, the largest element is a paragraph of
text that is displayed before any of the images or logo finish loading. Since
all the individual images are smaller than this paragraph, it remains the
largest element throughout the load process.

{% Aside %}
  In the first frame of the Instagram timeline, you may notice the camera logo
  does not have a green box around it. That's because it's an `<svg>` element,
  and `<svg>` elements are not currently considered LCP candidates. The first
  LCP candidate is the text in the second frame.
{% endAside %}

## How to measure LCP

LCP can be measured [in the lab](/user-centric-performance-metrics/#in-the-lab)
or [in the field](/user-centric-performance-metrics/#in-the-field), and it's
available in the following tools:

### Field tools

- [Chrome User Experience
  Report](https://developers.google.com/web/tools/chrome-user-experience-report)
- [PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights/)
- [Search Console (Core Web Vitals
  report)](https://support.google.com/webmasters/answer/9205520)
- [`web-vitals` JavaScript library](https://github.com/GoogleChrome/web-vitals)

### Lab tools

- [Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/)
- [Lighthouse](https://developers.google.com/web/tools/lighthouse/)
- [WebPageTest](https://webpagetest.org/)

### Measure LCP in JavaScript

To measure LCP in JavaScript, you can use the [Largest Contentful Paint
API](https://wicg.github.io/largest-contentful-paint/). The following example
shows how to create a
[`PerformanceObserver`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver)
that listens for `largest-contentful-paint` entries and logs them to the
console.

```js
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    console.log('LCP candidate:', entry.startTime, entry);
  }
}).observe({type: 'largest-contentful-paint', buffered: true});
```

{% Aside 'warning' %}

  This code shows how to log `largest-contentful-paint` entries to the console,
  but measuring LCP in JavaScript is more complicated. See below for details:

{% endAside %}

In the above example, each logged `largest-contentful-paint` entry represents
the current LCP candidate. In general, the `startTime` value of the last entry
emitted is the LCP value—however, that is not always the case. Not all
`largest-contentful-paint` entries are valid for measuring LCP.

The following section lists the differences between what the API reports and how
the metric is calculated.

#### Differences between the metric and the API

- The API will dispatch `largest-contentful-paint` entries for pages loaded in a
  background tab, but those pages should be ignored when calculating LCP.
- The API will continue to dispatch `largest-contentful-paint` entries after a
  page has been backgrounded, but those entries should be ignored when
  calculating LCP (elements may only be considered if the page was in the
  foreground the entire time).
- The API does not report `largest-contentful-paint` entries when the page is
  restored from the [back/forward cache](/bfcache/#impact-on-core-web-vitals),
  but LCP should be measured in these cases since users experience them as
  distinct page visits.
- The API does not consider elements within iframes, but to properly measure LCP
  you should consider them. Sub-frames can use the API to report their
  `largest-contentful-paint` entries to the parent frame for aggregation.

Rather than memorizing all these subtle differences, developers can use the
[`web-vitals` JavaScript library](https://github.com/GoogleChrome/web-vitals) to
measure LCP, which handles these differences for you (where possible):

```js
import {getLCP} from 'web-vitals';

// Measure and log LCP as soon as it's available.
getLCP(console.log);
```

You can refer to [the source code for
`getLCP()`](https://github.com/GoogleChrome/web-vitals/blob/master/src/getLCP.ts)
for a complete example of how to measure LCP in JavaScript.

{% Aside %}
  In some cases (such as cross-origin iframes) it's not possible to measure LCP
  in JavaScript. See the
  [limitations](https://github.com/GoogleChrome/web-vitals#limitations) section
  of the `web-vitals` library for details.
{% endAside %}

### What if the largest element isn't the most important?

In some cases the most important element (or elements) on the page is not the
same as the largest element, and developers may be more interested in measuring
the render times of these other elements instead. This is possible using the
[Element Timing API](https://wicg.github.io/element-timing/), as described in
the article on [custom metrics](/custom-metrics/#element-timing-api).

## How to improve LCP

LCP is primarily affected by four factors:

* Slow server response times
* Render-blocking JavaScript and CSS
* Resource load times
* Client-side rendering

For a deep dive on how to improve LCP, see [Optimize
LCP](/optimize-lcp/). For additional guidance on individual
performance techniques that can also improve LCP, see:

* [Apply instant loading with the PRPL
  pattern](/apply-instant-loading-with-prpl)
* [Optimizing the Critical Rendering
  Path](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/)
* [Optimize your CSS](/fast#optimize-your-css)
* [Optimize your Images](/fast#optimize-your-images)
* [Optimize web Fonts](/fast#optimize-web-fonts)
* [Optimize your JavaScript](/fast#optimize-your-javascript) (for
  client-rendered sites)

## Additional resources

- [Lessons learned from performance monitoring in
  Chrome](https://youtu.be/ctavZT87syI) by [Annie
  Sullivan](https://anniesullie.com/) at
  [performance.now()](https://perfnow.nl/) (2019)

{% include 'content/metrics/metrics-changelog.njk' %}


text:
---
title: "Integration Tests with SQL Server Database Snapshots"
authors: johnnyreilly
tags: [Database Snapshots, Integration Testing, SQL Server]
hide_table_of_contents: false
---
## Once More With Feeling

 This is a topic that I have written about [before](https://blog.johnnyreilly.com/2014/01/integration-testing-with-entity.html).... But not well. I recently had cause to dust down my notes on how to use snapshotting in your integration tests. To my dismay, referring back to my original blog post was less helpful than I'd hoped. Now I've cracked the enigma code that my original scribings turned out to be, it's time to turn my relearnings back into something genuinely useful.

## What's the Scenario?

You have a test database. You want to write integration tests. So what's the problem? Well, these tests will add records, delete records, update records within the tables of the database. They will mutate the data. And that's exactly what they ought to do; they're testing that our code uses the database in the way we would hope and expect.

So how do we handle this? Well, we could handle this by writing code at the end of each test that is responsible for reverting the database back to the state that it was in at the start of the test. So if we had a test that added a record and tested it, we'd need the test to be responsible for removing that record before any subsequent tests run. Now that's a totally legitimate approach but it adds tax. Each test becomes more complicated and requires more code.

So what's another approach? Perhaps we could take a backup of our database before our first test runs. Then, at the end of each test, we could restore our backup to roll the database back to its initial state. Perfect, right? Less code to write, less scope for errors. So what's the downside? Backups are slowwwww. Restores likewise. We could be waiting minutes between each test that runs. That's not acceptable.

There is another way though: [database snapshots](https://msdn.microsoft.com/en-us/library/ms175158.aspx) \- a feature that's been nestling inside SQL Server for a goodly number of years. For our use case, to all intents and purposes, database snapshots offers the same functionality as backups and restores. You can backup a database (take a snapshot of a database at a point in time), you can restore a database (roll back the database to the point of the snapshot). More importantly, you can do either operation in \**under a second*\*. As it happens, Microsoft advocate using this approach themselves:

> In a testing environment, it can be useful when repeatedly running a test protocol for the database to contain identical data at the start of each round of testing. Before running the first round, an application developer or tester can create a database snapshot on the test database. After each test run, the database can be quickly returned to its prior state by reverting the database snapshot.

Sold!

## Talk is cheap, show me the code

In the end it comes down to 3 classes; `DatabaseSnapshot.cs` which does the actual snapshotting work and 2 classes that make use of it.

### DatabaseSnapshot.cs

This is our `DatabaseSnapshot` class. Isn't it pretty?

```cs
using System.Data;
using System.Data.SqlClient;

namespace Testing.Shared
{
    public class DatabaseSnapshot
    {
        private readonly string _dbName;
        private readonly string _dbSnapShotPath;
        private readonly string _dbSnapShotName;
        private readonly string _dbConnectionString;

        public DatabaseSnapshot(string dbName, string dbSnapshotPath, string dbSnapshotName, string dbConnectionString)
        {
            _dbName = dbName;
            _dbSnapshotPath = dbSnapshotPath;
            _dbSnapshotName = dbSnapshotName;
            _dbConnectionString = dbConnectionString;
        }

        public void CreateSnapshot()
        {
            if (!System.IO.Directory.Exists(_dbSnapshotPath))
                System.IO.Directory.CreateDirectory(_dbSnapshotPath);

            var sql = $"CREATE DATABASE { _dbSnapshotName } ON (NAME=[{ _dbName }], FILENAME='{ _dbSnapshotPath }{ _dbSnapshotName }') AS SNAPSHOT OF [{_dbName }]";

            ExecuteSqlAgainstMaster(sql);
        }

        public void DeleteSnapshot()
        {
            var sql = $"DROP DATABASE { _dbSnapshotName }";

            ExecuteSqlAgainstMaster(sql);
        }

        public void RestoreSnapshot()
        {
            var sql = "USE master;\r\n" +

                $"ALTER DATABASE {_dbName} SET SINGLE_USER WITH ROLLBACK IMMEDIATE;\r\n" +

                $"RESTORE DATABASE {_dbName}\r\n" +
                $"FROM DATABASE_SNAPSHOT = '{ _dbSnapshotName }';\r\n" +

                $"ALTER DATABASE {_dbName} SET MULTI_USER;\r\n";

            ExecuteSqlAgainstMaster(sql);
        }

        private void ExecuteSqlAgainstMaster(string sql, params SqlParameter[] parameters)
        {
            using (var conn = new SqlConnection(_dbConnectionString))
            {
                conn.Open();
                var cmd = new SqlCommand(sql, conn) { CommandType = CommandType.Text };
                cmd.Parameters.AddRange(parameters);
                cmd.ExecuteNonQuery();
                conn.Close();
            }
        }
    }
}
```

It exposes 3 methods:

CreateSnapshot

This method creates the snapshot of the database. We will run this right at the start, before any of our tests run.

DeleteSnapshot

Deletes the snapshot we created. We will run this at the end, after all our tests have finished running.

RestoreSnapshot

Restores the database back to the snapshot we took earlier. We run this after each test has completed. This method relies on a connection to the database (perhaps unsurprisingly). It switches the database in use away from the database that is being restored prior to actually running the restore. It happens to shift to the master database (I believe that's entirely incidental; although I haven't tested).

### SetupAndTeardown.cs

This class is responsible for setting up the snapshot we're going to use in our tests right before any of the tests have run (in the `FixtureSetup` method). It's also responsible for deleting the snapshot once all the tests have finished running (in the `FixtureTearDown` method). It should be noted that in this example I'm using NUnit and this class is written to depend on the hooks NUnit exposes for running code at the very beginning and end of the test cycle. All test frameworks have these hooks; if you're using something other than NUnit then it's just a case of swapping in the relevant attribute (everything tends to attribute driven in the test framework world).

```cs
using NUnit.Framework;

namespace Testing.Shared
{
   [SetUpFixture]
   public class SetupAndTeardown
   {
      public static DatabaseSnapshot DatabaseSnapshot;

      [SetUp]
      public void FixtureSetup()
      {
         DatabaseSnapshot = new DatabaseSnapshot("MyDbName", "C:\\", "MySnapshot", "Data Source=.;initial catalog=MyDbName;integrated security=True;");

         try
         {
            // Try to delete the snapshot in case it was left over from aborted test runs
            DatabaseSnapshot.DeleteSnapShot();
         }
         catch { /* this should fail with snapshot does not exist */ }

         DatabaseSnapshot.CreateSnapShot();
      }

      [TearDown]
      public void FixtureTearDown()
      {
         DatabaseSnapshot.DeleteSnapShot();
      }
   }
}
```

### TestBase.cs

All of our test classes are made to inherit from this class:

```cs
using NUnit.Framework;

namespace Testing.Shared
{
   public class TestBase
   {
      [TearDown]
      public void TearDown()
      {
         SetupAndTeardown.DatabaseSnapshot.RestoreSnapShot();
      }
   }
}
```

Which restores the database back to the snapshot position at the end of each test. And that... Is that!