amazon web services – AWS Lambda error on build Node with Sharp Library

I have a problem to build my lambda handler. I’m trying to use sharp library to do an image resize on S3.

My code:

S3.getObject({
    Bucket: bucketName,
    Key: objectKey
}, (err, data) => {
    SHARP(data.Body).resize(250, 250).toFormat("jpg").toBuffer().then((buffer) => {
        S3.putObject({
            Body: buffer,
            Bucket: bucketName,
            Key: objectKey,
            ContentType: "image/jpeg",
            ContentDisposition: "inline",
        })
    })
});

My node dependencies:

  "dependencies": {
    "aws-sdk": "^2.637.0",
    "dotenv": "^10.0.0",
    "mysql": "^2.18.1",
    "sharp": "^0.29.1",
    "util": "^0.12.4"
  },
  "devDependencies": {
    "esbuild": "^0.12.27",
    "nodemon": "^2.0.12"
  }

My code to build:

esbuild --bundle --minify --platform=node --target=node12 --outdir=build index.js && cd build && zip index.js.zip index.js

AWS Lambda error:

Cannot find module '../build/Release/sharp-linux-x64.node'
Require stack:
- /var/task/index.js
- /var/runtime/UserFunction.js
- /var/runtime/index.js

Possible solutions:
- Install with the --verbose flag and look for errors: "npm install --ignore-scripts=false --verbose sharp"
- Install for the current runtime: "npm install --platform=linux --arch=x64 sharp"
- Consult the installation documentation: https://sharp.pixelplumbing.com/install

database – A Hit Counter For AWS Python Lambda powered with DynamoDB

I’m learning how to use DynamoDB and various AWS services, so I decided to write a simple hit counter application for my education of how to use DynamoDB. This application deduplicates hits from the same client for the same page by storing a hash of their user agent and ip address. It also stores 1 entry of hits per day, and accumulates them over the time domain. I’m looking for feedback on how I structured the dynamo calls and potential issues that it has. I suspect that I might be using a consistent read when I don’t need to. I’m also curious if I used the right pattern to handle an upsert in dynamodb.

The dynamo db table has a hash key of the “url” and a sort field called “as_of_when” which says roughly when the hits occured.

"""
A simple hit counter stuff to learn the various apis of dynamodb.
"""

import datetime
import os
import hashlib
import base64

import boto3
from botocore.exceptions import ClientError
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all
from pybadges import badge

patch_all()

TABLE_NAME = os.getenv("TABLE_NAME", "hit_counts")

dynamo = boto3.client('dynamodb')


def get_today() -> str:
    """
    Gets a formatted date string
    """
    return datetime.datetime.now().strftime("%Y-%m-%d")

def get_full_timestamp() -> str:
    """
    Gets a complete date string
    """
    return datetime.datetime.now().strftime("%Y%m%d%H%M%S")

def get_previous_total(url:str):
    """
    Gets the most recent known total. Should be used before inserting a new instance
    """
    response = dynamo.query(
        TableName=TABLE_NAME,
        Select='ALL_ATTRIBUTES',
        Limit=1,
        KeyConditionExpression="the_url=:urlval",
        ScanIndexForward=False,
        ExpressionAttributeValues={
            ":urlval": {
                "S": url
            }
        }
    )
    if response('Count') == 0:
        return 0
    return response('Items')(0)('accumulated_count')('N')

@xray_recorder.capture('insert_new_entry')
def insert_new_entry(url:str, as_of_when : str, user_hash : str, user_id : str):
    the_count = str(int(get_previous_total(url)) + 1)

    result = dynamo.put_item(
        TableName=TABLE_NAME,
        Item={
            'the_url': {
                'S': url
            },
            'as_of_when': {
                'S': as_of_when
            },
            'today_count': {
                'N': '1'
            },
            'accumulated_count': {
                'N': the_count
            },
            'user_id_hashes': {
                'SS': (user_hash)
            },
            'user_hashes': {
                'SS': (user_id)
            }
        },
        ReturnValues='ALL_OLD',
        ReturnItemCollectionMetrics='SIZE',
        ReturnConsumedCapacity='TOTAL',
        ConditionExpression='attribute_not_exists(the_url) and attribute_not_exists(as_of_when)'
    )
    print('insert_result', result)

    
    return result

