<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: arszen123</title>
    <description>The latest articles on DEV Community by arszen123 (@arszen123).</description>
    <link>https://dev.to/arszen123</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F125531%2F11f0e5e8-6455-4dca-8be8-b7acf52c8b79.png</url>
      <title>DEV Community: arszen123</title>
      <link>https://dev.to/arszen123</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arszen123"/>
    <language>en</language>
    <item>
      <title>Building an offer notification service on AWS</title>
      <dc:creator>arszen123</dc:creator>
      <pubDate>Sat, 26 Feb 2022 10:18:20 +0000</pubDate>
      <link>https://dev.to/arszen123/building-an-offer-notification-service-on-aws-587e</link>
      <guid>https://dev.to/arszen123/building-an-offer-notification-service-on-aws-587e</guid>
      <description>&lt;p&gt;Let's build a simple web crawler application on AWS, that sends a notification when there is a special offer for a product.&lt;/p&gt;

&lt;p&gt;I love peanut butter, and whenever there is an offer for it I would like to stock up some. So I thought I will create a simple application that sends me a notification whenever there is an offer for this product. What I need, to create this application is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The product &lt;a href="https://www.myprotein.com/sports-nutrition/all-natural-peanut-butter/10530743.html" rel="noopener noreferrer"&gt;URL&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;And the exact location where the offer is located on the webpage, so I can extract this information. For this product, the offer is located in the &lt;code&gt;#pap-banner-text-value&lt;/code&gt; HTML element.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Probably you want to get notified by different things, so you can customize the application logic. Perhaps you would like to get notifications when a GPU/XBOX/PS4 is back in stock or you want to pull data from an API and send notifications based on predefined criteria. It's up to you what the application sends notifications about.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7doztty6xz6cz3wx1fv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7doztty6xz6cz3wx1fv.png" alt="Architecture diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The AWS services we will use to create this application are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/eventbridge/" rel="noopener noreferrer"&gt;AWS EventBridge&lt;/a&gt; - For scheduling lambda function invocations&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/lambda/" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt;  -  For crawling the website and publishing messages to an SNS topic&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/sns/" rel="noopener noreferrer"&gt;AWS SNS &lt;/a&gt; -  For sending email notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll also use NodeJS for the Lambda function and &lt;a href="https://www.serverless.com/framework" rel="noopener noreferrer"&gt;Serverless&lt;/a&gt; for  managing the infrastructure and deploying the application.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting up the development environment
&lt;/h2&gt;

&lt;p&gt;First, we have to install the Serverless CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; serverless
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After installation, we have to configure the credentials. &lt;em&gt;If you don't have it, you can generate new credentials on the AWS console.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;serverless config credentials &lt;span class="nt"&gt;--provider&lt;/span&gt; aws &lt;span class="nt"&gt;--key&lt;/span&gt; 1234 &lt;span class="nt"&gt;--secret&lt;/span&gt; 5678
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After we have installed the CLI, we can create a new project.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;serverless create &lt;span class="nt"&gt;--template&lt;/span&gt; aws-nodejs &lt;span class="nt"&gt;--path&lt;/span&gt; offer-notification-application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The above command creates a skeleton project with a &lt;code&gt;serverless.yml&lt;/code&gt; file, where we'll define our infrastructure, and a &lt;code&gt;handler.js&lt;/code&gt; where we'll implement our Lambda function.&lt;/p&gt;


&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;Based on the above architecture diagram, we'll have a Lambda function, which will be invoked every day. This Lambda function will fetch the target website content, and whenever an offer is found it publishes a message to an SNS topic. Because our Lambda function will publish to an SNS topic, therefore it must have the necessary permissions to do this.&lt;/p&gt;

&lt;p&gt;We also need an SNS topic where the offers will be published and an email subscriber which needs to be notified whenever a new message is published on this topic. &lt;/p&gt;

&lt;p&gt;The following &lt;code&gt;serverless.yml&lt;/code&gt; file describes the above-mentioned architecture.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;






