<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Blocking Queue]]></title><description><![CDATA[Blocking Queue]]></description><link>https://blog.blockingqueue.com</link><generator>RSS for Node</generator><lastBuildDate>Fri, 23 Feb 2024 07:22:50 GMT</lastBuildDate><atom:link href="https://blog.blockingqueue.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><atom:link rel="next" href="https://blog.blockingqueue.com/rss.xml?page=1"/><item><title><![CDATA[Events in Node.js]]></title><description><![CDATA[<p>I heard multiple times that javascript is event-based but never really thought about how it works.</p><p>According to Wikipedia event-driven programming "is a programming paradigm in which the flow of the program is determined by events"</p><p>This doesn't say much but once I saw a simple example and that brought a lot of clarity.Will help a lot to understand it and know its internals. </p><p>Node.js has a module that you can use to create fire and listen for your own events. The essence is that we will listen for specific events and register listeners for each event.Listeners are just functions. Then we can emit events and the registered listeners will be executed. Each event is identified by a string or symbol. </p><p>By default the most basic code will look like this:</p><pre><code>const EventEmitter <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"events"</span>);const emitter <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> EventEmitter();emitter.on(<span class="hljs-string">"testEvent"</span>, () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {  console.log(<span class="hljs-string">"test event"</span>);})emitter.emit(<span class="hljs-string">"testEvent"</span>);</code></pre><p>What was so good about it was the "on" method. I have seen it in https/http and in ethersjs provider.on and jquery, it's almost everywhere and much of the Node.js core API is built around it. </p>]]></description><link>https://blog.blockingqueue.com/events-in-nodejs</link><guid isPermaLink="true">https://blog.blockingqueue.com/events-in-nodejs</guid><dc:creator><![CDATA[Liviu]]></dc:creator><pubDate>Tue, 19 Jul 2022 09:48:42 GMT</pubDate></item><item><title><![CDATA[Use python in shell, as if it were awk]]></title><description><![CDATA[<h3 id="heading-use-python-in-shell-as-if-it-were-awk">Use python in shell, as if it were awk</h3><p>My first technical article was about how to use awk.For some reason, I like learning bash even if it doesn't always make sense.I posted an article on hacker news and somebody suggested using one-liners, Perl.I thought that was a good idea but with Python, not Perl.</p><p>After starting to work on it I realized by default python is not that fitted for this.Unfortunately, python is not that useful for command-line one-liner programs.As soon as you need an indented block (like if) there is no way around line break, but even so, I think it will be a good exercise.Awk also allows you to provide a file with the script so it might not be a big deal in the end.</p><h3 id="heading-basic-usage">Basic usage</h3><p>The first thing you need is to run python with some input as code.This is easily achievable using -c</p><pre><code class="lang-bash">python -c <span class="hljs-string">'print(1 + 1)'</span></code></pre><p>The most common usage of awk is to print a few fields out of a file, for example:</p><pre><code class="lang-bash">$ cat file.inName, Population(2020), Population(2020), Land area(sq mi),Los Angeles, 3898747, 3792621, 469.49San Diego, 1386932, 1307402, 325.88San Jose, 1013240,945942, 178.26San Francisco, 873965, 805235, 46.91$ awk  -F, <span class="hljs-string">'{print $1 $3}'</span> file.inName Population(2020)Los Angeles 3792621San Diego 1307402San Jose945942San Francisco 805235</code></pre><p>The same thing in Python will look like:</p><pre><code>$ python -<span class="hljs-built_in">c</span> '<span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> <span class="hljs-keyword">open</span>(<span class="hljs-string">"file.in"</span>): fields=line.<span class="hljs-built_in">split</span>(<span class="hljs-string">","</span>); <span class="hljs-built_in">print</span> (fields[<span class="hljs-number">0</span>].strip(),fields[<span class="hljs-number">3</span>].strip())'<span class="hljs-type">Name</span>    <span class="hljs-type">Land</span> area(sq mi)<span class="hljs-type">Los</span> <span class="hljs-type">Angeles</span>    <span class="hljs-number">469.49</span><span class="hljs-type">San</span> <span class="hljs-type">Diego</span>    <span class="hljs-number">325.88</span><span class="hljs-type">San</span> <span class="hljs-type">Jose</span>    <span class="hljs-number">178.26</span><span class="hljs-type">San</span> <span class="hljs-type">Francisco</span>    <span class="hljs-number">46.91</span></code></pre><p>Python looks a bit more complex and since it is longer it will be more complicated to type if this is not part of a script.Another inconvenience is that each field needs to be stripped.We also made use of ";" and wrote multiple instructions on the same line.</p><h3 id="heading-begin-end">Begin end</h3><p>Awk has begin and end actions.These are very useful if you need to do sum or averages.</p><pre><code class="lang-bash">$ seq 99 101 &gt;numbers.txt$ awk <span class="hljs-string">'{sum=sum+$1} END {print "Sum: "sum" Avg: "sum/NR}'</span> numbers.txSum: 300 Avg: 100</code></pre><p>Python version will look like:</p><pre><code class="lang-bash">$ python -c <span class="hljs-string">'sum=0; NR=0for line in open("numbers.tx"): sum+=int(line); NR+=1print("Sum:",sum," Avg:",sum/NR)'</span>Sum: 300  Avg: 100.0</code></pre><p>Awk can be written as a one-line while the python version will need multiple lines and initialization for variables.At this point, I started to think that even if I do these multi-line commands it will be better to have a small utility function that will deal with the parsing and initialize standard awk variables.</p><pre><code class="lang-python"><span class="hljs-keyword">import</span> sys<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">arg_param_value</span>(<span class="hljs-params">i</span>):</span>    <span class="hljs-keyword">if</span> i &lt; len(sys.argv):        <span class="hljs-keyword">return</span> sys.argv[i]    <span class="hljs-keyword">else</span>:        <span class="hljs-keyword">return</span> <span class="hljs-string">""</span><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">parse_params</span>():</span>    i = <span class="hljs-number">1</span>    <span class="hljs-keyword">while</span> i &lt; len(sys.argv):        arg = sys.argv[i]        <span class="hljs-keyword">if</span> arg.startswith(<span class="hljs-string">'-'</span>):            i += <span class="hljs-number">1</span>            args[arg] = arg_param_value(i)        <span class="hljs-keyword">else</span>:            inputs.append(sys.argv[i])        i += <span class="hljs-number">1</span><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">code</span>():</span>    <span class="hljs-keyword">if</span> <span class="hljs-string">'-f'</span> <span class="hljs-keyword">in</span> args:        <span class="hljs-keyword">with</span> open(args[<span class="hljs-string">'-f'</span>], <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> f:            <span class="hljs-keyword">return</span> f.readlines()    <span class="hljs-keyword">else</span>:        <span class="hljs-keyword">return</span> inputs.pop(<span class="hljs-number">0</span>)  <span class="hljs-comment"># removes first element from the list</span><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process_file</span>():</span>    <span class="hljs-keyword">global</span> NR    FNR = <span class="hljs-number">0</span>    <span class="hljs-keyword">with</span> open(FILENAME, <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> file:        <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> file:            line = line.strip()            <span class="hljs-keyword">if</span> len(line) == <span class="hljs-number">0</span>:                <span class="hljs-keyword">continue</span>            <span class="hljs-keyword">if</span> FS == <span class="hljs-string">''</span>:                fields = line.split()            <span class="hljs-keyword">else</span>:                fields = line.split(FS)            NF = len(fields)            FNR += <span class="hljs-number">1</span>            NR += <span class="hljs-number">1</span>            exec(code)args = {}inputs = []parse_params()code = code()NR = <span class="hljs-number">0</span>FS = <span class="hljs-string">''</span><span class="hljs-keyword">if</span> <span class="hljs-string">'-F'</span> <span class="hljs-keyword">in</span> args: FS = args[<span class="hljs-string">'-F'</span>]<span class="hljs-keyword">for</span> FILENAME <span class="hljs-keyword">in</span> inputs:    process_file()</code></pre><p>And I run it like:</p><pre><code class="lang-bash">$ python main.py -F <span class="hljs-string">";"</span> <span class="hljs-string">"print(fields[2], fields[3])"</span> in1.csv in2.csv</code></pre><p>Of course, there is more functionality in awk, I will slowly add it to my script and hopefully, I can turn it into something usable.There won't be a $0 $1 $2 .. $n, instead, I will use line for $0 and fields[] for $1 $2 and all the others.</p><p>After doing all this I think python is useful for these types of tasks especially if you already use it in other places.The main advantage would be that you don't have to learn awk if you already know python.The GitHub with a more complete version is here: <a target="_blank" href="Link">https://github.com/liviusd/pawk</a></p><p>Please let me know what you think about it!</p>]]></description><link>https://blog.blockingqueue.com/use-python-in-shell-as-if-it-were-awk</link><guid isPermaLink="true">https://blog.blockingqueue.com/use-python-in-shell-as-if-it-were-awk</guid><dc:creator><![CDATA[Liviu]]></dc:creator><pubDate>Sat, 05 Feb 2022 21:39:48 GMT</pubDate><cover_image>https://cdn.hashnode.com/res/hashnode/image/upload/v1644097349991/Hf5vJHlQy.jpeg</cover_image></item><item><title><![CDATA[AWS Lambda Tutorial]]></title><description><![CDATA[<p>The first time I heard about AWS lambda it make me doubt my career."Less" is an adjective suffix meaning without so I thought serverless is a way of getting rid of the servers.I'm a backend developer so I imagine this is a way of generating backend code.In reality serverless is just a way of making your backend easier to scale.Actually, you don't have to worry about how to scale it. </p><p>A few weeks ago I read again about it, it was something about how to build a SaaS with 0$, and lambda was mentioned because you get 1 000 000 free calls.I liked the idea, seeing some benefits in it and I thought it would be useful to try all sorts of things, so I will need an easy deployment process that I could use to quickly run side projects.In order to follow this, you will need an AWS account and aws cli working.I will be using java but it should be easy to adapt to any other language because I will deploy it using Docker container.I did this using the command line because it is easier to replicate.</p><h3 id="heading-how-lambda-works">How lambda works</h3><p>In theory, things are simple. You write a function that is ran based on some event.In this tutorial, the event is a REST call.Each such function will be executed in a container.This means lambda has its own isolated execution environment.The container is created when the function is executed for the first time.After some time the container is destroyed.Because of this, you might get into cold start issues.This happens because your container may take some time to start.Sometimes AWS will reuse your container so you won't notice it but if your function is rarely called you might see it takes a lot of time to execute.</p><h3 id="heading-build-the-project">Build the project</h3><p>I used the IntelliJ Idea and created an empty maven project.I added the  AWS lambda java core dependency to the project and build a simple method that handles a request.</p><p>The java code looks like this:</p><pre><code class="lang-java"><span class="hljs-keyword">package</span> bq;<span class="hljs-keyword">import</span> com.amazonaws.services.lambda.runtime.Context;<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">App</span> </span>{    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Object <span class="hljs-title">handleRequest</span><span class="hljs-params">(Object arg, Context context)</span> </span>{        <span class="hljs-keyword">return</span> arg;    }}</code></pre><p>The maven pom to package this is:</p><pre><code class="lang-xml"><span class="hljs-meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">project</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://maven.apache.org/POM/4.0.0"</span>         <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">"http://www.w3.org/2001/XMLSchema-instance"</span>         <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">modelVersion</span>&gt;</span>4.0.0<span class="hljs-tag">&lt;/<span class="hljs-name">modelVersion</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>bq<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>bq<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>maven-compiler-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.5.1<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>11<span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">target</span>&gt;</span>11<span class="hljs-tag">&lt;/<span class="hljs-name">target</span>&gt;</span>                <span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span>            <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>maven-dependency-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.1.2<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">includeScope</span>&gt;</span>runtime<span class="hljs-tag">&lt;/<span class="hljs-name">includeScope</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">executions</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">execution</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">id</span>&gt;</span>copy-dependencies<span class="hljs-tag">&lt;/<span class="hljs-name">id</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">phase</span>&gt;</span>package<span class="hljs-tag">&lt;/<span class="hljs-name">phase</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">goals</span>&gt;</span>                                <span class="hljs-tag">&lt;<span class="hljs-name">goal</span>&gt;</span>copy-dependencies<span class="hljs-tag">&lt;/<span class="hljs-name">goal</span>&gt;</span>                            <span class="hljs-tag">&lt;/<span class="hljs-name">goals</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">execution</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">executions</span>&gt;</span>                <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>        <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.amazonaws<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>aws-lambda-java-core<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.2.1<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">project</span>&gt;</span></code></pre><p>We need maven-dependency-plugin because we will copy all the jar files into the docker container.This plugin will make sure we have them in the target/dependency directory. Maybe there is a way to push everything as a jar but this is good enough to start. </p><p>Make sure everything works</p><pre><code class="lang-bash">$ mvn package</code></pre><p>This is the project structure:</p><pre><code>. Dockerfile lambda<span class="hljs-operator">-</span>iam.json lambda.iml pom.xml src    main       java          bq              App.java       resources    test        java target     bq<span class="hljs-number">-1.0</span><span class="hljs-operator">-</span>SNAPSHOT.jar     classes        bq            App.class     dependency        aws<span class="hljs-operator">-</span>lambda<span class="hljs-operator">-</span>java<span class="hljs-operator">-</span>core<span class="hljs-number">-1.2</span><span class="hljs-number">.1</span>.jar     generated<span class="hljs-operator">-</span>sources        annotations     maven<span class="hljs-operator">-</span>archiver         pom.properties    <span class="hljs-comment">//removed the rest</span></code></pre><h3 id="heading-push-the-container">Push the container</h3><p>As previously mentioned the lambda will start a docker container.This uses AWS base images for Lambda.More details about it here https://gallery.ecr.aws/lambda/javaThe usage tab also shows you how to build your lambda container if you need more instructions. </p><p>The docker file:</p><pre><code><span class="hljs-attribute">FROM</span> public.ecr.aws/lambda/java:<span class="hljs-number">11</span><span class="hljs-attribute">COPY</span> target/classes <span class="hljs-variable">${LAMBDA_TASK_ROOT}</span><span class="hljs-attribute">COPY</span> target/dependency/* <span class="hljs-variable">${LAMBDA_TASK_ROOT}</span>/lib/<span class="hljs-attribute">CMD</span><span class="hljs-meta"> [ "bq.App::handleRequest" ]</span><span class="hljs-attribute">RUN</span> chmod <span class="hljs-number">644</span> $(find . -type f)<span class="hljs-attribute">RUN</span> chmod <span class="hljs-number">755</span> $(find . -type d)</code></pre><p>Build the container</p><pre><code>mvn packagedocker build . -t java<span class="hljs-operator">-</span>aws<span class="hljs-operator">-</span>echo:<span class="hljs-number">1</span></code></pre><p>And tested it:</p><pre><code>docker run  <span class="hljs-operator">-</span>p <span class="hljs-number">9000</span>:<span class="hljs-number">8080</span> java<span class="hljs-operator">-</span>aws<span class="hljs-operator">-</span>echo:<span class="hljs-number">1</span>curl <span class="hljs-operator">-</span>XPOST <span class="hljs-string">"http://localhost:9000/2015-03-31/functions/function/invocations"</span> <span class="hljs-operator">-</span>d <span class="hljs-string">'{}'</span></code></pre><p>The docker image will be hosted in  Elastic Container Registry (ecr)After I saw everything worked on localhost I created an ecr repository and pushed the image:</p><pre><code>aws ecr create<span class="hljs-operator">-</span>repository <span class="hljs-operator">-</span><span class="hljs-operator">-</span>repository<span class="hljs-operator">-</span>name java<span class="hljs-operator">-</span>aws<span class="hljs-operator">-</span>echoaws ecr get<span class="hljs-operator">-</span>login<span class="hljs-operator">-</span>password <span class="hljs-operator">-</span><span class="hljs-operator">-</span>region us<span class="hljs-operator">-</span>west<span class="hljs-number">-2</span> <span class="hljs-operator">|</span> docker login <span class="hljs-operator">-</span><span class="hljs-operator">-</span>username AWS <span class="hljs-operator">-</span><span class="hljs-operator">-</span>password<span class="hljs-operator">-</span>stdin YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-west<span class="hljs-number">-2</span>.amazonaws.comdocker tag java<span class="hljs-operator">-</span>aws<span class="hljs-operator">-</span>echo:<span class="hljs-number">1</span> YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-west<span class="hljs-number">-2</span>.amazonaws.com/java<span class="hljs-operator">-</span>aws<span class="hljs-operator">-</span>echo:<span class="hljs-number">1</span>docker push YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-west<span class="hljs-number">-2</span>.amazonaws.com/java<span class="hljs-operator">-</span>aws<span class="hljs-operator">-</span>echo:<span class="hljs-number">1</span></code></pre><h3 id="heading-create-the-lambda">Create the lambda</h3><p>Before we create the lambda we need to create a role that lambda will assume.This is the minimal policy I found somewhere in AWS docs:</p><pre><code class="lang-json">{  <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,  <span class="hljs-attr">"Statement"</span>: [    {      <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,      <span class="hljs-attr">"Principal"</span>: {        <span class="hljs-attr">"Service"</span>: <span class="hljs-string">"lambda.amazonaws.com"</span>      },      <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"sts:AssumeRole"</span>    }  ]}</code></pre><pre><code class="lang-bash">aws iam create-role --role-name lambda --assume-role-policy-document file://lambda.json</code></pre><p>Creating the lambda from the command line is fairly simple.</p><pre><code class="lang-bash">aws lambda create-function --function-name java-lambda --code ImageUri=YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-west-2.amazonaws.com/java-aws-echo:1 --role arn:aws:iam::YOUR_AWS_ACCOUNT_ID:role/lambda --package-type Image</code></pre><p>And voila that is all for your function. The only thing is that is not yet exposed on the internet. You can give it a try from AWS console UI and trigger a test.</p><h4 id="heading-exposing-the-lambda-into-internet">Exposing the lambda into internet.</h4><p>This was the part I wasn't expecting to be that complicated.Once you have your lambda deployed you are probably asking yourself, where do I find the URL?My assumption was that once you created it by default it will receive a default URL.It is not the case and you need to do a few more steps and your function will be exposed using the AWS API Gateway.Here is a bash script I created that will create an API GW for your lambda:</p><pre><code class="lang-bash"><span class="hljs-meta">#!/usr/bin/env bash</span>NAME=<span class="hljs-string">"Lambda API GW"</span>METHOD=<span class="hljs-string">"POST"</span><span class="hljs-comment">#you can find the arn if you go on Lambda &gt; Functions &gt; java-lambda -&gt;Copy ARN</span>LAMBDA_ARN=<span class="hljs-string">"PROVIDE THE LAMBDA ARN!!!!"</span>REGION=<span class="hljs-string">"us-west-2"</span>aws apigateway create-rest-api --name <span class="hljs-string">"<span class="hljs-variable">$NAME</span>"</span> &gt; apigateway-create-rest-api.tmpAPI_ID=$(cat apigateway-create-rest-api.tmp |jq <span class="hljs-string">".id"</span> -r)<span class="hljs-built_in">echo</span> <span class="hljs-variable">$API_ID</span>ROOT_ID=$(aws apigateway get-resources --rest-api-id <span class="hljs-variable">$API_ID</span>|jq <span class="hljs-string">'.items|first.id'</span> -r)<span class="hljs-built_in">echo</span> <span class="hljs-variable">$ROOT_ID</span><span class="hljs-comment">#request</span>aws apigateway put-method --rest-api-id <span class="hljs-variable">$API_ID</span> --resource-id <span class="hljs-variable">$ROOT_ID</span> --http-method <span class="hljs-variable">$METHOD</span> --authorization-type NONE --no-api-key-required<span class="hljs-comment">#Response</span>aws apigateway put-method-response --rest-api-id <span class="hljs-variable">$API_ID</span> --resource-id <span class="hljs-variable">$ROOT_ID</span> --http-method <span class="hljs-variable">$METHOD</span> --status-code 200 --response-models <span class="hljs-string">"{\"application/json\": \"Empty\"}"</span><span class="hljs-built_in">echo</span> <span class="hljs-string">"aws apigateway put-method --rest-api-id <span class="hljs-variable">$API_ID</span> --resource-id <span class="hljs-variable">$ROOT_ID</span> --http-method <span class="hljs-variable">$METHOD</span>"</span><span class="hljs-built_in">echo</span> <span class="hljs-string">"Integrations"</span>URI=<span class="hljs-string">"arn:aws:apigateway:<span class="hljs-variable">$REGION</span>:lambda:path/2015-03-31/functions/<span class="hljs-variable">$LAMBDA_ARN</span>/invocations"</span><span class="hljs-built_in">echo</span> <span class="hljs-variable">$URI</span>aws apigateway put-integration --rest-api-id <span class="hljs-variable">$API_ID</span> --resource-id <span class="hljs-variable">$ROOT_ID</span> --<span class="hljs-built_in">type</span> AWS --http-method <span class="hljs-variable">$METHOD</span> --integration-http-method <span class="hljs-variable">$METHOD</span> --uri <span class="hljs-variable">$URI</span>aws apigateway put-integration-response --rest-api-id <span class="hljs-variable">$API_ID</span> --resource-id <span class="hljs-variable">$ROOT_ID</span> --http-method <span class="hljs-variable">$METHOD</span> --status-code 200 --content-handling CONVERT_TO_TEXT<span class="hljs-built_in">echo</span> <span class="hljs-string">"Permissions"</span>FUNCTION_NAME=$(aws lambda get-function --function-name <span class="hljs-variable">$LAMBDA_ARN</span>|jq <span class="hljs-string">'.Configuration.FunctionName'</span> -r)ACCOUNT_ID=$(aws sts get-caller-identity|jq <span class="hljs-string">'.Account'</span> -r)SOURCE_ARN=<span class="hljs-string">"arn:aws:execute-api:<span class="hljs-variable">$REGION</span>:<span class="hljs-variable">$ACCOUNT_ID</span>:<span class="hljs-variable">$API_ID</span>/*/<span class="hljs-variable">$METHOD</span>/"</span><span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$FUNCTION_NAME</span> <span class="hljs-variable">$SOURCE_ARN</span>"</span>aws lambda add-permission --function-name <span class="hljs-variable">$FUNCTION_NAME</span> --statement-id STTT --action lambda:InvokeFunction --principal apigateway.amazonaws.com --source-arn <span class="hljs-variable">$SOURCE_ARN</span>aws apigateway create-deployment --rest-api-id <span class="hljs-variable">$API_ID</span> --stage-name atm1</code></pre><p>I then searched for the lambda URL in the AWS console.Log into your account and select API Gateway.The URL for it is: https://us-west-2.console.aws.amazon.com/apigateway/main/apisThen click on the newly created API and it should show the Resources and the POST method.In the left menu, there should be "Stages", click on it and then select the atm1.<br />On a blue background, there should be "Invoke URL" in the stage editor.Give it a test:</p><pre><code class="lang-bash">curl -XPOST <span class="hljs-string">"Your Invoke URL"</span> -d <span class="hljs-string">'{}'</span></code></pre><p>If you followed this tutorial and you have any issues please let me know. Hope this helps!</p>]]></description><link>https://blog.blockingqueue.com/aws-lambda-tutorial</link><guid isPermaLink="true">https://blog.blockingqueue.com/aws-lambda-tutorial</guid><dc:creator><![CDATA[Liviu]]></dc:creator><pubDate>Wed, 05 Jan 2022 22:56:09 GMT</pubDate><cover_image>https://cdn.hashnode.com/res/hashnode/image/upload/v1641423228817/jAA6Q5ncD.jpeg</cover_image></item><item><title><![CDATA[Yet Another AWK Cheat Sheet]]></title><description><![CDATA[<p>I like bash, you can achieve a lot of things with some basic commands. I also like to make scripts for my work because it is the perfect documentation.</p><p>A long time ago I learned the basics of sed and grep and this helped me a lot while doing support. Before having fancy tools like Kibana and CloudWatch knowing to grep was paying off. Even now if I need to debug something very complicated I prefer having the logs in a console. </p><p>Another thing that I still do in the console is some sanity checks between different sources. For example, I have a customer's file that I need to match to another file that has database records and see they are in sync.  This is how I got to learn AWK and write about how I use it.</p><p>I could add a proper introduction to AWK here but I assume you have some experience with it so I'll keep it short. AWK is a text-processing language and it is used as a data extraction tool or other similar tasks.</p><h3 id="heading-how-it-works">How it works</h3><p>Awk is a scripting language, requires no compilation, and has variables, numeric and string functions, and logical operators. </p><p>The basic thing to remember about it is that it deals with records and fields. Records are read one at a time and then they are split into fields. You can imagine it like reading a simple CSV file where a record is a line and a field is a cell.</p><h3 id="heading-basic-usage">Basic usage</h3><p>The most basic usage of awk is to get just a few fields out of each line. </p><pre><code>$ echo <span class="hljs-string">"a b c"</span> | awk <span class="hljs-string">'{ print <span class="hljs-subst">$2</span>" "<span class="hljs-subst">$3</span>}'</span>b c</code></pre><p>A few things to remember from here. Each field has its own variable: $1, $2, $3, and so on ($0 represents the entire record). Other important to remember variables (not all of them):</p><ul><li>NR: Number of Records</li><li>NF: Number of Fields</li><li>FNR refers to the record number (typically the line number) in the current file different than NR refers to the total record number. This has an interesting usage because NR==FNR is true only for the first file, and is used a lot in file comparison</li></ul><h3 id="heading-separator">Separator</h3><p>By default, awk will split records based on whitespace.  If you have a different separator use -F. The delimiter can be a regular expression: -F'[,:]' so you can use multiple delimiters.</p><pre><code>$ echo <span class="hljs-string">"a,b,c"</span> | awk -F<span class="hljs-string">','</span>  <span class="hljs-string">'{print <span class="hljs-subst">$1</span>" "<span class="hljs-subst">$2</span>}'</span>a b</code></pre><h3 id="heading-input">Input</h3><p>Most probably you won't use awk with echo or commands from the standard input, reading from a file would look like this:</p><pre><code>$ echo <span class="hljs-string">"a b c"</span> <span class="hljs-operator">&gt;</span> f1.txt$ awk <span class="hljs-string">'{ print $2" "$3}'</span> f1.txt b c</code></pre><p>Awk accepts multiple input files:</p><pre><code>$  echo <span class="hljs-string">"1 2 3"</span> <span class="hljs-operator">&gt;</span> f2.txt$ awk <span class="hljs-string">'{ print $2" "$3}'</span> f1.txt f2.txt b c<span class="hljs-number">2</span> <span class="hljs-number">3</span></code></pre><p>Program source code can also be read from a file, for this we use the -f option:</p><pre><code>$ echo <span class="hljs-string">'{ print $2" "$3}'</span> <span class="hljs-operator">&gt;</span> aw$ awk <span class="hljs-operator">-</span>f aw f1.txt b c</code></pre><h3 id="heading-selection-criteria">Selection Criteria</h3><p>Before doing the processing for each record you can use selection criteria. This can be a pattern or a condition.  This is useful if you want to process the lines which match the given pattern or respect condition.  </p><p>awk '/manager/ {print}' f1.txt </p><h3 id="heading-beginend">Begin/End</h3><p>You can also add begin and end actions.</p><pre><code>$awk '      <span class="hljs-type">BEGIN</span> {<span class="hljs-built_in">print</span> <span class="hljs-string">"start"</span>}{<span class="hljs-built_in">print</span> $<span class="hljs-number">1</span><span class="hljs-string">" "</span>$<span class="hljs-number">3</span>}<span class="hljs-type">END</span> {<span class="hljs-built_in">print</span> <span class="hljs-string">"end"</span>}' f1.txt starta <span class="hljs-built_in">c</span>end</code></pre><p>These are very useful if you need to do an average or print a sum. </p><pre><code><span class="hljs-string">$</span> <span class="hljs-string">seq</span> <span class="hljs-number">99</span> <span class="hljs-number">101</span> <span class="hljs-string">&gt;numbers.txt</span><span class="hljs-string">$</span> <span class="hljs-string">awk</span> <span class="hljs-string">'{sum=sum+$1}END {print "Sum: "sum" Avg: "sum/NR}'</span> <span class="hljs-string">numbers.txt</span> <span class="hljs-attr">Sum: 300 Avg:</span> <span class="hljs-number">100</span></code></pre><p>seq 99 101 &gt;numbers.txt will create a sequence of numbers, one per line in a file</p><h3 id="heading-matching-2-files">Matching 2 files</h3><p>With these examples in mind, we can try the main task, match 2 files based on one of the fields. You can think of it as a database inner join. </p><p>There will be 2 files: names.txt and license.txt. In names.txt the first column is the id while in license.txt the second column is the id. The script will be in the matchScript file.   We want to match each name to its license. </p><p>Awk will iterate over both files. As mentioned earlier, FNR is the record number in the current file while NR is the record number out of the total. The condition NR==FNR will hold true only while iterating records from the first files, this means details from the first file will be stored in a map. The map will be initialized on the first usage.Next will end current rerond processing moving to the next one.</p><p>The second part will check if the id is already in the map and print if the condition matched. </p><pre><code>$ cat names.txt <span class="hljs-number">1</span>,Sleepy<span class="hljs-number">3</span>,Dopey<span class="hljs-number">2</span>,Grumpy$ cat license.txt BASIC,<span class="hljs-number">2</span>BASIC,<span class="hljs-number">1</span>PRO,<span class="hljs-number">3</span>$ cat matchScript (NR<span class="hljs-operator">=</span><span class="hljs-operator">=</span>FNR){   names[$1]<span class="hljs-operator">=</span>$2;    next}($2 in names){   print names[$2]<span class="hljs-string">","</span>$1}$ awk <span class="hljs-operator">-</span>f matchScript <span class="hljs-operator">-</span>F <span class="hljs-string">','</span> names.txt license.txt Grumpy,BASICSleepy,BASICDopey,PRO</code></pre><h3 id="heading-other">Other</h3><p>If you need more info or you want to go into deep details  <a target="_blank" href="https://www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents">this</a>  is the best place for it. </p>]]></description><link>https://blog.blockingqueue.com/yet-another-awk-cheat-sheet</link><guid isPermaLink="true">https://blog.blockingqueue.com/yet-another-awk-cheat-sheet</guid><dc:creator><![CDATA[Liviu]]></dc:creator><pubDate>Wed, 15 Dec 2021 21:04:11 GMT</pubDate><cover_image>https://cdn.hashnode.com/res/hashnode/image/upload/v1639602457915/d2TDmuM3U.jpeg</cover_image></item><item><title><![CDATA[Hello world]]></title><description><![CDATA[<p>Here we go, my first blog post. In my head, I wanted to do this for a very long time but never really give it a try. Not sure why, one reason might be my not-so-good writing skills. Then I realized there is no better way to exercise your writing skills than writing. It is like a tech skill, you can read as many tutorials as you want it won't work until you try it yourself. Practice makes perfect</p><p>My hopes are I will keep a log of tech things I'm doing and trying. From time to time I will also post nontech things I found interesting. </p><p>Why BlockingQueue? I really like StackOverflow but all bug names domain are already taken, so I was left with a data structure</p><p>That's all for now, read me later :)</p>]]></description><link>https://blog.blockingqueue.com/hello-world</link><guid isPermaLink="true">https://blog.blockingqueue.com/hello-world</guid><dc:creator><![CDATA[Liviu]]></dc:creator><pubDate>Mon, 06 Dec 2021 20:52:23 GMT</pubDate><cover_image>https://cdn.hashnode.com/res/hashnode/image/upload/v1639254498957/jWau0DZB0.jpeg</cover_image></item></channel></rss>