@xray_recorder.capture('update_existing_entry')
def update_existing_entry(url:str, as_of_when : str, user_hash : str, user_id : str):
    result = dynamo.execute_statement(
        Statement=f"""
            UPDATE {TABLE_NAME}
            SET today_count = today_count + 1
            SET accumulated_count = accumulated_count + 1
            SET user_hashes = set_add(user_hashes, ?)
            SET user_id_hashes = set_add(user_id_hashes, ?)
            WHERE the_url = ? AND as_of_when = ? RETURNING ALL NEW *
        """,
        Parameters=(
            {
                "SS": (user_id)
            },
            {
                "SS": (user_hash)
            },
            {
                "S": url
            },
            {
                "S": as_of_when
            }
        )
    )
    return result

@xray_recorder.capture('get_todays_entry')
def get_todays_entry(url:str, as_of_when : str):
    result = dynamo.get_item(
        TableName=TABLE_NAME,
        Key={
            'the_url': {
                'S': url
            },
            'as_of_when': {
                'S': as_of_when
            }
        },
        AttributesToGet=(
            'today_count',
            'accumulated_count',
            'user_hashes',
            'user_id_hashes'
        ),
        ConsistentRead=True
    )

    print('get_todays_entry', result)
    if 'Item' in result:
        return result('Item')
    return None


def increment_hit_count(url:str, as_of_when : str, user_hash : str, user_id : str):
    """
    increments a counter instance in the dynamo table
    """
    current_hits = get_todays_entry(url, as_of_when)

    if current_hits is None:
        # Insert new entry
        x = insert_new_entry(url, as_of_when, user_hash, user_id)
        current_hits = {
            'accumulated_count': {
                'N': "1"
            }
        }
    else:
        # Check for existence in existing object
        print(current_hits('user_id_hashes'))
        print(user_id)
        if user_hash not in current_hits('user_id_hashes')('SS'):
            result = update_existing_entry(url, as_of_when, user_hash, user_id)
            if 'Items' in result:
                current_hits = result('Items')(0)
            print(result)

    
    return  current_hits('accumulated_count')('N')




def hash_api_gateway_event(event : dict):
    reqContext = event('requestContext')('http')
    reqString = ':'.join((reqContext('sourceIp'), reqContext('protocol') + reqContext('userAgent')))
    
    m = hashlib.md5()
    m.update(reqString.encode('utf-8'))

    return base64.b64encode(m.digest()).decode('utf-8'), reqString


def handler(event : dict, context):
    """
    # Invoked via query string parameters from an image tag
    # Returns a SVG unless text parameter is set.
    """
    print(event)
    print("hello")

    user_hash, og_user_id = hash_api_gateway_event(event)
    print(user_hash, og_user_id)

    if 'queryStringParameters' in event:
        url = event('queryStringParameters')('url')
        result = increment_hit_count(url, get_today(), user_hash, og_user_id)

        print(result)


    body =  badge(left_text="Total Views", right_text=result)

    return {
        "statusCode": 200,
        "isBase64Encoded": False,
        "headers": {
            "Content-Type": "image/svg+xml"
        },
        "body": body
    }

Are PD-, $lambda$-, $psi$-, and $delta$-rings monoids in a monoidal category?

$newcommand{pt}{mathrm{pt}}newcommand{N}{mathbb{N}}newcommand{Z}{mathbb{Z}}$A number of algebraic structures can be defined as monoids in some appropriate monoidal category:

  • A monoid is a monoid in $(mathsf{Sets},times,pt)$;
  • A semiring is a monoid in $(mathsf{CMon},otimes_{N},N)$;
  • A ring is a monoid in $(mathsf{Ab},otimes_Z,Z)$;
  • An $R$-algebra is a monoid in $(mathsf{Mod}_R,otimes_R,R)$;
  • A graded $R$-algebra is a monoid in $(mathsf{Gr}_Zmathsf{Mod}_R,otimes_R,R)$;
  • A differential graded $R$-algebra is a monoid in $(mathsf{Ch}_bullet(mathsf{Mod}_R),otimes_R,R)$;
  • A differential ring is a monoid in abelian groups with endomorphisms.