&lt;p&gt;We also need a .env file with an EMAIL environment variable in it, set to the desired email address where we want to receive the notifications.&lt;/p&gt;




&lt;p&gt;Now, that we have defined our infrastructure, we can move on and write our application logic.&lt;/p&gt;

&lt;p&gt;We should create a new &lt;code&gt;src&lt;/code&gt; directory and move the &lt;code&gt;handler.js&lt;/code&gt; file under the newly created directory, to make it better structured.&lt;/p&gt;

&lt;p&gt;What our Lambda function needs to do is fetch the target website content and check whether there is an interesting offer. For this, we need some additional packages to fetch the site (&lt;a href="https://www.npmjs.com/package/axios" rel="noopener noreferrer"&gt;axios&lt;/a&gt;) and parse the HTML content (&lt;a href="https://www.npmjs.com/package/cheerio" rel="noopener noreferrer"&gt;cheerio&lt;/a&gt;), so let's install them with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;axios cheerio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now we have everything to implement the application core logic. For this product, it will look like the following.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;As you can see the &lt;code&gt;fetchOffer&lt;/code&gt; function fetches the website content, and as we already know that the offer is located in the &lt;code&gt;#pap-banner-text-value&lt;/code&gt; HTML element, with cheerio we can easily extract the content of it.&lt;/p&gt;

&lt;p&gt;Because I only want to get notifications when the offer is something like &lt;strong&gt;2 FOR 1&lt;/strong&gt; or &lt;strong&gt;30 % off&lt;/strong&gt;, I need to check if the offer matches with one of the regular expressions.&lt;/p&gt;

&lt;p&gt;In the handler function, the &lt;code&gt;fetchOffer&lt;/code&gt; function is invoked, and whenever it returns an offer it will be published to the SNS topic.&lt;/p&gt;

&lt;p&gt;It's very simple, isn't it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;p&gt;Now we can deploy the application to AWS with a single command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;serverless deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After it's successfully deployed, we should receive a confirmation email to the configured email address. After we have confirmed the subscription, we'll receive an email from every message published on that SNS topic.&lt;/p&gt;

&lt;p&gt;To remove the deployed application run the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;serverless remove
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;We can easily test the deployed application manually by invoking the Lambda function with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;serverless invoke &lt;span class="nt"&gt;--function&lt;/span&gt; crawl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there is an offer on the site, we should receive an email about the offer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;For creating this application we have used Serverless, to define the infrastructure and deploy our application. We also used AWS Lambda for running our code, scheduled events for triggering the Lambda function invocation, and SNS for sending email notifications to subscribers. As you have seen it was very easy to implement and deploy this application to AWS with Serverless.&lt;/p&gt;

&lt;p&gt;You can check out the repository on &lt;a href="https://github.com/arszen123/offer-notification-application/tree/88d2862f45f3f8549842ccb6439e7948dd268978" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>node</category>
      <category>serverless</category>
      <category>lambda</category>
    </item>
    <item>
      <title>GitHub Copilot in flight</title>
      <dc:creator>arszen123</dc:creator>
      <pubDate>Thu, 09 Dec 2021 15:30:32 +0000</pubDate>
      <link>https://dev.to/arszen123/github-copilot-in-flight-181</link>
      <guid>https://dev.to/arszen123/github-copilot-in-flight-181</guid>
      <description>&lt;h2&gt;
  
  
  GitHub Copilot in flight
&lt;/h2&gt;




&lt;h3&gt;
  
  
  GitHub Copilot?
&lt;/h3&gt;

&lt;p&gt;If you haven't heard about &lt;a href="https://copilot.github.com"&gt;GitHub Copilot&lt;/a&gt; yet, it is an AI-powered code assistant which can suggest whole lines and entire functions of code inside your favorite IDE.&lt;/p&gt;




&lt;h3&gt;
  
  
  Copilot in flight
&lt;/h3&gt;

&lt;p&gt;Just when I started to create a &lt;a href="https://github.com/arszen123/calculator"&gt;simple compiler&lt;/a&gt; in TypeScript, I got access to GitHub Copilot. I got excited and instantly integrated it into VSCode and started using it. My first thought was it will only slow me down because I have to interpret and correct every single line of code it suggests. Soon I realized it made the development faster than I could have imagined.&lt;/p&gt;

&lt;p&gt;The first thing I tried is to make Copilot suggest me a complete implementation of a &lt;a href="https://en.wikipedia.org/wiki/Circular_buffer"&gt;CircularBuffer&lt;/a&gt; utility class. But it only suggested a simple Buffer class, which implementation was incorrect and I had to fix it manually.&lt;/p&gt;

&lt;p&gt;Probably this was a bigger challenge for it, so I decided to only use it for smaller tasks like function implementations and unit test writing. In the beginning, it still suggested some irrelevant and incorrect code, but as the project grew the suggestion got better.&lt;/p&gt;

&lt;p&gt;My experience is that it adapts to the developer/project, so you can't trust it 100% (as it is &lt;a href="https://copilot.github.com/#faq-does-github-copilot-write-perfect-code"&gt;noted on their website&lt;/a&gt;). For example, at first, I started writing unit tests like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;And soon it started suggesting similar code. Imagine a test case where I want to test a more complex expression, like this: &lt;code&gt;10 * (4 + 16) / 10&lt;/code&gt;. It would be messy, and unreadable. So I refactored the test cases to assert the generated syntax tree.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You can see that it's much easier to read this test case than the previous one. Copilot quickly adapted to this and started suggesting relevant code, to make the development faster.&lt;/p&gt;

&lt;p&gt;Another example is when I wanted to parse a simple expression with a single function call for the first time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z0G5rzf0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/31sydo281ppywhc357zu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z0G5rzf0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/31sydo281ppywhc357zu.jpg" alt="Simple function call test case suggested by Copilot" width="621" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first sight, this code suggestion looks good, but it does not fit entirely well into my project. First, there is no &lt;code&gt;CallNode&lt;/code&gt;, only a &lt;code&gt;FunctionCallNode&lt;/code&gt; (It was defined before I started writing this test case). Also, the node first parameter should be a token and not another node. You can see a possible implementation below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;After this test case was implemented, Copilot started suggesting correct implementations for similar test cases. Below is a nested function call test case suggested by Copilot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gbmj1zvB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/107x6v8wve75fi9nkehw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gbmj1zvB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/107x6v8wve75fi9nkehw.jpg" alt="Nested function call" width="485" height="314"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I also tried to observe Copilot during the core components implementation. So, I gave it a task to suggest a function call parser, and to my surprise, it suggested a nice code snippet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2K1lgvxD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7934ql70h35xvubhvsqu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2K1lgvxD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7934ql70h35xvubhvsqu.jpg" alt="Function call parser by Copilot" width="624" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But there is some problem with the above code,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It should create a new &lt;code&gt;FunctionCallNode&lt;/code&gt; and not a &lt;code&gt;VarNode&lt;/code&gt; ,&lt;/li&gt;
&lt;li&gt;If the current token is not a function identifier, it should forward the control and try to parse an expression,&lt;/li&gt;
&lt;li&gt;The parsed function must have one and only one parameter, and it is a big limitation.&lt;/li&gt;
&lt;/ol&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As you can see in the above implementation the previously mentioned errors are fixed and the parsed function calls can have zero or more parameters.&lt;/p&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;For me, Copilot was very helpful for some tedious work, especially when I had to write almost the same code over and over (ex. token definitions, specific node types), and it was also very useful for writing unit tests. For the core components implementation, I mostly used it as an autocomplete to type faster, and not as an assistant who suggests whole implementations.&lt;/p&gt;

&lt;p&gt;In my opinion, Copilot adapts to the project/developer, therefore it does not make anyone a better developer, but it can make a good developer faster. We still have to understand the suggested code and correct any mistake it makes, but it looks very promising.&lt;/p&gt;




&lt;p&gt;Thank you for reading my first ever article, I hope you enjoyed it.&lt;/p&gt;

</description>
      <category>githubcopilot</category>
      <category>development</category>
      <category>productivity</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