Is this also the case for the following notions of "rings with power operations"?

  1. PD-rings (nLab, Wikipedia), triples $(A,I,gamma_n)$ with $gamma_ncolon Ito I$ satisfying e.g. (but not only)
    $$gamma_{n}(x+y)=sum_{k=0}^{n}gamma_{n-k}(x)gamma_{k}(y);$$
  2. $lambda$-rings (nLab, Wikipedia), pairs $(A,lambda_n)$ with $lambda_n$ satisfying e.g. (but not only)
    $$lambda^{n}(x+y)=sum_{i+j=n}lambda^i(x)lambda^j(y);$$
  3. $psi$-rings, pairs $(A,psi_n)$ with $psi_n$ satisfying e.g. (but not only)
    $$psi^npsi^m(x)=psi^{nm}(x);$$
  4. $delta$-rings, pairs $(A,delta)$ with $delta$ satisfying e.g. (but not only)
    $$delta(xy)=x^pdelta(y)+y^pdelta(x)+pdelta(x)delta(y).$$

python – Llamar una lambda hija y dejarla corriendo

Estoy haciendo unos procesos que pueden tardar mucho tiempo, y no tengo problemas con eso, pero en el FE no puedo hacer esperar tanto al usuario por lo que con asyncio tengo pensado llamar a otra lambda que haga el proceso, independiente si sale correcto o no (El resultado se guarda en DynamoDB) y que la lambda padre solo devuelva algo tipo Se procesarán los datos mientras que la lambda hija carga con todo el proceso correspondiente

import asyncio

async def Settlement():
    #Hago unos calculos para los parametros del metodo de invoker
    print("Starting...")
    task = asyncio.create_task(invoker())
    print("Ending...")

async def invoker():
    task = asyncio.ensure_future(client.invoke(
    #Tambien he usado asyncio.create_task
        FunctionName = '<ARN>',
        InvocationType = 'Event'
    ))
    return await task('body')
def lambda_handler(event, context):
    asyncio.run(Settlement())
    return "Procesando datos"

El problema es que me tira el error An asyncio.Future, a coroutine or an awaitable is required

lambda calculus – Lemma relating variable substitution to de Bruijn substitution

Notation:

  • Let $t$ and $u$ be terms in the $lambda$-calculus, and $x$ be a variable name.

  • Let $(xmapsto u)t$ be the substitution in $t$ of free variable $x$ for the term $u$.

  • Let $t^phi$ be the de Bruijn index–representation of a term $t$ in the $lambda$-calculus (where $phi$ is an injection from variable names to $mathbb{N}$, with a sufficiently-large domain).

  • Let $(i mapsto_{textrm{dB}} u^phi)(t^phi)$ be the substitution in $t^phi$ of the free variable with index $i$ for the de Bruijn term $u^phi$.


Question:

I’ve tried to search existing literature for a rigorous proof of the following (intuitively correct?) statement, but have come up empty:

$((xmapsto u)t)^phi = (phi(x) mapsto_{textrm{dB}} u^phi)(t^phi)$.

Specifically, I’m hoping for a proof that deals directly with the “normal” $lambda$-calculus quotiented by $alpha$-equivalence, instead of one that uses the Barengredt convention, nominal logic, etc.


What I’ve Tried:

  • I think this is equivalent to Exercise 6.2.8 in Types and Programming Languages, but that proof isn’t given explicitly. Also, I assume it relies on the Barendregt convention (like the rest of TAPL).

  • I’ve found a paper that seems to prove this statement by using a nominal logic–representation of the $lambda$-calculus as an intermediary, but I guess I’m hoping for something more straightforward: Proof Pearl: De Bruijn Terms Really Do Work.

  • I’ve also proving the statement via induction on $t$, but without much luck (to wit, it’s been a few weeks now and I’m still banging my head against it).

what does the brackets behind lambda mean? – python

i am new to python and i am wondering why this doesnt work for lambda in python ?

for person in people:
print(lambda person:person.split()(0) + ' ' + person.split() 
(-1))

results:

<function <lambda> at 0x7f9d04332ed8>
<function <lambda> at 0x7f9d04332ed8>
<function <lambda> at 0x7f9d04332ed8>
<function <lambda> at 0x7f9d04332ed8>

but instead, the solution given was

for person in people:
print((lambda person:person.split()(0) + ' ' + person.split() 
(-1))(person))

results:

Dr. Brooks
Dr. Collins-Thompson
Dr. Vydiswaran
Dr. Romero

What does it mean to add ‘(person)’ behind the lambda expression? and what does the first result mean?

Thank you for your answers, i deeply appreciate your explanation!

javascript – lambda function vs anonymous function vs callback function

I’m writing a introductory JavaScript tutorial series, I have a question about terminology.

When explaining the Array.prototype methods, I’ve given an example of some code like:

const letters = ('a', 'b', 'c'); 
letters.forEach((value) => {
    console.log("the value is: " + value)
}); 

I’ve said what’s happening here is:

  1. Firstly, we’re calling an object function (a function that belongs to and object, in this case the object is the letters array).
  2. We pass as the first and only argument, a function: (value) => {//...} This is commonly known as a lambda or anonymous function.. (Unfortunately AWS Lambda functions, which is a service provided by Amazon confuses the terminology a bit 😭 )
  3. That function has a parameter value, that is is going to be the current element as the we iterate over the array.
  4. We print the value.

So the first question is, say instead my code looked like:

function printCurrentValue(value) {
    console.log("the value is: " + value)
}

const letters = ('a', 'b', 'c'); 
letters.forEach(printCurrentValue); 
  • Would we still call that an anonymous function? After all, it it is now assigned to a variable.
  • Would we still call it a lambda function?

That is – intuitively I would say an anonymous function is any unnamed function, whereas I would still want to say that a named function can be used as a lambda function, as would be the case here, because lambda function, if you’ll excuse my vagueness, is a ‘a function that produces one value from another or something’, I’m sure there’s a better definition.

Elsewhere in the tutorial, I want to talk about callbacks.

For example, I might have some code like:

fetch('/user')
.then((res) => res.json())
.then((json) => console.log(json)); 

Where (res) => res.json() and (json) => console.log(json) are callbacks and they are also anonymous functions – but I’m not sure it’s correct to call them lambda functions.

That is, I would define a callback as ‘a function that is called else where in your application’. By that definition, the lambda functions passed into an Array.prototype method are callback functions.

Is there a tidy way to differentiate between the three terms?

Delete older EBS Volume snapshots except few with certain tags using Python, Lambda

I am learning Python and managed to accomplish the above. But my script doesn’t seem optimal. Could someone help to take a review and suggest for betterment?

import boto3
from datetime import datetime,timedelta

REGION = "ap-southeast-1"
retention_days = 45
account_id = boto3.client('sts').get_caller_identity().get('Account')
ec2 = boto3.client('ec2', region_name=REGION)

def lambda_handler(event, context):
    now = datetime.now()
    outdated_snapID = ()
    retain_snapID = ()
    result = ec2.describe_snapshots(OwnerIds=(account_id))
    for snapshot in result('Snapshots'):
        # Remove timezone info from snapshot in order for comparison to work below
        snapshot_time = snapshot('StartTime').replace(tzinfo=None)
        # Subtract snapshot time from now returns a timedelta 
        # Check if the timedelta is greater than retention days
        if (now - snapshot_time) > timedelta(retention_days):
            outdated_snapID.append(snapshot('SnapshotId'))
    retain_snap = ec2.describe_snapshots(OwnerIds=(account_id), Filters=({'Name': 'tag:Retain', 'Values': ('True', 'true')}))
    for snap in retain_snap('Snapshots'):
        # Remove timezone info from snapshot in order for comparison to work below
        snapshot_time = snap('StartTime').replace(tzinfo=None)
        if (now - snapshot_time) > timedelta(retention_days):
            retain_snapID.append(snap('SnapshotId'))
    # Remove retained snapshotID's from the outdated array
    for i in retain_snapID:
        outdated_snapID.remove(i)
    for x in outdated_snapID:
        delete_snapshot(x)

def delete_snapshot(snapshotID):
    try:
        ec2.delete_snapshot(SnapshotId=snapshotID)
    except Exception as ex:
        print("Something went wrong:", ex)
        pass
```