<?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[Akash R Chandran's blog]]></title><description><![CDATA[The world seeks the knowledge I have. So I am here to share it.]]></description><link>https://blog.akashrchandran.in</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1665838327590/TqIXk0Tvv.png</url><title>Akash R Chandran&apos;s blog</title><link>https://blog.akashrchandran.in</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 04:13:03 GMT</lastBuildDate><atom:link href="https://blog.akashrchandran.in/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Ultimate Guide to Understanding Spring Batch 5 Processing]]></title><description><![CDATA[In your development life, you might have come across a place where you need to use batch processing, and you need to find the right framework that is robust, resilient and widely adopted, offering LTS (Long-Term Support) for sustained stability and s...]]></description><link>https://blog.akashrchandran.in/ultimate-guide-to-understanding-spring-batch-5-processing</link><guid isPermaLink="true">https://blog.akashrchandran.in/ultimate-guide-to-understanding-spring-batch-5-processing</guid><category><![CDATA[spring batch]]></category><category><![CDATA[Springboot]]></category><category><![CDATA[Spring]]></category><category><![CDATA[Batch Processing]]></category><category><![CDATA[Java]]></category><category><![CDATA[Spring framework]]></category><category><![CDATA[Processing]]></category><dc:creator><![CDATA[Akash R Chandran]]></dc:creator><pubDate>Sun, 13 Apr 2025 16:16:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1744559195289/064b3e6c-32fb-4044-854d-188701277ec5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In your development life, you might have come across a place where you need to use batch processing, and you need to find the right framework that is robust, resilient and widely adopted, offering LTS (Long-Term Support) for sustained stability and support in production environments. Spring Batch is one of them. As the name suggests it is part of the larger Spring framework. Spring is a Java-based framework with many projects and a big community of contributors. If you have used or learned Spring Boot, you’re already halfway to learning Spring Batch. This blog will explain the concepts of the Spring Batch. We will implement a simple batch process that sends emails to a list of addresses. Without wasting time let’s directly get into it.</p>
<h1 id="heading-what-is-batch-processing">What is Batch Processing?</h1>
<p>Batch processing is handling a large amount of data in batches. Batches can be time ranges or numbers of records, etc. We use batch processing when the amount of data is finite and known and can be processed with some delay. <strong>As per the Spring documentation, batch processing is the processing of a finite amount of data in a manner that does not require external interaction or interruption.</strong></p>
<p>For example, suppose we open a Google Form to retrieve user feedback for your mobile application. Then you download the responses as a CSV file. Now you have the CSV file and want to convert the data from CSV to a database table. Here, you need batch processing to efficiently use the resources without errors or omissions. As you're processing a huge amount of data, it will take time to complete.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735782653637/3caf8ba2-cb8d-4a5d-a86c-54a935f8a4cd.png" alt class="image--center mx-auto" /></p>
<p><strong>Why choose batch processing?</strong> One might ask. The main advantage of batch processing is that it handles a finite amount of data, which can be very large, even reaching millions, billions, or trillions of records. Depending on the requirements, you can design an approach that uses resources efficiently.</p>
<h1 id="heading-what-is-spring-batch">What is Spring Batch?</h1>
<p>Spring Batch is a framework that facilitates batch processing by providing various features such as parallel processing, fault tolerance, horizontal scalability, and ease of use. It was initially developed through a collaboration between Accenture and Interface21 (now SpringSource), the creators of the Spring Framework in 2007. At the end of March 2008, the Spring Batch 1.0.0 release was made available to the public. It was one of the initial concepts for batch processing in Java.</p>
<p>Now, Spring Batch is being developed by VMware, the same company that develops Spring Boot. The latest version, Spring Batch 5, introduces many new features. Development is progressing rapidly, with new releases every six months. Spring Batch provides various features, making it one of the best batch-processing frameworks out there. Let’s look at some of the features.</p>
<h1 id="heading-features-of-spring-batch">Features of Spring Batch</h1>
<ul>
<li><p><strong>Flexibility:</strong> Spring Batch provides excellent flexibility. Whatever batch processing you need to do, Spring Batch can support it. Run batches in parallel on a single device or distribute them across multiple devices; Spring Batch supports it all.</p>
</li>
<li><p><strong>Fault Tolerance</strong>: The spring batch has various types of fault tolerance mechanisms such as the retry, skip, restart ability etc. which are essential for the perfect batch processing framework.</p>
</li>
<li><p><strong>Transaction Management</strong>: Your job needs transactions in a database. Worry not, Spring Batch can automatically start transactions. If it fails at any point, it will automatically roll back, so you don’t have to worry about it.</p>
</li>
<li><p><strong>Chunk-based processing</strong>: Spring Batch supports chunk processing, meaning it doesn’t commit or save until a certain number of records or items are processed. This can significantly improve performance when storing data in a database or file.</p>
</li>
<li><p><strong>Job Management</strong>: Spring Batch can handle batch jobs efficiently. It stores information such as the number of items processed, the current item number, etc., in its database. In case of a crash, it can recover and continue from where it left off.</p>
</li>
<li><p><strong>Support for various resources like databases, files and more</strong>: Since it is part of Spring Boot, which already supports many databases out of the box, Spring Batch inherits that capability. On top of that, it also supports many custom databases, files, and other resources.</p>
</li>
</ul>
<hr />
<p><strong>Java isn’t your cup of tea? Why not use Python for batch processing with Luigi? It's a Python-based framework for workflow orchestration developed by Spotify. Get concepts of it in my blog link below.</strong></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.akashrchandran.in/deep-dive-into-the-concepts-of-luigi">https://blog.akashrchandran.in/deep-dive-into-the-concepts-of-luigi</a></div>
<p> </p>
<h1 id="heading-architecture-of-spring-batch">Architecture of Spring Batch</h1>
<p>The Spring batch architecture contains 3 high-level components. The architecture looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743066483931/236f023d-9adf-44c4-9526-6ba99abb049d.png" alt class="image--center mx-auto" /></p>
<p>The application component contains the custom code and configuration used to build your batch processes. Business logic services and all the configurations of how you organize the job are considered the application.</p>
<p>The Batch Core contains the core runtime classes necessary to launch and control a batch job. It includes implementations for <code>JobLauncher</code>, <code>Job</code>, and <code>Step</code>. Both Application and Core are built on top of a common infrastructure.</p>
<p>The infrastructure contains all the readers, writers, and different services. Their core also uses such elements. The application layer is connected to the infrastructure layer due to the custom implementations that the developer creates for the read and write.</p>
<h1 id="heading-core-components-of-spring-batch">Core Components of Spring Batch</h1>
<h2 id="heading-job">Job</h2>
<p>A single execution unit that summarises a series of processes for batch application in Spring Batch. Multiple jobs can exist in a single application. Job is an entity that comprises the details of the entire batch process. From where to start to what comes next, every detail is contained within a Job entity. A job can contain many N number steps.</p>
<p>A batch job in Spring Batch is represented by the Job interface provided by the <code>spring-batch-core</code> dependency:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Job</span> </span>{
    <span class="hljs-function">String <span class="hljs-title">getName</span><span class="hljs-params">()</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">(JobExecution execution)</span></span>;
}
</code></pre>
<p>At a fundamental level, the Job interface requires that implementations specify the Job name (the <code>getName()</code> method) and what the Job is supposed to do (the execute method).</p>
<p>The execute method gives a reference to an <code>JobExecution</code> object. The <code>JobExecution</code> represents the actual execution of the Job at runtime. It contains several runtime details, such as the start time, the end time, the execution status, and so on.</p>
<p>In Spring Batch, a job is defined as a Spring bean, allowing Spring Batch to manage everything from creation to termination. The definition kind of looks like this.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Bean</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> Job <span class="hljs-title">newsletterJob</span><span class="hljs-params">(JobRepository jobRepository, Step step1)</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> JobBuilder(<span class="hljs-string">"newsletter-job"</span>, jobRepository)
            .start(step1)
            .build();
}
</code></pre>
<h2 id="heading-step">Step</h2>
<p>A Step is a domain object that encapsulates an independent, sequential phase of a batch Job. It contains all of the information necessary to define a unit of work in a batch Job. The job can contain any number of steps. This step can be individually parallelised, fault-tolerant and restartable.</p>
<p>A Step in the Spring Batch is represented by the Step interface provided by the <code>spring-batch-core</code> dependency:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Step</span> </span>{
  <span class="hljs-function">String <span class="hljs-title">getName</span><span class="hljs-params">()</span></span>;
  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">(StepExecution stepExecution)</span> <span class="hljs-keyword">throws</span> JobInterruptedException</span>;
}
</code></pre>
<p>Similar to the Job interface, the Step interface requires, at a fundamental level, an implementation to specify the step name (the <code>getName()</code> method) and what the step is supposed to do (the execute method).</p>
<p>The execute method provides a reference to an <code>StepExecution</code> object. The <code>StepExecution</code> represents the actual execution of the step at runtime. It contains several runtime details, such as the start time, the end time, the execution status, and so on. Spring Batch stores this runtime information in the metadata repository, similar to the <code>JobExecution</code>, as we have seen previously.</p>
<h2 id="heading-jobparameters">JobParameters</h2>
<p>Job parameters are values passed to the job, allowing the entire job process to access them. <strong>One of the key features of Spring Batch is its ability to determine whether a job is new or if it is running a previous job, and this is determined using the values of job parameters passed.</strong> The values passed as job parameters will be hashed and stored. When a new job is run, the values of job parameters are compared to check whether they match any old job.</p>
<pre><code class="lang-java"> JobParameters jobParameters = <span class="hljs-keyword">new</span> JobParametersBuilder()
                .addString(<span class="hljs-string">"filePath"</span>, <span class="hljs-string">"input/data.csv"</span>)
                .addLong(<span class="hljs-string">"time"</span>, System.currentTimeMillis()) <span class="hljs-comment">// make the job unique every time it runs</span>
                .toJobParameters();
</code></pre>
<p>Access to the job parameters is possible both in the <code>JobExecution</code> context and the <code>Stepexecution</code> context.</p>
<h2 id="heading-joblauncher">JobLauncher</h2>
<p>As we have created a job with steps now we want some way to invoke the job on startup, this can be done using the JobLauncher interface.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">JobLauncher</span> </span>{
   <span class="hljs-function">JobExecution <span class="hljs-title">run</span><span class="hljs-params">(Job job, JobParameters jobParameters)</span>
          <span class="hljs-keyword">throws</span>
             JobExecutionAlreadyRunningException,
             JobRestartException,
             JobInstanceAlreadyCompleteException,
             JobParametersInvalidException</span>;
}
</code></pre>
<p>The run method is designed to launch a given Job with a set of JobParameters.</p>
<h2 id="heading-jobexecutioncontext">JobExecutionContext</h2>
<p>It stores the different details about the job execution that are used by Spring Batch to keep track of the different parts of the job execution. The <code>JobExecutionContext</code> is a key-value pair storage, where Spring Batch puts some keys, and it is available to the entire job process to access. Even custom data can be added and accessed later in the job execution. It can be used to share data between steps.</p>
<pre><code class="lang-java">JobExecution jobExecution = jobLauncher.run(job, jobParameters);
JobExecutionContext jobExecutionContext = jobExecution.getExecutionContext();
jobExecutionContext.put(<span class="hljs-string">"jobStartTime"</span>, <span class="hljs-keyword">new</span> Date());
</code></pre>
<h2 id="heading-stepexecutioncontext">StepExecutionContext</h2>
<p>It is the same as the <code>JobExecutionContext</code> but only local to a step execution. There you may say each step will have its step execution context. It is also a key value store which spring batch stores keys related to the step execution. Even custom data can be added and accessed later in the step execution. It can be used to share data between different parts of the same steps.</p>
<pre><code class="lang-java">StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
StepExecutionContext stepExecutionContext = stepExecution.getExecutionContext();
stepExecutionContext.put(<span class="hljs-string">"currentItem"</span>, currentItem);
</code></pre>
<h2 id="heading-jobrepository">JobRepository</h2>
<p>Spring batch is stateful, it means that it stores details of the job execution and the step execution. This is denoted by the <code>JobExecution</code> and <code>StepExecution</code>. Spring batch supports different types of databases for storing its state, relational databases such as MySQL, and PostgreSQL and non-relational databases such as MongoDB. The relations between different tables can be seen below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744436774503/493a1be5-8a33-4f1a-842d-7bbfa841747d.png" alt class="image--center mx-auto" /></p>
<p>Each table is crucial for the spring batch to manage running job states. Each of them serves as metadata storage for different components of the spring batch environment. Let’s look into each table.</p>
<h3 id="heading-jobinstance">Job_Instance</h3>
<p>The <code>Job_Instance</code> table stores the unique job runs. I have previously mentioned that the job parameters are used to uniquely identify a job. This is the table used for that purpose. A job can be run again if something fails and you want to restart the old job. The job parameters are hashed and stored as a job key in this table. The job name and the job key are together used to identify if the job is new or not. For each unique run of the job, the spring batch creates a new job instance.</p>
<h3 id="heading-jobexecution">Job_Execution</h3>
<p>The <code>Job_Execution</code> table stores the details of each job run. Even if a job is restarted, it is stored as a new row, and the details are kept separate. The <code>Job_Execution</code> table consists of various columns that store details about the job execution, such as start_time, end_time, and status. The job execution, along with the job instance, is checked to see if the job is complete or failed. If it has failed, it can be restarted. Completed jobs cannot be restarted by default; you will need to manually configure that.</p>
<h3 id="heading-jobexecutionparams">Job_Execution_Params</h3>
<p>The <code>Job_Execution_Params</code> table stores the job parameters. There can be multiple job parameters for a single job. Sometimes you want to pass a value as a job parameter but don’t want that value to uniquely identify the job. In that case, you have the option to set the identifying to false, and it will be reflected in this table.</p>
<h3 id="heading-jobexecutioncontext-1">Job_Execution_Context</h3>
<p>Used to store the <code>JobExecutionContext</code> data. The stored data is in Java serialized format, which is then encoded in base64. The base64 encoding is used to prevent character issues that can occur during storage.</p>
<h3 id="heading-stepexecution">Step_Execution</h3>
<p>The <code>Step_Execution</code> stores the details about the execution of different steps. Each step execution is stored as a new row. It stores different details including the start_time, end_time, Read_count, Write_count etc. done by the step.</p>
<h3 id="heading-stepexecutioncontext-1">Step_Execution_Context</h3>
<p>It stores the <code>StepExecutionContext</code> data. The stored data is in Java serialized format, which is then encoded in base64. The base64 encoding is used to prevent character issues that can occur during storage.</p>
<h1 id="heading-types-of-steps">Types of Steps</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744137942172/1670dd58-5413-41d7-a569-aba67c624981.png" alt class="image--center mx-auto" /></p>
<p>There are many types of steps available each of them is very useful in many different scenarios. The most used step type is the Tasklet step. Anyway we will look into each of them.</p>
<h2 id="heading-taskletstep">TaskletStep</h2>
<p>The Tasklet step is a straightforward step that calls the Tasklet's execute method. The Tasklet is a functional interface with an execute method that the developer must implement. Spring Batch will automatically call the Tasklet's execute method repeatedly until it returns a finished status. By default, Spring Batch runs the Tasklet step inside a transaction, ensuring data integrity and consistency. The Tasklet allows us to implement everything from reading to writing, including fault tolerance mechanisms like retry and skip.</p>
<p>The most famous implementation of the Tasklet is the chunk-oriented Tasklet, which will read, process, and write the data in chunks, which is very neat when it comes to processing huge amounts of data. Only for the chunk-oriented step does Spring Batch provide various components like fault tolerance mechanisms such as retry, skip, and restart ability. Even parallel processing mechanisms are only available for the chunk-oriented step. <em>We will look into this step in detail in future blogs.</em></p>
<h2 id="heading-partition-step">Partition Step</h2>
<p>The partitioning step divides data into different parts based on specific criteria. It's like cutting a pizza into slices, where each slice is a partition. The criteria are set by the partition handler. Partitioning is done according to the criteria you provide. By default, Spring Batch offers only one implementation out of the box.</p>
<h2 id="heading-flow-step">Flow Step</h2>
<p>The flow step is used to define the order in which steps should be executed. It allows for conditional execution of steps. For example, if the first step is completed successfully, the next step can be executed. If the first step fails, you can skip the second step and execute the third one instead. This can be managed using the flow step.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Bean</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> Job <span class="hljs-title">conditionalJob</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> jobBuilderFactory.get(<span class="hljs-string">"conditionalJob"</span>)
        .start(step1())
        .on(<span class="hljs-string">"COMPLETED"</span>)
        .to(step2()) <span class="hljs-comment">// If step1 succeeds, go to step2</span>
        .from(step1())
        .on(<span class="hljs-string">"FAILED"</span>)
        .to(step3()) <span class="hljs-comment">// If step1 fails, go to step3</span>
        .end() <span class="hljs-comment">// End the job</span>
        .build();
}
</code></pre>
<h2 id="heading-jobstep">JobStep</h2>
<p>It is a step that calls another job to execute. You can have multiple job definitions, and one job can have a step that calls another job. We will look into it in future blogs for now it is all you need to know.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Bean</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> Step <span class="hljs-title">childStep</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> StepBuilder(<span class="hljs-string">"childStep"</span>, jobRepository)
        .tasklet(
            (contribution, chunkContext)
                -&gt; {
                System.out.println(<span class="hljs-string">"Executing Child Job Step"</span>);
                <span class="hljs-keyword">return</span> RepeatStatus.FINISHED;
            },
            transactionManager)
        .build();
}

<span class="hljs-meta">@Bean</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> Job <span class="hljs-title">childJob</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> JobBuilder(<span class="hljs-string">"childJob"</span>, jobRepository)
                         .start(childStep())
                         .build();
}

<span class="hljs-comment">// Parent Job: Includes a JobStep to execute the child job</span>
<span class="hljs-meta">@Bean</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> Step <span class="hljs-title">parentStep</span><span class="hljs-params">(Job childJob, JobLauncher jobLauncher)</span> </span>{
    JobStep jobStep = <span class="hljs-keyword">new</span> JobStep();
    jobStep.setJobLauncher(jobLauncher);
    jobStep.setName(<span class="hljs-string">"parentStepExecutingChildJob"</span>);
    <span class="hljs-keyword">return</span> jobStep;
}

<span class="hljs-meta">@Bean</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> Job <span class="hljs-title">parentJob</span><span class="hljs-params">(Step parentStep)</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> JobBuilder(<span class="hljs-string">"parentJob"</span>, jobRepository)
                          .start(parentStep)
                          .build();
}
</code></pre>
<h1 id="heading-basic-job-flow">Basic Job Flow</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744214478175/86583b39-1b60-44da-ada3-476941818912.png" alt class="image--center mx-auto" /></p>
<p>The <strong>JobLauncher</strong> will start the job. Before it begins, a new row will be created in the <code>Job_Instance</code> table if it is a new job, and the job parameters will be added to the <code>Job_Execution_Params</code> table. Then, the <strong>Job</strong> execution will start, and a new row will be added to the <code>Job_Execution</code> table. The job doesn't need to be unique; for every job run, a new row will be added to the <code>Job_Execution</code> table. The job will call the <strong>Step</strong>, and a new row will be added to the <code>Step_Execution</code> table. Then, the step will execute the tasklet, and so on.</p>
<h1 id="heading-launching-a-job">Launching a Job</h1>
<p>There are several ways to launch a job, and we'll explore all of them in this section. Each method is used in different scenarios based on your purpose.</p>
<h2 id="heading-automatic-job-launch-on-startup">Automatic Job Launch on Startup</h2>
<p>If we have only one job definition, we can configure Spring Batch to launch it on startup. However, if there are multiple job definitions, this approach can cause issues, so it's better not to use it. To enable this, simply set the property to <code>true</code> in <code>application.properties</code> or <code>application.yml</code>.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">spring:</span>
  <span class="hljs-attr">batch:</span>
    <span class="hljs-attr">job:</span>
      <span class="hljs-attr">enabled:</span> <span class="hljs-literal">true</span>
</code></pre>
<p>If you have multiple job definitions then you can provide the name of the job you want to run on startup in <code>application.properties</code> or <code>application.yml</code> as below.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">spring:</span>
  <span class="hljs-attr">batch:</span>
    <span class="hljs-attr">job:</span>
      <span class="hljs-attr">enabled:</span> <span class="hljs-literal">true</span>
      <span class="hljs-attr">name:</span> <span class="hljs-string">newsletter-job</span>
</code></pre>
<h2 id="heading-using-commandlinerunner">Using CommandLineRunner</h2>
<p>It’s a good option if you want to run the job using the command line or a command. For this approach to work you have to know which class you have added the job configuration as you have to pass it to the <code>CommandLineRunner</code>.</p>
<pre><code class="lang-bash">$ java CommandLineJobRunner in.akashrchandran.nbt.config.BatchConfig
</code></pre>
<h2 id="heading-using-joblauncher">Using JobLauncher</h2>
<p>There might be a need to run a Job based on our needs like we need to schedule it using the Quartz or trigger run when we get an API request etc. Then we can’t set it to run on startup or use the command line to run, the solution here is to use the Job launcher interface. You can autowire it using the spring dependency injection.</p>
<pre><code class="lang-java">jobLauncher.run(job, <span class="hljs-keyword">new</span> JobParameters());
</code></pre>
<p>You can use the JobLauncher anywhere and run the job based on your needs. I will show an example of running the job from a web container.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Controller</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">JobLauncherController</span> </span>{

    <span class="hljs-meta">@Autowired</span>
    JobLauncher jobLauncher;

    <span class="hljs-meta">@Autowired</span>
    Job job;

    <span class="hljs-meta">@PostMapping("/jobLauncher")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">handle</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception </span>{
        jobLauncher.run(job, <span class="hljs-keyword">new</span> JobParameters());
    }
}
</code></pre>
<h1 id="heading-code-example">Code Example</h1>
<p>We won't stop with just the basics. Let's try to apply what we've learned and create a simple application that sends newsletters. There will be a text file containing some random email IDs. Since the application is simple, we will implement it using the Tasklet we discussed earlier.</p>
<p>I will be using IntelliJ Ultimate IDE to code this project. However, you can use any IDE you like, such as Vscode, Vim, or even Notepad. It’s your choice.</p>
<h2 id="heading-getting-the-dependencies">Getting the dependencies</h2>
<p>Head over to the <a target="_blank" href="https://start.spring.io/">Spring Initializer</a> to get the dependencies for our application. We will require the dependencies I have selected below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744459860840/c7fa9add-4aff-4b9b-b832-df93389b2fda.png" alt class="image--center mx-auto" /></p>
<p>Let me clarify the dependencies needed. We require Spring Batch, of course. The Java Mail Sender is for sending emails, and H2 is for the in-memory database because I don't want to set up an external database for this simple project. I don't recommend using H2 in production. You should provide a database for the <code>JobRepository</code>. It can be almost any database provider, like MySQL, PostgreSQL, or even MongoDB.</p>
<p>Download the zip file and load it into your IDE, and then we can start coding.</p>
<h2 id="heading-creating-a-batchconfig-class">Creating a BatchConfig class</h2>
<p>We'll start by creating a class <code>BatchConfig</code> to store all the configurations for our batch process, including the Job and Step definitions. There is no need to keep the same name it’s just your choice. You have to annotate the class, to let the spring know that the class contains the configurations for our batch process.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Configuration</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BatchConfig</span> </span>{
<span class="hljs-comment">// Batch config</span>
}
</code></pre>
<ol>
<li><h3 id="heading-defining-the-job">Defining the Job</h3>
</li>
</ol>
<p>From what we've learned, we know we need to define the entire batch process as a <code>Job</code>. The job definition is simple since we will only have one step, which is sending the emails.</p>
<pre><code class="lang-java">    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Job <span class="hljs-title">newsletterJob</span><span class="hljs-params">(JobRepository jobRepository, Step step)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> JobBuilder(<span class="hljs-string">"newsletter-job"</span>, jobRepository)
                .start(step)
                .build();
    }
</code></pre>
<p>Since it is a Spring bean, the parameters will be autowired for us, that's the magic of Spring. I won't explain that here, so let's move on to the next part.</p>
<ol start="2">
<li><h3 id="heading-defining-the-step">Defining the Step</h3>
</li>
</ol>
<p>Next, we need to define the step and pass the tasklet, which we will write shortly, to execute.</p>
<pre><code class="lang-java">    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Step <span class="hljs-title">newsletterStep</span><span class="hljs-params">(JobRepository jobRepository,
                               PlatformTransactionManager transactionManager,
                               Tasklet tasklet)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> StepBuilder(<span class="hljs-string">"newsletter-step"</span>, jobRepository)
                .tasklet(tasklet, transactionManager)
                .build();
    }
</code></pre>
<p>As we have only a single tasklet we are going to define, we can autowire that as well.</p>
<p><strong><em>You can view the entire class code on GitHub, here is the</em></strong> <a target="_blank" href="https://github.com/akashrchandran/spring-batch-session/blob/ca6d65f5598981df538cebeec89f8155267434c4/tasklet/newsletter-batch-tasklet-async/src/main/java/in/akashrchandran/nbt/config/BatchConfig.java#L16-L30"><strong><em>link</em></strong></a><strong><em>.</em></strong></p>
<h2 id="heading-configuration-for-sending-emails">Configuration for Sending Emails</h2>
<p>Java Mail Sender needs some setup before you can send emails, like your email address and password. I'll be using Gmail to send my emails, but you can use any other service.</p>
<p>For Gmail, you need to get an App Password. You can't use your regular Google account password for security reasons, so you will need to generate one. I'll provide a link to an article on how to obtain the App Password.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.getmailbird.com/gmail-app-password/">https://www.getmailbird.com/gmail-app-password/</a></div>
<p> </p>
<p>Now we have to add some properties to <code>application.properties</code> or <code>application.yml</code> whichever you use. I prefer the YAML file. So I will show that only, you can just use the same property keys <code>application.properties</code> and it should work.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">spring:</span>
  <span class="hljs-attr">application:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">newsletter-batch-tasklet-async</span>
  <span class="hljs-attr">mail:</span>
    <span class="hljs-attr">properties:</span>
      <span class="hljs-attr">mail:</span>
        <span class="hljs-attr">smtp:</span>
          <span class="hljs-attr">auth:</span> <span class="hljs-literal">true</span>
          <span class="hljs-attr">starttls:</span>
            <span class="hljs-attr">enable:</span> <span class="hljs-literal">true</span>
    <span class="hljs-attr">host:</span> <span class="hljs-string">smtp.gmail.com</span>
    <span class="hljs-attr">port:</span> <span class="hljs-number">587</span>
    <span class="hljs-attr">username:</span> <span class="hljs-string">${SPRING_MAIL_USERNAME}</span>
    <span class="hljs-attr">password:</span> <span class="hljs-string">${SPRING_MAIL_PASSWORD}</span>
</code></pre>
<p>The <code>${SPRING_MAIL_USERNAME}</code> and <code>${SPRING_MAIL_PASSWORD}</code> are used here to get the values from the Environment Variables. You can set the environment variables. You can set the environment variables based on your operating system</p>
<pre><code class="lang-bash"><span class="hljs-comment"># unix or linux based system</span>
$ <span class="hljs-built_in">export</span> SPRING_MAIL_USERNAME=example@example.com

<span class="hljs-comment"># windows command prompt</span>
$ <span class="hljs-built_in">set</span> SPRING_MAIL_USERNAME=example@example.com

<span class="hljs-comment"># windows poweshell</span>
&gt; <span class="hljs-variable">$env</span>:SPRING_MAIL_USERNAME = <span class="hljs-string">"example.org"</span>
</code></pre>
<p>If you're using the IntelliJ IDE, you can set the environment variables in the Run Configurations.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744474547644/2fe0a21c-f531-47f6-a967-be57a5e1761b.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-creating-the-tasklet">Creating the Tasklet</h2>
<p>To create a Tasklet step, we need to implement the Tasklet interface provided by Spring Batch. First, we will create a class named <code>NewsletterTasklet</code> and make it implement the Tasklet interface. After that, you will likely see an error indicating that you need to implement the methods of that interface, specifically the <code>execute()</code> method.</p>
<p>We need to annotate the class <code>@Component</code> to inform Spring that it is a Spring bean. Additionally, we will autowire <code>JavaMailSender</code> to send the mail. This <code>recipientsFilePath</code> is the path of the file that contains the emails. Using the <code>@Value</code> annotation so that we can define the values in the <code>application.properties</code> or <code>applciation.yml</code>.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Component</span>
<span class="hljs-meta">@RequiredArgsConstructor</span>
<span class="hljs-meta">@Slf4j</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NewsletterTasklet</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Tasklet</span> </span>{
    <span class="hljs-meta">@Value("${newsletter.recipients.file}")</span>
    <span class="hljs-keyword">private</span> String recipientsFilePath;

    <span class="hljs-meta">@Value("${newsletter.max.concurrent:10}")</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> maxConcurrent;

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> JavaMailSender mailSender;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> RepeatStatus <span class="hljs-title">execute</span><span class="hljs-params">(StepContribution contribution, ChunkContext chunkContext)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        <span class="hljs-comment">// custom code to send the newsletter</span>
    }
}
</code></pre>
<ol>
<li><h3 id="heading-reading-emails-from-a-text-file">Reading emails from a text file</h3>
</li>
</ol>
<p>We will be reading the emails from a text file named <code>spam.txt</code> which I have already kept in the resource folder. So we need to define a method which reads the text file splits the lines and returns the emails as a list. We can just define a private method for the same.</p>
<pre><code class="lang-java">    <span class="hljs-function"><span class="hljs-keyword">private</span> List&lt;String&gt; <span class="hljs-title">readRecipientsFromFile</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">try</span> {
            Resource resource = <span class="hljs-keyword">new</span> ClassPathResource(recipientsFilePath);
            <span class="hljs-keyword">if</span> (resource.exists()) {
                <span class="hljs-keyword">try</span> (Stream&lt;String&gt; lines = <span class="hljs-keyword">new</span> BufferedReader(
                        <span class="hljs-keyword">new</span> InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8))
                        .lines()) {
                    log.info(<span class="hljs-string">"Successfully loaded recipients from resources: {}"</span>, recipientsFilePath);
                    <span class="hljs-keyword">return</span> lines.filter(line -&gt; line != <span class="hljs-keyword">null</span> &amp;&amp; !line.isBlank())
                            .toList();
                }
            } <span class="hljs-keyword">else</span> {
                log.warn(<span class="hljs-string">"Resource file '{}' does not exist"</span>, recipientsFilePath);
            }
        } <span class="hljs-keyword">catch</span> (Exception e) {
            log.error(<span class="hljs-string">"Error reading recipients from file '{}': {}"</span>, recipientsFilePath, e.getMessage(), e);
        }
        <span class="hljs-keyword">return</span> Collections.emptyList();
    }
</code></pre>
<ol start="2">
<li><h3 id="heading-sending-an-email-to-the-email-id">Sending an email to the email ID</h3>
</li>
</ol>
<p>Then we need a method to send email to the email ID we passed. We can create another private function for that as well.</p>
<pre><code class="lang-java">    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sendEmail</span><span class="hljs-params">(String to)</span> </span>{
        SimpleMailMessage message = <span class="hljs-keyword">new</span> SimpleMailMessage();
        message.setFrom(<span class="hljs-string">"yourEmail@domain.com"</span>);
        message.setTo(to);
        message.setSubject(<span class="hljs-string">"Newsletter"</span>);
        message.setText(<span class="hljs-string">"This is the content of the newsletter."</span>);
        mailSender.send(message);
        log.info(<span class="hljs-string">"Email sent successfully to {}"</span>, to);
    }
</code></pre>
<ol start="3">
<li><h3 id="heading-implementing-asynchronous-email-sending">Implementing Asynchronous Email Sending</h3>
</li>
</ol>
<p>Finally, we need to code the execute method which will use the above techniques to read and send emails. We use the <code>ExecutorService</code> to call the send email function asynchronously. We can use many threads to send the message but it is always to limit the number of threads that are concurrently executing. We can do something like this</p>
<pre><code class="lang-java"><span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> RepeatStatus <span class="hljs-title">execute</span><span class="hljs-params">(
    StepContribution contribution, ChunkContext chunkContext)</span> <span class="hljs-keyword">throws</span> Exception </span>{
    log.info(<span class="hljs-string">"Starting NewsletterTasklet execution with async processing."</span>);
    List&lt;String&gt; recipients = readRecipientsFromFile();
    <span class="hljs-keyword">int</span> totalRecipients = recipients.size();
    ExecutorService executor = Executors.newFixedThreadPool(maxConcurrent);
    List&lt;CompletableFuture&lt;Void&gt;&gt; allFutures = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    <span class="hljs-comment">// Create async tasks for all recipients</span>
    <span class="hljs-keyword">for</span> (String recipient : recipients) {
        CompletableFuture&lt;Void&gt; future = CompletableFuture.runAsync(() -&gt; {
            <span class="hljs-keyword">try</span> {
                sendEmail(recipient);
            } <span class="hljs-keyword">catch</span> (Exception e) {
                log.error(<span class="hljs-string">"Failed to send email to {}: {}"</span>, recipient,
                    e.getMessage(), e);
            }
        }, executor);
        allFutures.add(future);
    }
    CompletableFuture.allOf(allFutures.toArray(<span class="hljs-keyword">new</span> CompletableFuture[<span class="hljs-number">0</span>])).join();
    executor.shutdown();
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">if</span> (!executor.awaitTermination(<span class="hljs-number">30</span>, TimeUnit.SECONDS)) {
            executor.shutdownNow();
        }
    } <span class="hljs-keyword">catch</span> (InterruptedException e) {
        executor.shutdownNow();
        Thread.currentThread().interrupt();
    }

    log.info(<span class="hljs-string">"Finished NewsletterTasklet execution. Total emails sent: {}"</span>, totalRecipients);
    <span class="hljs-keyword">return</span> RepeatStatus.FINISHED;
}
</code></pre>
<h2 id="heading-executing-the-batch-process">Executing the batch process</h2>
<p>I have listed about 10 emails in my spam.txt file. In a real scenario, you would read these from a user database, but this example is simpler. Before executing the batch process we need to add some more properties to the <code>application.yml</code>.</p>
<p>I will be showing the job running on application startup. You can use any way to run the job, as I have shown in the launching the jobs part.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">spring:</span>
  <span class="hljs-attr">batch:</span>
    <span class="hljs-attr">jdbc:</span>
      <span class="hljs-attr">initialize-schema:</span> <span class="hljs-string">always</span> <span class="hljs-comment"># to create job repository tables.</span>
    <span class="hljs-attr">job:</span>
      <span class="hljs-attr">enabled:</span> <span class="hljs-literal">true</span> <span class="hljs-comment"># to run the job on applcaiiton startup.</span>

<span class="hljs-attr">newsletter:</span>
  <span class="hljs-attr">recipients:</span>
    <span class="hljs-attr">file:</span> <span class="hljs-string">spam.txt</span> <span class="hljs-comment"># file name which contains the emails.</span>
  <span class="hljs-attr">max:</span>
    <span class="hljs-attr">concurrent:</span> <span class="hljs-number">5</span> <span class="hljs-comment"># limiting the number of concurrent threads.</span>
</code></pre>
<p>Now we can simply run the application. Ensure you have added the environment variables; otherwise, the application will display an error.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744535177358/a3d97c85-0da5-45c2-a284-b70a1cf58dca.gif" alt class="image--center mx-auto" /></p>
<p>As you can see the emails have been sent successfully within 17 seconds. I could have increased the concurrent thread count and may have gotten better results but that is not what this blog is about.</p>
<p><strong>You can view the entire code on my Github repository.</strong></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/akashrchandran/spring-batch-session/tree/main/tasklet/newsletter-batch-tasklet-async">https://github.com/akashrchandran/spring-batch-session/tree/main/tasklet/newsletter-batch-tasklet-async</a></div>
]]></content:encoded></item><item><title><![CDATA[Deep Dive into the Concepts of Luigi]]></title><description><![CDATA[I have been working on the batch processing aspects lately, and I found many topics on this idea. One of the ways was to use Luigi, a Spotify maintained project. The main problem is that there aren't many good blogs about how to implement batch proce...]]></description><link>https://blog.akashrchandran.in/deep-dive-into-the-concepts-of-luigi</link><guid isPermaLink="true">https://blog.akashrchandran.in/deep-dive-into-the-concepts-of-luigi</guid><category><![CDATA[luigi]]></category><category><![CDATA[Batch Processing]]></category><category><![CDATA[Spotify]]></category><category><![CDATA[workflow-orchestration]]></category><category><![CDATA[Concepts]]></category><dc:creator><![CDATA[Akash R Chandran]]></dc:creator><pubDate>Fri, 14 Mar 2025 05:00:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741890739976/1fff342b-0e29-4f9f-a744-afbe74b248c7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have been working on the batch processing aspects lately, and I found many topics on this idea. One of the ways was to use Luigi, a Spotify maintained project. The main problem is that there aren't many good blogs about how to implement batch processing in a simple and easy-to-understand way. So, I thought, why not write one myself that can be helpful for many people out there? Let's buckle up for a ride through Luigi, a workflow orchestration tool. We won't be seeing every feature it has, but we will be looking into the main feature, which is batch processing. I won’t be showing how to implement a batch process in Luigi for now let’s focus on the concepts and features. We will be doing that in the next blog😉.</p>
<h1 id="heading-what-is-luigi">What is Luigi?</h1>
<p>It's a Python-based batch processing framework built and maintained by Spotify. You can check out their <a target="_blank" href="https://github.com/spotify/luigi">GitHub repo</a>. They use it for their workflows, which led to its development and adoption by many companies. It was mainly used to automate the tasks involved in their music streaming service and build reproducible processes. It's open-sourced by Spotify, so you can contribute to it as well. Luigi is a workflow orchestration framework, meaning it gives you full control over the batch process, including a nice dashboard to view and control the tasks. There are many more features available in this; let’s first check the architecture of Luigi.</p>
<h1 id="heading-architecture">Architecture</h1>
<p>There are some essential architectural designs and concepts everyone should know about before using Luigi. Let’s discuss a few of the main topics here.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741788886267/e86ed60d-8df8-450d-abb5-a700de13a4b7.png" alt="Architecture diagram of the luigi" class="image--center mx-auto" /></p>
<p>This is a simple flow showing how the Luigi architecture looks. Luigi is a workflow orchestration framework, which means it runs as a central server that manages all the client or local servers. There are two tasks for the central server:</p>
<ul>
<li><p>Ensure that two instances of the same task are not running simultaneously.</p>
</li>
<li><p>Show a visualization of the tasks being run.</p>
</li>
</ul>
<p>There is also a web interface to manage and schedule the job that you want to run.</p>
<h2 id="heading-tasks">Tasks</h2>
<p>Tasks are the basic building blocks in Luigi. The important thing is that they are defined as Python classes that inherit from <code>Luigi.Task</code>. They encapsulate the logic for a specific job and include three essential methods:</p>
<ul>
<li><p><code>requires()</code>: Specifies dependencies on other tasks, ensuring they are executed before the current task.</p>
</li>
<li><p><code>run()</code>: Contains the code to execute the task, defining the business logic or operations performed.</p>
</li>
<li><p><code>output()</code>: Returns one or more target objects, representing the task's output, which is typically a file or database entry.</p>
</li>
</ul>
<p>Here’s a <strong>Luigi</strong> example that demonstrates a simple <strong>ETL pipeline</strong>.</p>
<p>We have a pipeline that:</p>
<ol>
<li><p><strong>Extracts</strong> data from a text file.</p>
</li>
<li><p><strong>Transforms</strong> the data by converting all text to uppercase.</p>
</li>
<li><p><strong>Loads</strong> the transformed data into a final output file.</p>
</li>
</ol>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="36911e11cdb243c4a70356901f66fe1f"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/akashrchandran/36911e11cdb243c4a70356901f66fe1f" class="embed-card">https://gist.github.com/akashrchandran/36911e11cdb243c4a70356901f66fe1f</a></div><p> </p>
<p>In this Luigi pipeline, each step is a <strong>task</strong>, which is a piece of work that depends on other tasks. The first task, <code>ExtractData</code>, creates a text file (<code>extracted_data.txt</code>) with a list of sample words. The second task, <code>TransformData</code>, depends on <code>ExtractData</code>, so it runs only after the first task is done. It reads the file, changes all words to uppercase, and saves them in <code>transformed_data.txt</code>. The third task, <code>LoadData</code>, depends on <code>TransformData</code> and waits for it to finish before it runs. It reads the transformed file, adds "Loaded:" to each word, and writes the result to <code>final_data.txt</code>. Luigi uses the <code>requires()</code> method to manage dependencies, making sure tasks run in the right order. The <code>output()</code> method shows where each task's result will be saved, and the <code>run()</code> method has the actual steps to process the data. Running the script with <a target="_blank" href="http://luigi.build"><code>luigi.build</code></a><code>([LoadData()], local_scheduler=True)</code> starts the whole pipeline, running tasks one after the other while keeping their dependencies in check.</p>
<h2 id="heading-targets">Targets</h2>
<p>A <strong>target</strong> in Luigi represents the output of a task and acts as a checkpoint to determine if the task needs to run. Before executing a task, Luigi checks whether the target already exists. If it does, Luigi <strong>skips</strong> the task, assuming it has been completed successfully. This prevents unnecessary recomputation and makes pipelines more <strong>efficient and fault-tolerant</strong>.</p>
<p><strong>Types of Targets in Luigi</strong></p>
<ol>
<li><p><strong>LocalTarget</strong> – Used for files stored locally.</p>
</li>
<li><p><strong>S3Target</strong> – Stores data in Amazon S3.</p>
</li>
<li><p><strong>GCSFileSystemTarget</strong> – Saves files in Google Cloud Storage.</p>
</li>
<li><p><strong>PostgresTarget / MySqlTarget</strong> – Used for database records.</p>
</li>
</ol>
<p>The example is shown in task section.</p>
<h2 id="heading-dependencies">Dependencies</h2>
<p>In Luigi, <strong>dependencies</strong> define the relationships between tasks in a data pipeline. They ensure that each task runs <strong>only after its required tasks are completed</strong>, maintaining the correct execution order. This helps streamline workflows, prevent errors from out-of-order execution, and ensure data consistency.</p>
<p><strong>How Dependencies Work</strong></p>
<p>Dependencies are defined using the <code>requires()</code> method in a Luigi task. A task lists its required tasks, and Luigi automatically ensures that those tasks are completed before running the dependent task.</p>
<h2 id="heading-dependency-graph">Dependency Graph</h2>
<p>In Luigi, <strong>dependency graphs</strong> visually represent the relationships between tasks in a pipeline. They help in understanding task execution order, identifying bottlenecks, and debugging failures.</p>
<h3 id="heading-how-luigi-builds-dependency-graphs"><strong>How Luigi Builds Dependency Graphs</strong></h3>
<p>Each <strong>Luigi task</strong> defines dependencies using the <code>requires()</code> method. When a pipeline runs, Luigi constructs a <strong>Directed Acyclic Graph (DAG)</strong> where:</p>
<ul>
<li><p><strong>Nodes</strong> represent tasks.</p>
</li>
<li><p><strong>Edges</strong> represent dependencies.</p>
</li>
</ul>
<p>Luigi ensures that each task executes <strong>only after</strong> all its dependencies are completed.</p>
<p><img src="https://assets.digitalocean.com/articles/luigi-python/step7b.png" alt="Example visualization of dependency graph in luigi" /></p>
<h2 id="heading-scheduling">Scheduling</h2>
<p>Luigi provides flexible scheduling options to automate workflow execution. Tasks can be run <strong>manually</strong>, <strong>on a schedule</strong>, or <strong>triggered by dependencies</strong>.</p>
<ol>
<li><h4 id="heading-running-tasks-manually">Running Tasks Manually</h4>
<p> You can execute a Luigi task manually using the command line:</p>
</li>
</ol>
<pre><code class="lang-bash">luigi --module my_tasks TaskName --local-scheduler
</code></pre>
<p>This runs the task immediately without relying on the central scheduler.</p>
<ol start="2">
<li><h4 id="heading-using-luigid-for-centralized-scheduling">Using <code>luigid</code> for Centralized Scheduling</h4>
<p> For managing large workflows, Luigi offers a <strong>central scheduler</strong> (<code>luigid</code>). It tracks task status and ensures dependencies run in the correct order. Start the scheduler with:</p>
</li>
</ol>
<pre><code class="lang-bash">luigid --background
</code></pre>
<p>Then, run tasks using:</p>
<pre><code class="lang-bash">luigi --module my_tasks TaskName --scheduler-host localhost
</code></pre>
<p>This enables <strong>centralized monitoring</strong> and <strong>parallel execution</strong> of tasks.</p>
<ol start="3">
<li><p>Automating with Cron Jobs</p>
<p> Luigi does not have a built-in scheduler like Apache Airflow but can be integrated with <strong>cron jobs</strong> for periodic execution. Example cron entry for running a Luigi task every day at midnight:</p>
</li>
</ol>
<pre><code class="lang-bash">0 0 * * * luigi --module my_tasks TaskName --scheduler-host localhost
</code></pre>
<h1 id="heading-features-of-luigi">Features of Luigi</h1>
<p>Luigi is a Python-based workflow management system designed to build and automate complex data pipelines. It ensures tasks run in the correct order and handles dependencies efficiently. Here are some of its key features:</p>
<ol>
<li><p><strong>Task Dependency Management</strong><br /> Luigi automatically tracks and resolves dependencies between tasks using a Directed Acyclic Graph (DAG). This ensures that each task runs only when its dependencies are met.</p>
</li>
<li><p><strong>Automatic Checkpoints with Targets</strong><br /> Each task in Luigi produces an output target (like a file or database entry). If a target exists, Luigi skips re-execution, preventing redundant processing and improving efficiency.</p>
</li>
<li><p><strong>Built-in Scheduler &amp; Worker System</strong><br /> Luigi comes with a central scheduler (<code>luigid</code>) that allows tasks to be monitored, retried, and executed in parallel using workers. This makes it great for handling large-scale data pipelines.</p>
</li>
<li><p><strong>Scalability &amp; Parallel Execution</strong><br /> Luigi can run tasks in parallel using multiple workers, making it ideal for big data processing and distributed computing.</p>
</li>
<li><p><strong>Integration with Various Storage &amp; Compute Systems</strong><br /> Luigi supports multiple storage and database systems, including:</p>
<ul>
<li><p>Local file system (<code>LocalTarget</code>)</p>
</li>
<li><p>Amazon S3 (<code>S3Target</code>)</p>
</li>
<li><p>Google Cloud Storage (<code>GCSFileSystemTarget</code>)</p>
</li>
<li><p>Hadoop &amp; HDFS (<code>HdfsTarget</code>)</p>
</li>
<li><p>Databases like MySQL &amp; PostgreSQL (<code>PostgresTarget</code>, <code>MySqlTarget</code>)</p>
</li>
</ul>
</li>
<li><p><strong>Visualization &amp; Monitoring</strong><br /> Luigi provides a web-based UI that allows users to monitor running jobs, view logs, and visualize task dependencies. Run the scheduler with:</p>
<pre><code class="lang-bash"> luigid --background
</code></pre>
<p> and access the UI at <a target="_blank" href="http://localhost:8082">http://localhost:8082</a>.</p>
</li>
<li><p><strong>Fault Tolerance &amp; Retry Mechanism</strong><br /> Luigi automatically retries failed tasks and provides logging to help diagnose errors. This ensures robustness in long-running workflows.</p>
</li>
<li><p><strong>Extensibility &amp; Customization</strong><br /> Luigi allows you to create custom targets, parameterized tasks, and extend existing functionality, making it highly adaptable to different data engineering needs.</p>
</li>
<li><p><strong>Support for Incremental Processing</strong><br /> By using checkpoints (targets), Luigi only processes new or changed data, reducing computational overhead for large datasets.</p>
</li>
</ol>
<h1 id="heading-problems-with-luigi">Problems with Luigi</h1>
<ol>
<li><p><strong>No Native Support for Real-Time Streaming</strong></p>
<p> Luigi is designed for batch processing, meaning it lacks support for real-time or event-driven workflows. If you need real-time data processing, tools like Apache Airflow, Apache Kafka, or Flink may be better suited.</p>
</li>
<li><p><strong>Requires Manual Error Handling &amp; Retries</strong></p>
<p> While Luigi provides a retry mechanism, it does not handle failures automatically as efficiently as some other orchestration tools. You must explicitly define retry logic in your tasks to avoid failures stopping the entire pipeline.</p>
</li>
<li><p><strong>Limited Support for Dynamic Workflows</strong></p>
<p> Luigi workflows are static, meaning the dependency graph is defined before execution. Dynamically adding tasks at runtime is difficult compared to Apache Airflow, which supports dynamic DAG creation using Python scripts.</p>
</li>
<li><p><strong>Web UI is Basic &amp; Lacks Advanced Features</strong></p>
<p> The Luigi web UI is minimalistic and does not provide detailed logs, alerting, or advanced visualization. Other tools like Airflow offer more interactive UIs with better monitoring capabilities.</p>
</li>
<li><p><strong>Dependency Management Can Get Complex</strong></p>
<p> Large DAGs with many dependencies can become hard to manage. Unlike Airflow, Luigi does not provide a built-in way to visualize complex DAGs dynamically.</p>
</li>
<li><p><strong>Limited Community &amp; Ecosystem</strong></p>
<p> Smaller community compared to Apache Airflow, Prefect. Fewer pre-built integrations for third-party services, requiring custom implementations for many use cases.</p>
</li>
<li><p><strong>Higher Resource Usage Due to Process-Based Execution</strong></p>
<p> Luigi uses processes instead of threads for task execution, which can be more resource intensive. This approach may lead to higher memory and CPU usage compared to threading, which is more lightweight.</p>
</li>
</ol>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Luigi is a Python-based workflow management system developed by Spotify. The Spotify team had stopped development of the Luigi, and it didn’t get many fixes for a year. But now it has been actively maintained. Although, the Spotify has stopped using it you can find the detailed blog <a target="_blank" href="https://engineering.atspotify.com/2022/03/why-we-switched-our-data-orchestration-service/">here</a>.</p>
<p>I personally believe Luigi can be useful for small to medium-scale tasks. There are many frameworks and options available, and Luigi may not have a large community like Spring Batch. However, with each fix, Luigi is improving and will continue to get better over time. The main thing for me is that it is the simplest library for batch processing in Python, which is a language used by many beginners.</p>
<p>For large-scale tasks, you might consider using more robust options like Apache Flink or Apache Spark, which are designed to handle big data processing efficiently. If you prefer a lighter solution, Spring Batch could be a good choice, as it offers a more streamlined approach without being too resource-intensive. These alternatives provide greater scalability and performance for handling complex workflows and data processing needs.</p>
<h1 id="heading-references">References</h1>
<ul>
<li><p><a target="_blank" href="https://luigi.readthedocs.io/en/stable/design_and_limitations.html">Luigi Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://atlan.com/luigi-data-orchestration/#what-is-luigi">Luigi for Data Orchestration: Building Blocks, Capabilities, Setup</a></p>
</li>
<li><p><a target="_blank" href="https://airbyte.com/data-engineering-resources/luigi-python-data-pipeline">How to Build a Data Orchestration Pipeline Using Luigi in Python? | Airbyte</a></p>
</li>
<li><p><a target="_blank" href="https://www.digitalocean.com/community/tutorials/how-to-build-a-data-processing-pipeline-using-luigi-in-python-on-ubuntu-20-04">How To Build a Data Processing Pipeline Using Luigi in Python on Ubuntu 20.04 | DigitalOcean</a></p>
</li>
<li><p><a target="_blank" href="https://arxiv.org/abs/2402.17949?utm_source=chatgpt.com">End-to-End Analysis Automation over Distributed Resources with Luigi Analysis Workflows</a></p>
</li>
<li><p><a target="_blank" href="https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/dags.html">DAGs — Airflow Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://spring.io/batch">Spring | Batch</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to Add Loading Skeletons to React App Using Chakra UI]]></title><description><![CDATA[A while ago I was working on a project GamesDrive and built it using React + TypeScript and using Chakra UI. I was required to get information from the API and wait for its response and then process it and show it to the user. If they have a slow net...]]></description><link>https://blog.akashrchandran.in/how-to-add-loading-skeletons-to-react-app-using-chakra-ui</link><guid isPermaLink="true">https://blog.akashrchandran.in/how-to-add-loading-skeletons-to-react-app-using-chakra-ui</guid><category><![CDATA[React]]></category><category><![CDATA[vite]]></category><category><![CDATA[Chakra-ui]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[Akash R Chandran]]></dc:creator><pubDate>Tue, 06 Jun 2023 06:17:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1686020838726/9f4e918a-d62c-4baa-9d83-cb30e423bdcc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A while ago I was working on a project <a target="_blank" href="https://github.com/akashrchandran/gamesdrive">GamesDrive</a> and built it using React + TypeScript and using Chakra UI. I was required to get information from the API and wait for its response and then process it and show it to the user. If they have a slow network it would take forever to load and that would be a bad user experience. So I thought to add a loading spinner to the site and so I went to Chakra Documentation and saw something called Skeleton loading same as the loading animation on sites like Facebook and Linkedin. I was surprised to learn that you could create that animation using Chakra UI. It took me a while to figure out how to implement it on my website, but eventually, I was able to make it work. The Skeleton loading took my site's user experience to another level.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685685806674/b42d0602-6f6b-4aa3-83be-56a054952d3f.webp" alt class="image--center mx-auto" /></p>
<p>So here I am writing a blog about it, so you don't have to waste your precious time by searching and reading documentation <code>{ I hate it too }</code>. Let's not waste time and begin the tutorial.</p>
<h1 id="heading-initialize-your-react-project">Initialize Your React Project</h1>
<p>There are multiple ways you can create a react template. There are many tools available to do the same. I am going to use the same tools that I used for the project. So we are going to use React with TypeScript built using Vite.</p>
<h2 id="heading-creating-template-using-vite">Creating Template using Vite</h2>
<h3 id="heading-what-is-vite">what is Vite?</h3>
<p>Vite is a build tool that aims to provide a faster and leaner development experience for modern web projects. Vite is different as it was created by Evan You, who also created Vue.js, as a means to simplify and accelerate the build process. Vite leverages native ES modules in the browser to load your code instantly, no matter how large the app is. It also supports hot module replacement for an extremely fast development workflow.</p>
<h3 id="heading-setup-react-ts-using-vite">Setup React + TS using Vite</h3>
<p>You need to have Node JS version <code>14.18+, 16+</code>. I will be using NPM as my package manager. To get started open a folder in which you want to set up the project, I am going with <code>Documents</code> folder and paste the command below:</p>
<pre><code class="lang-bash">npm create vite@latest
</code></pre>
<p>You may be asked to install Vite if you don't have it already just press continue. It will ask for,</p>
<ul>
<li><p><strong>Project name</strong>: Give it any name you like, I prefer to give <code>skeleton-loading</code> as we trying to create skeleton-loading animation here.</p>
</li>
<li><p><strong>Framework</strong>: Choose React of course.</p>
</li>
<li><p><strong>Variant:</strong> For variant choose <em>TypeScript.</em></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685691574158/6fbeeea0-eed7-45c9-81ef-6d348136cdca.png" alt="Setup project using vite" class="image--center mx-auto" /></p>
<p>Now cd into the folder and install all the required packages. You can use the below commands,</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> skeleton-loading <span class="hljs-comment"># change this to your folder name</span>
 npm install
</code></pre>
<p>Installing packages may take some, depending mostly on your network speed. After installation, let's run the development server to check if everything is installed correctly. To run the development server use the command below,</p>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685692354056/96a3494c-aaaf-4ad7-8b9f-2b39bb0b5dc6.png" alt="Vite + React development server" class="image--center mx-auto" /></p>
<p>So we have successfully set up React and Vite, and now we have to install Chakra UI.</p>
<h1 id="heading-installing-chakra-ui">Installing Chakra UI</h1>
<p>They have a dedicated section in their documentation dealing installation of Chakra UI specifically for Vite, you can read it <a target="_blank" href="https://chakra-ui.com/getting-started/vite-guide">here</a>. As per the docs installation command is,</p>
<pre><code class="lang-bash">npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion
</code></pre>
<p>After installation open the project in your Favourite IDE, I am going with VS Code. And find <code>main.tsx</code> file, you can use <code>Ctrl + P</code> to search file in vs code.</p>
<p>And then wrap the <code>App</code> component with the <code>ChakraProvider</code> component. You have to import <code>ChakraProvider</code> component from the <code>import { ChakraProvider } from '@chakra-ui/react'</code>. The <code>main.tsx</code> file would look like this,</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> { ChakraProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App.tsx"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./index.css"</span>;

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>) <span class="hljs-keyword">as</span> HTMLElement).render(
  &lt;React.StrictMode&gt;
    &lt;ChakraProvider&gt;
      &lt;App /&gt;
    &lt;/ChakraProvider&gt;
  &lt;/React.StrictMode&gt;
);
</code></pre>
<p>You can delete the code inside the files <code>index.css</code> and <code>App.css</code> and also remove their import from the files <code>main.tsx</code> and <code>App.tsx</code>. As these styles may interfere with the styles provided by Chakra UI, so it's better to remove them.</p>
<p>Now setup for our Chakra UI is complete. To verify if our setup is complete we can try something like placing a button on our website. Go to <code>App.tsx</code> and remove all the code inside the <code>App</code> function or paste the below code after removing the entire code.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'@chakra-ui/react'</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    &lt;Button colorScheme=<span class="hljs-string">'blue'</span>&gt;Button&lt;/Button&gt;
  )
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App
</code></pre>
<p>Then start the development server using <code>npm run dev</code> command. And you should see something like this on the webpage.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685694381760/bbb30fc1-8723-4eef-97cc-e40cf8717478.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-lets-start-building">Let's start building!</h1>
<p>We don't want to build much of a UI, we just need to learn how to use the skeleton loading animation. This is pretty easy actually, so we directly make it. <strong>In Chakra UI,</strong> three types of skeleton components can be used to display loading states:</p>
<ul>
<li><p><a target="_blank" href="https://chakra-ui.com/docs/components/skeleton/usage#usage">Skeleton</a><strong>: The</strong> <code>Skeleton</code> component is the basic skeleton component in Chakra UI. It is used to create a loading placeholder for the content. It takes the height as a prop and displays a rectangular skeleton with the specified height. This component is useful when you want to display loading placeholders for multiple items or lines of text.</p>
<p>  Example usage:</p>
</li>
</ul>
<pre><code class="lang-typescript">&lt;Stack&gt;
&lt;Skeleton height=<span class="hljs-string">"20px"</span>/&gt;
&lt;Skeleton height=<span class="hljs-string">"20px"</span>/&gt;
&lt;/Stack&gt;
</code></pre>
<ul>
<li><a target="_blank" href="https://chakra-ui.com/docs/components/skeleton/usage#circle-and-text-skeleton"><strong>SkeletonCircle</strong></a><strong>: The</strong> <code>SkeletonCircle</code> component is used to create a circular loading placeholder. It takes the size props to specify the diameter of the circle. This component is often used to display loading placeholders for avatar images or circular icons. Example usage:</li>
</ul>
<pre><code class="lang-typescript">&lt;Box padding=<span class="hljs-string">'6'</span> boxShadow=<span class="hljs-string">'lg'</span> bg=<span class="hljs-string">'white'</span>&gt;
  &lt;SkeletonCircle size=<span class="hljs-string">'10'</span> /&gt;
  &lt;SkeletonText mt=<span class="hljs-string">'4'</span> noOfLines={<span class="hljs-number">4</span>} spacing=<span class="hljs-string">'4'</span> skeletonHeight=<span class="hljs-string">'2'</span> /&gt;
&lt;/Box&gt;
</code></pre>
<ul>
<li><a target="_blank" href="https://chakra-ui.com/docs/components/skeleton/usage#circle-and-text-skeleton"><strong>SkeletonText</strong></a>: The <code>SkeletonText</code> component is used to create a loading placeholder for text content. It takes props such as <code>mt</code> (margin-top), <code>noOfLines</code> (number of lines), <code>spacing</code> (line spacing), and <code>skeletonHeight</code> to define the appearance of the loading text. This component is useful when you want to display loading placeholders for paragraphs or blocks of text.</li>
</ul>
<p>Example usage:</p>
<pre><code class="lang-typescript">&lt;SkeletonText mt=<span class="hljs-string">'4'</span> noOfLines={<span class="hljs-number">4</span>} spacing=<span class="hljs-string">'4'</span> skeletonHeight=<span class="hljs-string">'2'</span> /&gt;
</code></pre>
<p>Now we know all the skeleton animation components provided by the Chakra UI. Now let's try to make an animation for a card with an image and text below it.</p>
<h2 id="heading-building-a-skeleton-loading-card">Building a skeleton loading card</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685733280706/c8980545-1a6a-41c2-953b-f8937fa20d9d.png" alt class="image--center mx-auto" /></p>
<p>Firstly we start building cards with the card component provided by Chakra UI. I like to create a folder called component in which all components used will be present. There is no square image skeleton component provided by Chakra, so we have to use the Skeleton component and give it some height.</p>
<p>Let's create a file called <code>SkeletonCard.tsx</code> and return a card with Skeleton and SkeletonText components nested inside. The main thing is trying to recreate the component to which you want to apply to load using these 3 components. My <code>SkeletonCard.tsx</code> file looks like this,</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Card, CardBody, Skeleton, SkeletonText } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>

<span class="hljs-keyword">const</span> SkeletonCard = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    &lt;Card&gt;
    &lt;Skeleton height=<span class="hljs-string">"200px"</span> /&gt;
    &lt;CardBody&gt;
      &lt;SkeletonText /&gt;
    &lt;/CardBody&gt;
  &lt;/Card&gt;
  )
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> SkeletonCard;
</code></pre>
<p>We have adjusted the height to ensure that it appears larger than the width, giving it the appearance of an image. Now we have to open <code>App.tsx</code> file and import this component.</p>
<p>In <code>App.tsx</code> file we can return a grid with a template attribute of <code>{base: `"nav" "main"`}</code>. I have added a navbar just for the heading <code>Example Skeleton Loading Animation</code>. You can remove it if you want to, if you do then change the template. We have to make a Grid component to define the template areas.</p>
<p>We need eight cards therefore we will be using an array called skeletons with 8 elements. And we map each element to a Skeleton card, you can set the array elements as key. The code in <code>App.tsx</code> looks like,</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Grid, GridItem, Heading, SimpleGrid } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;
<span class="hljs-keyword">import</span> SkeletonCard <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/SkeletonCard"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> skeletons = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>];
  <span class="hljs-keyword">return</span> (
    &lt;Grid
      templateAreas={{
        base: <span class="hljs-string">`"nav" "main"`</span>,
      }}
    &gt;
      &lt;GridItem area=<span class="hljs-string">"nav"</span> justifySelf=<span class="hljs-string">"center"</span>&gt;
        &lt;Heading&gt;Example Skeleton Loading Animation&lt;/Heading&gt;
      &lt;/GridItem&gt;
      &lt;GridItem&gt;
        &lt;SimpleGrid columns={<span class="hljs-number">4</span>} padding={<span class="hljs-number">10</span>} spacing={<span class="hljs-number">6</span>}&gt;
          {skeletons.map(<span class="hljs-function">(<span class="hljs-params">skeleton</span>) =&gt;</span> (
            &lt;SkeletonCard key={skeleton} /&gt;
          ))}
        &lt;/SimpleGrid&gt;
      &lt;/GridItem&gt;
    &lt;/Grid&gt;
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Thus we have successfully implemented a skeleton animation using Chakra UI. This is that easy to do. To check the result you can use the development server. To do that just run <code>npm run dev</code>. And you should be able to see the result.</p>
<p>We have implemented only the animation, it's the best case when you're trying to fetch data from an API or database so the user has to wait for a while, so you can use this animation to increase the user experience. You can use the <a target="_blank" href="https://chakra-ui.com/docs/components/skeleton">documentation</a> of Chakra to know more examples and use cases.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>We have completed implementing the skeleton loading animation on our website using Chakra UI. There are more libraries out there which can implement skeleton loading and you may be interested in them, so I have mentioned some below.</p>
<ul>
<li><p><a target="_blank" href="https://www.npmjs.com/package/react-loading-skeleton">react-loading-skeleton</a></p>
</li>
<li><p><a target="_blank" href="https://www.npmjs.com/package/react-content-loader#examples">react-content-loader</a></p>
</li>
</ul>
<p>There may be more I could only find them. User Experience is a crucial so using skeleton animations can give you a plus point atleast it did for me. Thank you for reading patiently and do follow me on social media.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://hashnode.com/@akashrchandran">https://hashnode.com/@akashrchandran</a></div>
]]></content:encoded></item><item><title><![CDATA[How to create REST API using Django REST framework]]></title><description><![CDATA[Let me introduce you to Steve, a banana farmer who cultivates a diverse range of bananas, from Apple bananas to Lady Fingers bananas. And steve love's his bananas and wants to sell them to the online market. Let's say he already has a website to list...]]></description><link>https://blog.akashrchandran.in/how-to-create-rest-api-using-django-rest-framework</link><guid isPermaLink="true">https://blog.akashrchandran.in/how-to-create-rest-api-using-django-rest-framework</guid><category><![CDATA[Django]]></category><category><![CDATA[django rest framework]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[APIs]]></category><category><![CDATA[REST API]]></category><dc:creator><![CDATA[Akash R Chandran]]></dc:creator><pubDate>Mon, 29 May 2023 10:38:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1685356199422/1153d641-4394-4459-909f-e3c8bd16d5d4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let me introduce you to Steve, a banana farmer who cultivates a diverse range of bananas, from Apple bananas to Lady Fingers bananas. And steve love's his bananas and wants to sell them to the online market. Let's say he already has a website to list your bananas on. As of now static you have stock available hardcore written to HTML file. Every time he wants to update you have to edit the HTML file which is sad🤕. He finally decide to make the website dynamic by creating an API to get stock information from the database.</p>
<p><img src="https://i.giphy.com/media/cw8Nr4u28tVKw/giphy.webp" alt class="image--center mx-auto" /></p>
<p>He takes his Banana Book laptop and starts coding. He chooses Django paired with the Django REST framework as we want to make the banana website robust. But he gets get stuck and couldn't figure out what to do next. He reaches burnout and feels like he cannot do it. Then he remembers his bananas and his love for bananas gave him more determination. He remembers an old friend <strong>Akash😎</strong>, who can help him to complete this task. So he asks the guy and that guy writes a tutorial for him.</p>
<blockquote>
<p>Let's help Steve to make a REST API using the Django REST framework.</p>
</blockquote>
<h2 id="heading-lets-help-steve">Let's help Steve</h2>
<p>Steve is a great guy and his love for bananas is immeasurable, so let's help Steve by building him a REST API using the Django REST framework. Firstly we require a laptop that has Python3 installed on it. You can download it from <a target="_blank" href="http://Python.org">Python.org</a>. Different versions of Python are available but be careful and choose any version <code>&gt;= 3.8</code>.</p>
<p>We will be building a Rest API to fetch banana stocks from the database. Let's not connect the database, it may get confusing to call it in one tutorial. Here instead we can use a JSON file which stores data and parse it to get the values of the stock. We are trying to learn how to use the Django rest framework and create a REST API using it. So we won't be learning much about database connection here.</p>
<h2 id="heading-setting-up-django">Setting up Django</h2>
<p>It's better to use a dedicated environment for each Django project. Even Django team suggests using a virtual environment. Python itself comes with <a target="_blank" href="https://docs.python.org/3/tutorial/venv.html">venv</a> for managing environments which we will use for this guide.</p>
<h3 id="heading-setting-up-environment">Setting up environment</h3>
<p>You can give any name to the virtual environment, but here I am going with <code>djangoproject</code>.</p>
<h4 id="heading-windows"><strong>Windows</strong></h4>
<p>Make sure you have installed Python before continuing to the next instructions.</p>
<p>Next, create a folder in your preferred directory and name it whatever you like I am going with <code>Django REST API framework</code>. Next to set up the virtual environment enter the command opening terminal or CMD.</p>
<pre><code class="lang-bash">py -3 -m venv djangoproject
.venv\scripts\activate
</code></pre>
<h4 id="heading-linux-or-mac-os"><strong>Linux or Mac OS</strong></h4>
<blockquote>
<p><strong><em>Most of the Linux Distributions come with python3 installed by default, just check if it exists by using the command.</em></strong></p>
</blockquote>
<pre><code class="lang-bash">python3 --version
</code></pre>
<p>For Mac users just head to <a target="_blank" href="http://python.org"><strong>python.org</strong></a> and download the .pkg file and start installing.</p>
<p>Next to setting up a virtual environment, on Linux sometimes we need to install the extra library. To do the same, just enter the command in your terminal.</p>
<pre><code class="lang-bash">sudo apt-get install python3-venv
</code></pre>
<p>Next, to initialize and activate a virtual environment on Mac and Linux, use the commands below.</p>
<pre><code class="lang-bash">python3 -m venv djangoproject
<span class="hljs-built_in">source</span> .venv/bin/activate
</code></pre>
<h3 id="heading-installing-django">Installing Django</h3>
<p>Next, we need to install Django on our virtual environment. To do that we can simply use the command below. Make sure you have activated the virtual environment before executing this command.</p>
<pre><code class="lang-bash">pip install Django
</code></pre>
<p>After that, we have to start a project in our directory to get started. Django provides a template for the project and we can use that to create our app. To get the template in our current working directory you can use the command below.</p>
<pre><code class="lang-bash">django-admin startproject django_rest_trial .
</code></pre>
<p><code>django_rest_trial</code> is the name of the project which I choose, but you're free to use whatever name you prefer. After running that some files and folders should appear on the file explorer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685249151526/6c781684-9c75-4733-9dc8-b9dffadeda67.png" alt="Vs code showing the files after running the Django start project command" class="image--center mx-auto" /></p>
<p>Now we need to create an app inside our Django project. The apps are like parts of a website which manage a certain task. for example, we can have an app for handling payment on the website or we can have an app that verifies login and sign-up. This is one of the pros of using Django as different teams can manage different apps yet they can make them work together.</p>
<p>To create a Django app you can use the below command. Here <code>rest_api</code> is my app name as it manages the REST APIs on our website. Feel free to choose a different name if you want to.</p>
<pre><code class="lang-bash">py manage.py startapp rest_api <span class="hljs-comment">#windows</span>

python3 manage.py startapp rest_api <span class="hljs-comment"># Linux and MAc</span>
</code></pre>
<p>After executing this command a new folder should appear with the name of the app that was created using the above command.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685259633231/ff624e38-47c6-49a5-b098-e0a8508b8d05.png" alt="Vs code showing the files after running the Django create app command" class="image--center mx-auto" /></p>
<p>Even though we don't require a database, Django sessions and other values like admin, users etc. need a database. By default, Django comes with SQLite, which is a great option as it doesn't need much of any configuration. Django needs to migrate the required tables and values to the database to do that we have to use the below command.</p>
<pre><code class="lang-bash">py manage.py migrate <span class="hljs-comment"># Windows</span>

python manage.py migrate <span class="hljs-comment"># Linux</span>
</code></pre>
<p>We have finished setting up our Django project, you can even try running it by just running the server using the runserver command. Go to <code>http://127.0.0.1:8000/</code> and you should see the standard Django greeting page.</p>
<pre><code class="lang-bash">py manage.py runserver <span class="hljs-comment"># Windows</span>

python3 manage.py runserver <span class="hljs-comment"># Linux</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685260149584/6b61a0ee-31cf-4b37-8375-07a73cad828b.png" alt="Standard django greeting page" class="image--center mx-auto" /></p>
<h2 id="heading-setting-up-the-django-rest-framework">Setting up the Django REST framework</h2>
<p>Next, we have to install the Django REST framework, to do the same we can use pip. To install it use the command below:</p>
<pre><code class="lang-bash">pip install djangorestframework
</code></pre>
<p>Then we need to edit the <code>settings.py</code> of our Django project and include <code>rest_framework</code> in our project. You can find the settings file inside the main project folder which is the <code>django_rest_trial</code> for me.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685260732247/28a9a1c4-a179-49bc-8ce9-81f3a177f77e.png" alt="Added rest_framework to the installed apps" class="image--center mx-auto" /></p>
<p>And that's it we have completed the setup of the Django REST framework. We also need to install <code>whitenoise</code> which helps in simplifying static file serving for Python web apps. You may think that we don't have any static files for our API, but Django has it for the admin panel, debug panel etc.</p>
<pre><code class="lang-bash">pip install whitenoise[brotli]
</code></pre>
<p>You have to set up <code>whitenoise</code> as well, to do that you have to add <code>whitenoise</code> to your middleware in the <code>setting.py</code> file.</p>
<pre><code class="lang-python">MIDDLEWARE = [
    <span class="hljs-string">'django.middleware.security.SecurityMiddleware'</span>,
    <span class="hljs-string">'whitenoise.middleware.WhiteNoiseMiddleware'</span>, <span class="hljs-comment">#Added</span>
    <span class="hljs-string">'django.contrib.sessions.middleware.SessionMiddleware'</span>,
    ...
]
</code></pre>
<p>You need also setup static files root to that copy and paste the below line after <code>STATIC_URL</code> variable. And add the lines below</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> DEBUG:
    STATIC_ROOT = os.path.join(BASE_DIR, <span class="hljs-string">'staticfiles'</span>)
    STATICFILES_STORAGE = <span class="hljs-string">'whitenoise.storage.CompressedManifestStaticFilesStorage'</span>
</code></pre>
<h2 id="heading-lets-start-coding">Let's start coding</h2>
<p>First of all, we need to get the JSON file on which we are going to store the data on. I will provide it below, just copy and paste it into a file named <code>database.json</code> and keep it the in the root folder with the <code>manage.py</code> file.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"bananaTypes"</span>: [<span class="hljs-string">"Apple Banana"</span>, <span class="hljs-string">"Cavendish"</span>, <span class="hljs-string">"Lady Finger"</span>, <span class="hljs-string">"Red Dacca"</span>],
  <span class="hljs-attr">"availableStock"</span>: [<span class="hljs-number">100</span>, <span class="hljs-number">200</span>, <span class="hljs-number">300</span>, <span class="hljs-number">400</span>]
}
</code></pre>
<p>Next, we need to configure routes or endpoints which our REST APIs will use. Let the <code>rest_api</code> app uses the route <code>/rest/</code>. That is over API endpoints will be starting with the <code>rest</code> keyword.</p>
<p>To configure this we need to create <code>urls.py</code> file in the <code>rest_api</code> app folder. Keeping it aside we will need it later, open the main project folder and open the urls.py file inside it and add the following element to the <code>urlpatterns</code> list. You may need to import the <code>include</code> function from the <code>django.urls</code>. Finally, the file would look like this,</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> admin
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> include, path <span class="hljs-comment"># include was also imported</span>

urlpatterns = [
    path(<span class="hljs-string">'admin/'</span>, admin.site.urls),
    path(<span class="hljs-string">'rest/'</span>, include(<span class="hljs-string">'rest_api.urls'</span>)), <span class="hljs-comment"># added</span>
]
</code></pre>
<p>Next, we will start coding the main part of the project. Open the <code>views.py</code> file in the app folder and continue the part.</p>
<h3 id="heading-coding-the-main-part">Coding the main part</h3>
<p>Let's start by creating a function that reads our database which is the <code>database.json</code> file. I need to parse JSON so we import json library also. And create a <code>read_database()</code> function. which somewhat looks like,</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> json

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_database</span>():</span>
    <span class="hljs-keyword">with</span> open(<span class="hljs-string">'database.json'</span>, <span class="hljs-string">'r'</span>) <span class="hljs-keyword">as</span> f:
        <span class="hljs-keyword">return</span> json.load(f)
</code></pre>
<p>After that, we create a function which accepts both <code>GET</code> and <code>POST</code> request and respond with the available stock of each banana variety. To do that we need to import <code>app_view</code> and <code>Response</code> from Django REST framework.</p>
<p>The <code>app_view</code> is a decorator which is used to denote what type of requests it can accept in our case we accept both <code>GET</code> and <code>POST</code> requests. It almost acts the same way as the <code>app.route</code> in Flask, we mention methods in the same if you know.</p>
<p>The <code>Response</code> object allows you to easily serialize data into the appropriate format (such as JSON or XML) and set the appropriate HTTP status code for the response. It also provides several convenient methods for setting headers, cookies, and other response metadata.</p>
<p>The <code>views.py</code> file would be like after all changes,</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> json

<span class="hljs-keyword">from</span> rest_framework.decorators <span class="hljs-keyword">import</span> api_view
<span class="hljs-keyword">from</span> rest_framework.response <span class="hljs-keyword">import</span> Response

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_database</span>():</span>
    <span class="hljs-keyword">with</span> open(<span class="hljs-string">'daabase.json'</span>, <span class="hljs-string">'r'</span>) <span class="hljs-keyword">as</span> f:
        <span class="hljs-keyword">return</span> json.load(f)

<span class="hljs-meta">@api_view(['GET', 'POST'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_stocks</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-keyword">try</span>:
        database = read_database()
        banana_type = database[<span class="hljs-string">'bananaTypes'</span>]
        avail_stock = database[<span class="hljs-string">'availableStock'</span>]
        response = {}
        <span class="hljs-keyword">for</span> banana,stock <span class="hljs-keyword">in</span> zip(banana_type,avail_stock):
            response[banana] = stock
        <span class="hljs-keyword">return</span> Response({<span class="hljs-string">'error'</span>:<span class="hljs-literal">False</span>, <span class="hljs-string">'bananaStock'</span>: response}, status=<span class="hljs-number">200</span>)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        <span class="hljs-keyword">return</span> Response({<span class="hljs-string">'error'</span>:<span class="hljs-literal">True</span>, <span class="hljs-string">'message'</span>: str(e)}, status=<span class="hljs-number">500</span>)
</code></pre>
<p>If you remember we have to still route the function <code>get_stocks</code> to one of the endpoints. To do that open the <code>urls.py</code> in the <code>rest_api</code> or app folder and paste the below code,</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path
<span class="hljs-keyword">from</span> . <span class="hljs-keyword">import</span> views


urlpatterns = [
    path(<span class="hljs-string">'get_stock/'</span>, views.get_stocks, name=<span class="hljs-string">'available stocks'</span>),
]
</code></pre>
<p>Now our Django REST API is successfully created. You can try running it on localhost by using the command <code>python manage.py runserver</code> and heading to <code>http://127.0.0.1:8000/rest/get_stocks/</code> to see the API working in real-time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685292367383/68c4ba64-c1f6-45da-9448-7c5dd14e76e1.png" alt="API response example" class="image--center mx-auto" /></p>
<p>You can even use <a target="_blank" href="https://www.postman.com/">Postman</a> or <a target="_blank" href="https://hoppscotch.io/">Hoppscotch</a> to test the API to check if it's working correctly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685292683521/f6a7682e-ce42-40fc-9d59-29d67e3252d4.png" alt="Testing API in Hoppscotch" class="image--center mx-auto" /></p>
<h2 id="heading-hosting-api-on-rendercom">Hosting API on render.com</h2>
<p>You need an account on <a target="_blank" href="https://www.render.com">render.com</a>. You can signup for one <a target="_blank" href="https://dashboard.render.com/register">here</a>. And connect your GitHub account to it. You can find all the instructions in detail on my old blog, I will link it below</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.akashrchandran.in/deploying-fastapi-application-to-render#heading-creating-renderhttpsrendercom-account">https://blog.akashrchandran.in/deploying-fastapi-application-to-render#heading-creating-renderhttpsrendercom-account</a></div>
<p> </p>
<h3 id="heading-creating-requirementstxt"><strong>Creating Requirements.txt</strong></h3>
<p>Usually, I use external library <a target="_blank" href="https://pypi.org/project/pipreqs/"><strong>pipreqs</strong></a>, but you can just simply type <code>django</code>, <code>djangorestframework</code>, <code>gunicorn</code> and <code>whitenoise[brotli]</code> in the requirements.txt file. When deploying, render will install the latest version of these modules.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685300911986/474cca7c-3367-497c-a941-c2b4bdce24c9.png" alt="image showing requirements.txt file" class="image--center mx-auto" /></p>
<h3 id="heading-creating-a-gitignore-file"><strong>Creating a .gitignore file</strong></h3>
<p><code>.gitignore</code> file helps to avoid uploading unwanted or private files to the git clients such as GitHub or GitLab. When sharing your code with others, there are often files or parts of your project, you do not want to share. So these files or folders can be mentioned in the .gitignore file.</p>
<p>For this Django project, we don't want to upload <code>djangoproject</code>, <code>__pycache__</code> and <code>db.sqlite3</code>to GitHub. So we mention them in the .gitignore file like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685294413376/178de7d6-60be-429b-9ae0-b5c8872b70c6.png" alt="Image showing .gitignore file" class="image--center mx-auto" /></p>
<h3 id="heading-upload-to-github-or-gitlab"><strong>Upload to GitHub or GitLab</strong></h3>
<p>I am using GitHub here, but you can use GitLab as well. I have installed <a target="_blank" href="https://git-scm.com/download/"><strong>git</strong></a>, and I have connected it to my GitHub account. You'll find many articles on how to do it, just google it. If you're using Visual Studio then it has an built GitHub plugin which makes it way easier. I have successfully uploaded it to GitHub, you can find mine at <a target="_blank" href="https://github.com/akashrchandran/Django-REST-API-framework">akashrchandran/Django-REST-API-framework</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685294694813/503bd37e-eab4-44d5-8253-3c1dfffc92b7.png" alt="Image showing my github repo" class="image--center mx-auto" /></p>
<h3 id="heading-make-the-app-production-ready"><strong>Make the app production ready</strong></h3>
<p>We will need to change some parts of the settings of Django to make it production ready.</p>
<p>Find the declaration of the <code>SECRET_KEY</code> setting by opening <code>settings.py</code>. We don't want to keep production secrets in source code, so we'll get them via an environment variable we'll set later:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Add this to begining of the file</span>
<span class="hljs-keyword">import</span> os
</code></pre>
<p>Next change <code>SECRET_KEY</code> to be equal to the environmental variable we are going to provide later.</p>
<pre><code class="lang-python">SECRET_KEY = os.environ.get(<span class="hljs-string">'SECRET_KEY'</span>, default=<span class="hljs-string">'thisisahugesecret'</span>)
</code></pre>
<p>Also, change <code>DEBUG</code> to dynamically change based on environment variables</p>
<pre><code class="lang-python">DEBUG = <span class="hljs-string">'RENDER'</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> os.environ
</code></pre>
<p>We need to change allowed hosts also, as we are hosting. Rather than directly giving the host id after deployment we can also make it dynamic</p>
<pre><code class="lang-python"><span class="hljs-comment"># https://docs.djangoproject.com/en/3.0/ref/settings/#allowed-hosts</span>
ALLOWED_HOSTS = []

RENDER_EXTERNAL_HOSTNAME = os.environ.get(<span class="hljs-string">'RENDER_EXTERNAL_HOSTNAME'</span>) 
<span class="hljs-keyword">if</span> RENDER_EXTERNAL_HOSTNAME:
    ALLOWED_HOSTS.append(RENDER_EXTERNAL_HOSTNAME)
</code></pre>
<p>And we are done our project is now production ready. Now let's push changes to GitHub and continue.</p>
<h3 id="heading-create-a-build-script"><strong>Create a Build Script</strong></h3>
<p>We need to run a series of commands to build our app. We can accomplish this with a build script. Create a script called <code>build.sh</code> at the root of your repository:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/usr/bin/env bash</span>
<span class="hljs-comment"># exit on error</span>
<span class="hljs-built_in">set</span> -o errexit

pip install -r requirements.txt

python manage.py collectstatic --no-input
python manage.py migrate
</code></pre>
<p>Make sure the script is executable before checking it into Git:</p>
<pre><code class="lang-bash">chmod a+x build.sh
</code></pre>
<p>We completed the build script as well, and now push it to GitHub.</p>
<h3 id="heading-deploying-to-rendercomhttprendercom"><strong>Deploying to</strong> <a target="_blank" href="http://Render.com"><strong>Render.com</strong></a></h3>
<p>As we are not deploying a static site, we should choose the option <code>Web Service</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667302637873/HPSesfyBd.png" alt="Choose web service" class="image--center mx-auto" /></p>
<p>If you have connected your GitHub account, then you can just search the repository name and find it there.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685299272521/671c9afc-1939-41ec-981c-d2abc7ffa1f6.png" alt="Select the repo by searching" class="image--center mx-auto" /></p>
<p>Give a name to your web service, then select the region which is nearest to you, for me in Singapore. Leave all other values default. For the Build command, copy and paste the below:</p>
<pre><code class="lang-bash">./build.sh
</code></pre>
<p>For the Start command, copy and paste the below:</p>
<pre><code class="lang-bash">gunicorn django_rest_trial.wsgi:application
</code></pre>
<p>where <code>django_rest_trial</code> is the name of the Django project. Do change this as per your project name.</p>
<p>Next, scroll down and click the <strong>Advance</strong> button and add the environment variables. Here we only require <code>SECRET_KEY</code>. You can also use the generate button which is provided by render. After adding click the <code>Create Web Service</code> button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685299747963/6ce68d20-a7ec-4d08-a54f-ab9783c5c219.png" alt="Image showing build and start command" class="image--center mx-auto" /></p>
<p>After clicking the button you should see a log with events happening, wait till it finishes deploying.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685302806166/e96cd63d-a00b-460d-93de-343e24f58cea.png" alt="Render deployment logs" class="image--center mx-auto" /></p>
<p>After the site is live visit the route <code>/rest/get_stocks</code> and you should see the API working.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685302939368/e0dd92a6-3f01-4eac-9f9f-c32b670f8f37.png" alt="Deployed version of our live site" class="image--center mx-auto" /></p>
<p>And here we have done it and we have successfully deployed our REST API to render.com. Now sit back and relax by eating as many bananas as you can. The deployed version is available <a target="_blank" href="https://django-rest-api-dzw1.onrender.com/rest/get_stocks/">here</a>.</p>
<h2 id="heading-steve-is-partying">Steve is partying</h2>
<p><img src="https://media2.giphy.com/media/3KC2jD2QcBOSc/giphy.gif" alt="Party time" class="image--center mx-auto" /></p>
<p>Thanks for helping Steve to complete his REST API, he is now partying🥳. You can get more information on how to use the Django REST framework to best way read the <a target="_blank" href="https://www.django-rest-framework.org/">documentation</a>. There are many alternatives to the Django REST framework, you can give them a try if you want,</p>
<ul>
<li><p><a target="_blank" href="https://django-tastypie.readthedocs.io/en/latest/">Django Tastypie</a></p>
</li>
<li><p><a target="_blank" href="https://restless.readthedocs.io/en/latest/index.html">Django Restless</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/jsocol/django-jsonview">django-jsonview</a></p>
</li>
</ul>
<p>They are good alternatives but some hardly maintained any more. Django REST framework is more powerful with authentication and stuff, you can learn about it in the docs.</p>
<p>That's all we have completed the tutorial. Looking forward to meet you in the next one. Meanwhile you can follow me on hashnode and other platforms,</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://hashnode.com/@akashrchandran">https://hashnode.com/@akashrchandran</a></div>
<p> </p>
<p>Thanks for reading patiently.</p>
]]></content:encoded></item><item><title><![CDATA[Vercel Launches 3 New Storage Options for Your Next Project!]]></title><description><![CDATA[If you have tried manually deploying apps to production, then you may know how nerve-wracking things can be. Even the slightest mistake could cause the production database to be deleted, leading the company to lose billions of dollars, making you fre...]]></description><link>https://blog.akashrchandran.in/vercel-launches-3-new-storage-options-for-your-next-project</link><guid isPermaLink="true">https://blog.akashrchandran.in/vercel-launches-3-new-storage-options-for-your-next-project</guid><category><![CDATA[Productivity]]></category><category><![CDATA[Vercel]]></category><category><![CDATA[hosting]]></category><category><![CDATA[Databases]]></category><category><![CDATA[PostgreSQL]]></category><dc:creator><![CDATA[Akash R Chandran]]></dc:creator><pubDate>Tue, 16 May 2023 13:44:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1684242075188/a6cf8f33-bb8f-4679-a6b3-3158fafc64b9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you have tried manually deploying apps to production, then you may know how nerve-wracking things can be. Even the slightest mistake could cause the production database to be deleted, leading the company to lose billions of dollars, making you freak out and flee the country before your boss finds out, and start living in the Himalayas as a goat farmer.</p>
<p><img src="https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExODlhZjk3YWQzZGUzYzU2MGU0YzA1NjRiMzliYTIyYTNjOWU3Y2JjOCZlcD12MV9pbnRlcm5hbF9naWZzX2dpZklkJmN0PWc/3o7TKFy1gaoy1JNqZG/giphy.gif" alt class="image--center mx-auto" /></p>
<p>That's why most of the developers use Vercel, Netlify, Heroku, and Firebase as they handle deployment for you and prevent you from making any big mistakes. Anyways vercel just introduced 3 new databases or storage options. And let's see them in brief.</p>
<h2 id="heading-what-is-vercel">What is vercel?</h2>
<p>Well, Vercel is a cloud platform which enables developers to host their websites and web apps that deploy and scale automatically. Vercel is the favourite choice for the deployment of Next.js apps as they have more efficient support for the framework. That's not that big as vercel also maintains the Next.js.</p>
<p>But the best part is that they support almost every language framework though they specialize in javascript frameworks. I have hosted many Python frameworks like Flask, FastAPI and even Django. They even support PHP, I have hosted my app there and haven't got any issues with speed or rendering.</p>
<p>They have a crazy awesome user interface and experience that makes it so user-friendly. It provides a free tier named <code>Hobby</code> for developers to experiment and try their platform. It’s against Vercel’s TOS to run a commercial app on the free tier. Even though you technically could, they will shut down your site if caught in violation. So you'll have to go with a paid plan and it's a bit expensive when compared to other platforms.</p>
<h2 id="heading-introduction">Introduction</h2>
<p>Vercel introduced 3 new additions to their storage solutions. They did it on 1st May and you can find the announcement on the <a target="_blank" href="https://vercel.com/blog/vercel-storage">website</a>. The new additions are:</p>
<ul>
<li><p><a target="_blank" href="https://vercel.com/blog/vercel-storage#vercel-kv-a-durable-redis-database">Vercel KV</a> (Beta)</p>
</li>
<li><p><a target="_blank" href="https://vercel.com/blog/vercel-storage#vercel-postgres-complex-data-made-easy">Vercel Postgres</a> (Beta)</p>
</li>
<li><p><a target="_blank" href="https://vercel.com/blog/vercel-storage#vercel-blob-easy-file-storage-at-the-edge">Vercel Blob</a> (Private Beta)</p>
</li>
</ul>
<p>We will be talking about them individually one by one below. This is a huge thing as they are trying to control users from using any other third-party database solution and managing it themselves. The database was the only thing missing on vercel but now it's kind of complete at least it is in beta for public use. They are not yet available for enterprise usage, mostly they will be available soon.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=gA8cHj3w5XI&amp;ab_channel=Vercel">https://www.youtube.com/watch?v=gA8cHj3w5XI&amp;ab_channel=Vercel</a></div>
<p> </p>
<h2 id="heading-vercel-kv">Vercel KV</h2>
<p>It's key-value storage like Redis, in fact exactly like Redis as it is powered by Upstash. If you didn't know Upstash is a <strong>Serverless in-memory cloud database</strong> from Upstash Inc, a California-based company. It is a Serverless Redis Service. It can be used for caching layer or as a database. You can more details about it <a target="_blank" href="https://vercel.com/storage/kv">here</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684212956158/c38839ce-7fb7-4db3-bff4-69e01b854ab8.gif" alt class="image--center mx-auto" /></p>
<p>For now, I am more interested in the speed at which it works, let's try to create a simple free tier vercel KV storage. The creation is pretty straightforward, they just ask you for the name and the region. I went with Singapore as my region, as it seems to be the nearest one.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684177607628/ee420bfe-7b58-49fc-937d-8425f1343e0e.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>They also provide CLI to set and get values directly from the database.</p>
</blockquote>
<p>I copied the Template that they provide for the testing, you can get the template source on <a target="_blank" href="https://github.com/vercel/examples/tree/main/storage/kv-redis-starter">GitHub</a>. I modified its <code>page.tsx</code> file just to set and get a value from the database.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> kv <span class="hljs-keyword">from</span> <span class="hljs-string">"@vercel/kv"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.time(<span class="hljs-string">"res"</span>);
  <span class="hljs-keyword">await</span> kv.set(<span class="hljs-string">"message"</span>, <span class="hljs-string">"Hello World!"</span>);
  <span class="hljs-keyword">const</span> msg = <span class="hljs-keyword">await</span> kv.get(<span class="hljs-string">"message"</span>);
  <span class="hljs-built_in">console</span>.timeEnd(<span class="hljs-string">"res"</span>);
  <span class="hljs-keyword">return</span> &lt;p&gt;{msg}&lt;/p&gt;;
}
</code></pre>
<p>When I first ran it took more than <code>200 ms</code> to load, as it was the first request server took time to warm up and respond. Even 2nd and 3rd try still resulted in more than <code>100 ms</code>, but after that, it came down under to <code>25 - 50 ms</code> range.</p>
<blockquote>
<p>Keep in mind that this was both reading and writing. But when I tested reading from the database alone it was a little above <code>15 ms</code>.</p>
</blockquote>
<p>The storage supports all the operations that can be done on Redis. There are limitations applied on creation, requests, record size etc you can find them <a target="_blank" href="https://vercel.com/docs/storage/vercel-kv/limits">here</a>. The pricing seems to be a little above the expected but it may drop in the future.</p>
<p><a target="_blank" href="https://vercel.com/docs/storage/vercel-kv/usage-and-pricing"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684180919754/388f1031-64dc-4ed3-806e-48002bf7b539.png" alt class="image--center mx-auto" /></a></p>
<h2 id="heading-vercel-postgres">Vercel Postgres</h2>
<p>This was the part for which I was most excited. They introduced Postgres one of the most advanced general-purpose object-relational database management systems. I have been using it for my projects. It's powered by Neon a fully managed serverless PostgreSQL. Neon separates storage and computing to offer modern developer features such as serverless, branching, bottomless storage, and more.</p>
<p>Coincidentally I used Neon for a freelancing project and it was amazing as it provide a web interface to edit, give analytics and view tables which made the development of my Django app super easy. I will have to try it to be sure if it is as good as Neon. The creation of Postgres is simply the same as that of Vercel KV and only requires a name and region ( Singapore is available so I choose that ).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684213441471/4143005e-18af-489d-87cb-2cef682a196d.png" alt class="image--center mx-auto" /></p>
<p>I copied the Template that they provide for the testing, you can get the template source at <a target="_blank" href="https://github.com/vercel/examples/tree/main/storage/postgres-starter">GitHub</a>. I modified its <code>page.tsx</code> file just to create, insert and select a value from the database.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { sql } <span class="hljs-keyword">from</span> <span class="hljs-string">"@vercel/postgres"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.time(<span class="hljs-string">"create"</span>);
  <span class="hljs-keyword">await</span> sql<span class="hljs-string">`CREATE TABLE IF NOT EXISTS PERSON (name varchar(255), age int)`</span>;
  <span class="hljs-built_in">console</span>.timeEnd(<span class="hljs-string">"insert"</span>);
  <span class="hljs-built_in">console</span>.time(<span class="hljs-string">"create"</span>);
  <span class="hljs-keyword">await</span> sql<span class="hljs-string">`INSERT INTO PERSON (name, age) VALUES ('Akash', 21)`</span>;
  <span class="hljs-built_in">console</span>.timeEnd(<span class="hljs-string">"insert"</span>);
  <span class="hljs-built_in">console</span>.time(<span class="hljs-string">"select"</span>);
  <span class="hljs-keyword">const</span> { rows } = <span class="hljs-keyword">await</span> sql<span class="hljs-string">`SELECT * FROM PERSON`</span>;
  <span class="hljs-built_in">console</span>.timeEnd(<span class="hljs-string">"select"</span>);
  <span class="hljs-keyword">return</span> (
    &lt;div&gt;
      {rows.map(<span class="hljs-function">(<span class="hljs-params">row</span>) =&gt;</span> (
        &lt;div key={row.age}&gt;
          {row.name} - {row.age}
        &lt;/div&gt;
      ))}
    &lt;/div&gt;
  );
}
</code></pre>
<pre><code class="lang-powershell">create: <span class="hljs-number">474.285</span>ms
insert: <span class="hljs-number">102.999</span>ms
<span class="hljs-built_in">select</span>: <span class="hljs-number">103.254</span>ms
</code></pre>
<p>I have tested it for like 10 times and I think the time averages out nearest to these values. It's pretty good and fast for me at least. Vercel also has a web interface to view tables and execute queries same as Neon.</p>
<p>The pricing is almost the same as that of Vercel KV. And also include the same limitations as of the same. You can view the pricing <a target="_blank" href="https://vercel.com/docs/storage/vercel-postgres/usage-and-pricing">here</a>.</p>
<h2 id="heading-vercel-blob">Vercel Blob</h2>
<p>This is something that can be very useful. Vercel Blob allows you to upload and serve files via a global network through unique and unguessable URLs. it's based on Cloudflare R2 which <strong>allows you to store large amounts of</strong> unstructured data like images and PDF files on the edge in other words it's a replacement for storage buckets like S3 and that could be a game changer if your <strong>app does file uploads.</strong> It is still in private beta but you can sign up for the waiting list to try it. To signup head to this <a target="_blank" href="https://vercel.com/storage/blob">link</a>.</p>
<p>They say it is users can upload files of <strong>any size</strong>. But for the private beta phase, the upload size is limited to <code>4 MB</code>, but soon they will release its full potential and will be available for public beta.</p>
<p>The SDK is pretty simple for developers to use same as the other storage. I don't have access to it so I can't test it for myself but I would say it would be good as the other two. As per the doc, the snippet given is</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { put } <span class="hljs-keyword">from</span> <span class="hljs-string">'@vercel/blob'</span>;
<span class="hljs-keyword">import</span> { NextResponse } <span class="hljs-keyword">from</span> <span class="hljs-string">'next/server'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">upload</span>(<span class="hljs-params">request</span>) </span>{
  <span class="hljs-keyword">const</span> form = <span class="hljs-keyword">await</span> request.formData();
  <span class="hljs-keyword">const</span> file = form.get(<span class="hljs-string">'file'</span>) <span class="hljs-keyword">as</span> File;
  <span class="hljs-keyword">const</span> blob = <span class="hljs-keyword">await</span> put(file.name, file, { access: <span class="hljs-string">'public'</span> });

  <span class="hljs-keyword">return</span> NextResponse.json(blob);
}
</code></pre>
<p>The pricing is available <a target="_blank" href="https://vercel.com/docs/storage/vercel-blob/usage-and-pricing">here</a>. It will be good for companies looking for storage that has some simplicity yet advanced technologies and have loads of money to waste.</p>
<h2 id="heading-is-it-worth-it">Is it worth it?</h2>
<p>Without much of a surprise No, it's not worth it as they are priced insanely high. As it's vercel they have a bit high pricing as always but the products are also somehow astonishingly good and have a good user interface. To phrase it they are Apple of the web industry. But that doesn't justify the pricing,</p>
<ul>
<li><p>Vercel KV is 1.5x the price of Upstash scaling without the way more generous free tier.</p>
</li>
<li><p>Vercel Postgres is 2x the price of Neon scaling without the way more generous free tier. The free tier of Neon has 3GB of storage compared to 256MB of Vercel, no limit of storage on its pro plans compared to 512MB of storage for Vercel, no limit on read and write data compared to Vercel, no limit on compute time compared to Vercel.</p>
</li>
<li><p>Vercel Blob is 2 times the price of Cloudflare R2 without the way more generous free tier.</p>
</li>
</ul>
<p>The prices may change later. The VP of Developer Experience at Vercel commented on Reddit that the prices may change with the feedback of the beta users and the pricing of vercel blob isn't final yet.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684227309553/a9b66bea-32e7-41cb-9447-37f4d7004aad.png" alt class="image--center mx-auto" /></p>
<p>This is still good for developers who don't want to use other applications just for the database instead they can find all the things in a single place which makes it easier to maintain and use.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Vercel is an amazing platform for hosting web applications without a doubt. And I am sure I am going to use Vercel Postgres for future projects for sure. You should try it for sure as all the storage options are available for the Hobby plan. Vercel is trying new <a target="_blank" href="https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions#server-actions">Server Actions</a> an <strong>alpha</strong> feature in Next.js, built on top of React <a target="_blank" href="https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions#actions">Actions</a>. They enable server-side data mutations, reduced client-side JavaScript, and progressively enhanced forms. This would be a great feature for web developers.</p>
<p>Lastly thank you for reading this patiently and please follow me on Linkedin, you can find the link at <a target="_blank" href="https://www.linkedin.com/in/akashrchandran/">Akash R. Chandran | LinkedIn</a>.</p>
]]></content:encoded></item><item><title><![CDATA[How to host FastAPI application on Deta Space]]></title><description><![CDATA[Almost 2 years ago while browsing through the FastAPI docs, I came across their sponsors one of which was deta.sh and it is still there you can view it at FastAPI Docs. As a curious person, I opened the link and browsed through their website. At that...]]></description><link>https://blog.akashrchandran.in/how-to-host-fastapi-application-on-deta-space</link><guid isPermaLink="true">https://blog.akashrchandran.in/how-to-host-fastapi-application-on-deta-space</guid><category><![CDATA[FastAPI]]></category><category><![CDATA[Python]]></category><category><![CDATA[deta.sh]]></category><category><![CDATA[deployment]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Akash R Chandran]]></dc:creator><pubDate>Tue, 28 Mar 2023 02:30:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679946314333/e647c4c1-d65c-43d3-8e5a-2a2f8e2f0411.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Almost 2 years ago while browsing through the FastAPI docs, I came across their sponsors one of which was <a target="_blank" href="https://deta.sh">deta.sh</a> and it is still there you can view it at <a target="_blank" href="https://fastapi.tiangolo.com/#sponsors">FastAPI Docs</a>. As a curious person, I opened the link and browsed through their website. At that time they had a minimalist design.</p>
<p><img src="https://resource.fyi/_next/image?url=http%3A%2F%2Fres.cloudinary.com%2Fdnr4p6zlc%2Fimage%2Fupload%2Fv1666362295%2Fraimcg6gvhi7ydemcfb2.png&amp;w=3840&amp;q=75" alt="old sample view of deta.sh website" /></p>
<p>They didn't have a GUI to manage apps only CLI to deploy and manipulate apps, the only thing they provided was the register/login and docs if I remember correctly. I tried deploying some apps but failed for some I don't remember. So let the deta cloud and tried something else.</p>
<p>But yesterday I came across the same site and was amazed that they are shifting to a new better version called <a target="_blank" href="https://deta.space/">Deta Space</a>. This is in still beta but it has everything a modern platform has like GUI to manage apps, view logs, better docs and even a page to find user-build apps that are deployed on Deta Space. So I decided to test it out by deploying a sample FastAPI application. We will use the same repository as I used in my old blog showing the deployment of the FastAPI application on Render.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.akashrchandran.in/deploying-fastapi-application-to-render">https://blog.akashrchandran.in/deploying-fastapi-application-to-render</a></div>
<p> </p>
<h1 id="heading-creating-deta-spacehttpsdetaspace-account"><strong>Creating</strong> <a target="_blank" href="https://deta.space/"><strong>Deta Space</strong></a> <strong>Account</strong></h1>
<p>As with any other site, you will need an account to host apps on <a target="_blank" href="https://deta.space/">Deta Space</a>. They don't provide any third-party signup method so you will have to have to use a good old email password. You are required to choose a unique username, I think it's for subdomain assignment not sure yet though. You can sign up using this <a target="_blank" href="https://deta.space/signup">link</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679927384583/500d1f86-fc05-4761-92f0-77ef17d23df4.png" alt class="image--center mx-auto" /></p>
<p>After login, you should be redirected to the dashboard and you should look something like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679928791396/143ca38c-9705-447c-8e47-0f5734d9edb9.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-setting-up-cli">Setting Up CLI</h1>
<p>Although the site has more GUI-rich features it still lacks a deployment option. So we have to set up our CLI tool if we want to continue. <a target="_blank" href="https://deta.space/docs/en/basics/cli">Setting up the CLI - Space Docs (</a>deta.space<a target="_blank" href="https://deta.space/docs/en/basics/cli">)</a> here you can find the instructions to do so. After installation login can be done by using the command</p>
<pre><code class="lang-bash">space login
</code></pre>
<p>If installed correctly it should show something like this. Next, we need is the authentication token from Deta space.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679936113776/cde33a31-7579-4afb-9172-4ff4a81d9bc0.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-getting-token-from-deta-space">Getting token from Deta Space</h2>
<p>After you log in you will be redirected to the dashboard, use the command palette. Just search for the settings and then click generate a new token.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679936640983/cbad93e1-1d2f-49a7-a212-e180aca37879.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679936700259/99f1a980-b930-4a7b-b9f1-24308c95df83.png" alt class="image--center mx-auto" /></p>
<p>After that copy the token and come back to the terminal page. And paste it onto the terminal</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679937233478/3ba11078-f563-4576-a96e-25a7e7f794ed.png" alt class="image--center mx-auto" /></p>
<p>we have successfully set up CLI. Now let's move on to the next part which is pushing the code to Deta Space.</p>
<p>I am not going to show to how to code or install FastAPI for that you can read my old blog post.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.akashrchandran.in/deploying-fastapi-application-to-render#heading-lets-make-a-simple-api-using-fastapi">https://blog.akashrchandran.in/deploying-fastapi-application-to-render#heading-lets-make-a-simple-api-using-fastapi</a></div>
<p> </p>
<p>You can also view the code project at my GitHub repository at <a target="_blank" href="https://github.com/akashrchandran/simple-api">akashrchandran/simple-api (</a><a target="_blank" href="http://github.com">github.com</a><a target="_blank" href="https://github.com/akashrchandran/simple-api">)</a>.  </p>
<h1 id="heading-creating-spaceignore-file">Creating .spaceignore file</h1>
<p>To exclude certain files and directories from being uploaded during space push, use the .spaceignore file. It acts similarly to a .gitignore file, where each line in the file specifies a pattern. All files and directories matching the patterns will be excluded from the push.<br />For example, a <code>.spaceignore</code> file with the following content <code>space push</code> will ignore the <code>test</code> and <code>docs</code> paths.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">test</span>
docs
</code></pre>
<p>For our project, we will be ignoring the folders</p>
<pre><code class="lang-bash">venv
__pycache__
</code></pre>
<h1 id="heading-deploying-to-deta-space"><strong>Deploying to Deta Space</strong></h1>
<p>After all the hard work we have done here is going to pay off, let's make the app accessible from anywhere on the planet. Open up the code in visual studio code or any other IDE or Notepad your wish. And open the terminal on the side or use the integrated terminal option in VS code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679940982983/7d575395-2e0d-4c04-a848-2164bec1fef4.png" alt class="image--center mx-auto" /></p>
<p>Make sure you have the Space CLI installed &amp; authenticated, then run the following command to create a new Space project in the current directory.</p>
<pre><code class="lang-bash">space new
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679941199101/c86860d0-967b-4e58-9d7e-5740eceea9da.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-editing-the-spacefile">Editing the Spacefile</h2>
<p>This will create a <code>Spacefile</code> in the root directory. And it will only have the version <code>v:0</code> as text and comment to the docs. This is where we define our runtime engine and other requirements. To get a clear idea about it you can visit the <a target="_blank" href="https://deta.space/docs/en/reference/spacefile/">Spacefile - Space Docs (</a><a target="_blank" href="http://deta.space">deta.space</a><a target="_blank" href="https://deta.space/docs/en/reference/spacefile/">)</a>. To run the FastAPI app we need to define some requirements in the Spacefile. Here's what the file looks like after adding the required lines.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679941690567/ea9cafee-b456-4015-af20-b0101492e191.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-yaml"><span class="hljs-comment"># Spacefile Docs: https://go.deta.dev/docs/spacefile/v0</span>
<span class="hljs-attr">v:</span> <span class="hljs-number">0</span>
<span class="hljs-attr">icon:</span> <span class="hljs-string">./icon.png</span>
<span class="hljs-attr">app_name:</span> <span class="hljs-string">"Simple FastAPI APP"</span>
<span class="hljs-attr">micros:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">simple-fastapi</span>
    <span class="hljs-attr">src:</span> <span class="hljs-string">./</span>
    <span class="hljs-attr">engine:</span> <span class="hljs-string">python3.9</span>
    <span class="hljs-attr">dev:</span> <span class="hljs-string">.venv/bin/uvicorn</span> <span class="hljs-string">main:app</span> <span class="hljs-string">--reload</span>
</code></pre>
<p>I ran into a few troubles while making the Spacefile, it seems python apps don't support <code>run</code> commands. Use <code>dev</code> to specify a command which starts your Micro in <strong>development</strong> mode. This command will be used to start your micro when you run.<br />You can specify the version of python you need using the key <code>engine</code>. There are only two versions available currently <code>python3.9</code> and <code>python3.8</code>.<br /><code>src</code> is the directory where the main.py file resides. You can keep it inside another folder and then specify the path to that folder.</p>
<p>for the <code>icon</code> I am using the logo of FastAPI, you can check it out at <a target="_blank" href="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png">logo-teal.png (1023×369) (</a><a target="_blank" href="http://tiangolo.com">tiangolo.com</a><a target="_blank" href="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png">)</a>.  </p>
<p><strong>PS:</strong> You are required to keep the file main.py as the entry file or it will not work. Make sure you use <code>main.py</code> for any python project.</p>
<h2 id="heading-deploying-the-app">Deploying the app</h2>
<p>To deploy we just need to give the command, and it should automatically deploy and give the output URL.  </p>
<pre><code class="lang-bash">space push
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679943610440/dccfcc03-b91e-4a3c-837d-501b6220f580.gif" alt class="image--center mx-auto" /></p>
<p>Congratulations the app is live🥳🥳. And you will be able to see the application in your dashboard. You can find my deployed version at <a target="_blank" href="https://simplefastapi-1-h6036723.deta.app">https://simplefastapi-1-h6036723.deta.app</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679943882001/786030ad-54a9-49a0-8b72-7da06d2f5b0a.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>This was a simple blog explaining the way to deploy the FastAPI application on Deta Space. There are many more things you can add to the project, I am just setting an example. The documentation is pretty amazing and you can find almost all the parts documented, do give it a read at <a target="_blank" href="https://deta.space/docs/en/introduction/start">Getting started - Space Docs (</a><a target="_blank" href="http://deta.space">deta.space</a><a target="_blank" href="https://deta.space/docs/en/introduction/start">)</a>.</p>
<p>Overall I would say it's pretty easy compared to other services, even though some services are popular yet it's hard to get the app deployed on the service. The Deta Space is not that famous but it was easy to deploy apps. I am sure that I will use the service again to host my apps.</p>
<p>The Deta Space is still under construction and it's developed and updated daily. This makes it vulnerable to bugs and other problems. If you are stuck at some place, first read the docs. If you're still stuck after that then you can join their Discord server and post your queries and problems.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://discord.com/invite/K3gYNqHXUU">https://discord.com/invite/K3gYNqHXUU</a></div>
<p> </p>
<p>The community may be small but they are active and almost answers every single query raised. Giving feedback will help build the platform faster and better, do share your review on Discord.</p>
<p>Finally thank you for reading this blog, it was a good experience to share my view and knowledge about the platform. Have a great day!</p>
]]></content:encoded></item><item><title><![CDATA[Top 10 Python Packages Every Developer Should Know About]]></title><description><![CDATA[Python is undoubtedly one of the most popular programming languages in today's tech industry. With an ever-increasing number of developers turning to it, Python has established itself as a must-know skill for any aspiring programmer or software engin...]]></description><link>https://blog.akashrchandran.in/top-10-python-packages-every-developer-should-know-about</link><guid isPermaLink="true">https://blog.akashrchandran.in/top-10-python-packages-every-developer-should-know-about</guid><category><![CDATA[Python]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[python beginner]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Akash R Chandran]]></dc:creator><pubDate>Thu, 09 Mar 2023 18:36:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1678386759783/fe665181-bedd-4f0f-901a-99b716b69126.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Python is undoubtedly one of the most popular programming languages in today's tech industry. With an ever-increasing number of developers turning to it, Python has established itself as a must-know skill for any aspiring programmer or software engineer. One reason behind its massive popularity is the vast collection of python packages that make coding more efficient and seamless. If you're looking to take your Python development skills to the next level, we've got you covered. In this post, we'll be discussing ten essential python packages every developer should know about to boost their productivity and streamline their workflow. Whether you're building web applications, performing data analysis tasks or developing machine learning models, these packages are guaranteed to simplify your work and enhance your code quality. So buckle up and get ready to dive into our top 10 list!</p>
<h2 id="heading-introduction-to-python-packages">Introduction to Python Packages</h2>
<p>Python is a widely used high-level interpreted language. Python's design philosophy emphasizes code readability with its notable use of significant whitespace. Its syntax allows programmers to express concepts in fewer lines of code than would be possible in languages such as C++ or Java. The language provides constructs intended to enable clear programs on both a small and large scale.</p>
<p>Python packages are collections of modules that you can import into your scripts to make use of their functionality. In this article, we'll take a look at some of the most popular Python packages that every developer should know about.</p>
<h2 id="heading-what-is-a-python-package">What is a Python Package?</h2>
<p>Python packages are modules that contain code written in the Python programming language. Packages can be used to extend the functionality of Python or to add new features to existing Python code. Python packages can be installed from a variety of sources, including the Python Package Index (PyPI), or third-party repositories. Once installed, packages can be imported into your Python code using the import statement.</p>
<p>Packages can contain a variety of different types of content, including:</p>
<ul>
<li><p>Modules: A module is a single Python file that contains code. Modules can be imported into other modules, or the main Python interpreter, using the import statement.</p>
</li>
<li><p>Classes: A class is a template for creating objects. Classes can be defined in modules and then imported into other modules, or the main Python interpreter, using the from...import statement.</p>
</li>
<li><p>Functions: A function is a block of code that performs a specific task. Functions can be defined in modules and then imported into other modules, or the main Python interpreter, using the from...import statement.</p>
</li>
<li><p>Data: Data is any information that can be stored in computer memory. Data can be stored in variables, and passed to functions as arguments.</p>
</li>
</ul>
<h2 id="heading-the-packages-are">The Packages are:</h2>
<h3 id="heading-pandas">Pandas</h3>
<p>The Python package Pandas is a free and open-source library that provides high-performance data structures and data analysis tools. It is built on the popular Python libraries NumPy and matplotlib, which allow for efficient data manipulation and analysis. Data structures and operations for manipulating numerical tables and time series data are available in Pandas. It is a must-have for data manipulation and data science tasks. Pandas is a highly effective data analysis, manipulation, and visualisation tool. It is used in many industries, including finance, analytics, and data science, for data cleaning, preparation, and analysis. Pandas make it simple to work with large datasets, allowing users to summarise, manipulate, and visualise data quickly and easily.</p>
<h3 id="heading-numpy">NumPy</h3>
<p>NumPy is a robust and effective module for doing scientific computations. It offers quick mathematical operations on these massive, multi-dimensional arrays and matrices for which it is developed. Many mathematical operations are offered by NumPy, such as Fourier analysis, linear algebra, and random number creation. For manipulating arrays, it also offers sophisticated indexing and slicing features. In disciplines including data science, machine learning, and computational physics, NumPy is extensively employed. Its popularity is a result of the performance and usability it combines, making it a crucial Python tool for scientific computing.</p>
<h3 id="heading-matplotlib">Matplotlib</h3>
<p>Matplotlib is a Python package that offers a range of tools to developers for making interactive visualisations, such as graphs and charts, that can be used for data analysis. It is a commonly used library in science, and it works particularly well for making static 2D and 3D plots that may be highly customised and detailed. Also, it offers assistance with story interactivity and animation creation. After you grasp the fundamentals of charting, Matplotlib's simple syntax makes it simple to use. For everyone who wishes to extract amazing images from their data, it offers a necessary tool.</p>
<h3 id="heading-tensorflow">TensorFlow</h3>
<p>Popular open-source software called TensorFlow is used to create and train machine learning models. It was created by Google and is one of the most used deep learning frameworks. Because TensorFlow is built on a dataflow graph, users can see how data flows through a neural network model. It offers a versatile and effective language for creating and refining models on huge datasets. Applications supported by this package include natural language processing, picture and speech recognition, and more. You may quickly scale sophisticated models to huge datasets with TensorFlow.</p>
<h3 id="heading-scikit-learn">Scikit-learn</h3>
<p>Built on top of NumPy, SciPy, and matplotlib, Scikit-learn is a free and open-source machine learning framework. It offers straightforward and effective tools for data analysis and mining. Scikit-learn offers tools for model selection and evaluation, data preprocessing, feature selection, and model visualisation in addition to several algorithms for classification, regression, clustering, and dimensionality reduction. Classification, regression, natural language processing, image processing, and other machine learning tasks are only a few of the many machine learning tasks for which it is frequently employed in both industry and research. Scikit-learn is a vital tool for anyone interested in machine learning because of its simplicity of use and extensive capability.</p>
<h3 id="heading-pytorch">PyTorch</h3>
<p>A well-liked open-source machine-learning library for Python is called Pytorch. Because of its adaptability, clarity, and scalability, it is widely used. Using the capabilities of graphics processing units (GPUs) to speed up training, Pytorch offers a simple interface for creating deep learning algorithms. The software is widely used in research, education, and business for a range of tasks including speech recognition, computer vision, natural language processing, and more. Pytorch has developed into a vital toolkit for machine learning enthusiasts and engineers alike thanks to its comprehensive collection of tools and community support.</p>
<h3 id="heading-flask">Flask</h3>
<p>Flask is a lightweight and powerful web development framework for building Python-based web applications. It includes a comprehensive set of tools and libraries for developing a wide range of web applications, from simple static sites to more complex web applications with dynamic data. Flask has an easy-to-learn and-use API, as well as a flexible and extensible design that allows you to tailor it to your specific requirements. It also includes built-in unit testing support, simple error handling, and easy integration with other libraries and services. Because of its simplicity, flexibility, and ease of use, Flask is a popular choice for developing web applications.</p>
<h3 id="heading-django">Django</h3>
<p>Django is a Python web framework that is open source and follows the Model-View-Controller (MVC) architecture. It is widely used to rapidly create high-quality web applications. Django's clean design encourages code reuse and employs object-oriented programming principles. Django includes a powerful URL routing system for creating clean URLs, an ORM for working with databases, and an HTML template engine. It also has an authentication system, security features, and middleware support built in. Django has a vibrant community that is constantly improving and contributing to the framework. Because of its scalability, flexibility, and ease of use, it is a popular choice among developers.</p>
<h3 id="heading-requests">Requests</h3>
<p>With the Python library Requests, HTTP requests are made easier. It was developed for usage with API requests and page scraping. Requests offer a straightforward and understandable interface for handling HTTP requests and responses. The package includes functions for managing cookies and sessions, authenticating users, and encoding data in several different forms. Moreover, Requests supports the HTTP/1.1 and HTTP/2 protocols and offers synchronous and asynchronous request handling. The programme is frequently used for tasks including automation, data extraction, and web development.</p>
<h3 id="heading-beautifulsoup">BeautifulSoup</h3>
<p>Beautiful Soup is a popular Python package for parsing HTML and XML documents. This package enables programmers to easily extract data from HTML pages. It makes it simple to use web scraping functions in Python. Beautiful Soup parses HTML documents and allows users to extract the content they require. Beautiful Soup's extensive documentation allows it to work with HTML files in a variety of formats. To efficiently extract content, the package supports a variety of searching and filtering methods. It is the go-to Python package for extracting data from web pages.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>In conclusion, the Python programming language is a very strong and flexible tool that can be applied to a wide range of projects, including web development and data analysis. The top 10 Python packages that every developer should be familiar with can help developers use Python to its best ability. These software packages offer strong tools and capabilities that can be utilised to create intricate applications and address intricate issues. These packages make it simple for developers to build dependable and effective apps. We trust that this article has helped you gain a better knowledge of the top 10 Python packages that every developer should be familiar with.</p>
]]></content:encoded></item><item><title><![CDATA[Going Beyond the
Basics: Rarely Used Python
Operators and Functions]]></title><description><![CDATA[Introduction
I am a self-taught python developer for more than 3 years now and yet I'm constantly surprised by the new things I learn every day. Each day I find a new operator or function which makes life so much easier. Many operators and functions ...]]></description><link>https://blog.akashrchandran.in/rarely-used-python-operators-and-functions</link><guid isPermaLink="true">https://blog.akashrchandran.in/rarely-used-python-operators-and-functions</guid><category><![CDATA[Python]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[python projects]]></category><category><![CDATA[python beginner]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Akash R Chandran]]></dc:creator><pubDate>Thu, 23 Feb 2023 18:34:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677203225236/af49e508-7c04-43b4-ae0a-a52da360598b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>I am a self-taught python developer for more than 3 years now and yet I'm constantly surprised by the new things I learn every day. Each day I find a new operator or function which makes life so much easier. Many operators and functions are inbuilt and knowing them makes a huge difference. It's not possible to learn them all but at least you can get familiar with them. So here's my cheat sheet for some rarely used in python3.</p>
<h2 id="heading-operators">Operators</h2>
<p>We can directly say that operator is a symbol or a set of symbols which is used to represent an action or a process. Operators are used to manipulate values and perform calculations, comparisons, and other operations in a program. All most all programming languages have the same set of operators like</p>
<ul>
<li><p>Arithmetic operators ( + , - , * , / )</p>
</li>
<li><p>Comparison operators ( == , != , &lt; , &gt; )</p>
</li>
<li><p>Logical operators ( AND , OR , NOT )</p>
</li>
<li><p>Assignment operators ( = )</p>
</li>
<li><p>Bitwise operators ( bitwise AND , bitwise OR , bitwise NOT )</p>
</li>
</ul>
<blockquote>
<p>These are simple operators that can be found in many programming languages.</p>
</blockquote>
<p>But we are not here to talk about them, let's get right into the topic which is some rarely used operators in python. If you are already familiar with those, it suggests that you possess strong development skills.</p>
<h3 id="heading-floor-division">Floor Division ( <code>//</code> )</h3>
<p>In contrast to standard division, floor division returns the largest possible integer. This number is either less than or equal to the outcome of the usual division. We can do the same in python by using the operator <code>//</code>.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Floor division</span>
print(<span class="hljs-number">5</span> // <span class="hljs-number">2</span>)
<span class="hljs-comment"># Output: 2</span>
</code></pre>
<p>In python, there is no ceiling equivalent operator. But you can use upside-down floor division.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">ceildiv</span>(<span class="hljs-params">a, b</span>):</span>
    <span class="hljs-keyword">return</span> -(a // -b)

print(ceildiv(<span class="hljs-number">5</span>, <span class="hljs-number">2</span>)
</code></pre>
<h3 id="heading-walrus-operator">Walrus Operator ( <code>:=</code> )</h3>
<p>Python 3.8 introduces the walrus operator that lets you assign a value to a variable as part of an expression. You can use it in situations where you want to evaluate an expression and use the result later. By reducing duplication and improving logic flow, the walrus operator makes your code more concise and readable. You don't need to declare the variable first and then assign it, you can directly do that.</p>
<pre><code class="lang-python">a = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
<span class="hljs-keyword">if</span> (n := len(a)) &gt; <span class="hljs-number">3</span>:
    print(<span class="hljs-string">f"List is too long (<span class="hljs-subst">{n}</span> elements, expected &lt;= 3)"</span>)
</code></pre>
<h3 id="heading-matrix-multiplication-operator">Matrix Multiplication Operator ( <code>@</code> )</h3>
<p>Matrix Multiplication Operator was introduced in Python 3.5 and it is used to multiply two-dimensional arrays in python. It's not available to use with the standard data structures of python rather it was specifically introduced for the numpy arrays. Numpy is a library specifically dealing with the operations of arrays or lists.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
A = np.array([[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>], [<span class="hljs-number">5</span>, <span class="hljs-number">6</span>]])
B = np.array([[<span class="hljs-number">7</span>, <span class="hljs-number">8</span>], [<span class="hljs-number">9</span>, <span class="hljs-number">10</span>]])
result = A @ B
print(result)
</code></pre>
<p>But you can do the same on standard not directly but you can convert it to numpy array and then multiply using the Operator.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
A = [[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>], [<span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>]]
arr = np.array(A)
B = [[<span class="hljs-number">10</span>, <span class="hljs-number">11</span>, <span class="hljs-number">12</span>], [<span class="hljs-number">13</span>, <span class="hljs-number">14</span>, <span class="hljs-number">15</span>], [<span class="hljs-number">16</span>, <span class="hljs-number">17</span>, <span class="hljs-number">18</span>]]
arr2 = np.array(B)
result = arr @ arr2
print(result)
</code></pre>
<h3 id="heading-set-like-operators">Set-like Operators</h3>
<p>Python's "set-like operators" are operations like union, intersection, difference, and the symmetric difference that behave like set operations but can also be used with other sequence types.</p>
<ul>
<li><p><code>|</code> (union): returns a new set that is absent of duplicates and contains every element from both sets (or other sequence types).</p>
</li>
<li><p><code>&amp;</code> (intersection): returns a new set that only includes the components that are shared by the two sets (or other sequence types).</p>
</li>
<li><p><code>-</code> (difference): returns a new set that only includes the items from the first set (or another sequence type) that aren't present in the second set.</p>
</li>
<li><p><code>^</code> (symmetric difference): returns a new set that only includes the items that are present in one of the two sets (or other sequence types), but not both.</p>
</li>
</ul>
<pre><code class="lang-python">list1 = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
list2 = [<span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]

<span class="hljs-comment"># Union</span>
result_union = list(set(list1) | set(list2))
print(result_union)
<span class="hljs-comment"># Output: [1, 2, 3, 4]</span>

<span class="hljs-comment"># Intersection</span>
result_intersection = list(set(list1) &amp; set(list2))
print(result_intersection)
<span class="hljs-comment"># Output: [2, 3]</span>

<span class="hljs-comment"># Difference</span>
result_difference = list(set(list1) - set(list2))
print(result_difference)
<span class="hljs-comment"># Output: [1]</span>

<span class="hljs-comment"># Symmetric difference</span>
result_symmetric_difference = list(set(list1) ^ set(list2))
print(result_symmetric_difference)
<span class="hljs-comment"># Output: [1, 4]</span>
</code></pre>
<p>In addition to sets, these operators can be applied to other sequence classes, such as lists, tuples, and strings. The returned output will be of the same type as the first argument when applied to non-set sequence types.</p>
<h2 id="heading-functions">Functions</h2>
<p>You can think of a function as a block of code that performs a specific task. Functions enable you to break your code into smaller, more modular pieces, making it easier to read, write, and maintain. Input arguments can be passed into functions, and then they can perform calculations or operations on them.</p>
<p>Many inbuilt functions are available in python and many may know the standard ones like</p>
<p>• len() - returns the number of items in an object such as a string, list, or tuple.</p>
<p>• input() - allows the user to input values from the keyboard and returns the entered value as a string.</p>
<p>• range() - a function that generates a sequence of numbers between the given start, stop and step values.</p>
<p>• sum() - returns the sum of all elements in an iterable such as a list or a tuple.</p>
<p>These are just some of the examples, the list may go far further. But for now, let's go deep down into rarely used python built-in functions.</p>
<h3 id="heading-sorted">sorted()</h3>
<p>In Python, you can sort a list with list.sort(). Keep in mind that this method modifies the original list in place, so the list gets sorted directly. Instead, you can use the sorted() function to get a sorted copy of the list while maintaining the integrity of the original list. The original list is not changed by this method; instead, it returns a fresh, sorted list.</p>
<pre><code class="lang-python">arr = [<span class="hljs-number">5</span>, <span class="hljs-number">7</span>, <span class="hljs-number">3</span>, <span class="hljs-number">6</span>, <span class="hljs-number">2</span>, <span class="hljs-number">9</span>, <span class="hljs-number">1</span>, <span class="hljs-number">4</span>, <span class="hljs-number">8</span>]
sort_arr = sorted(arr)
print(arr)
print(sort_arr)
<span class="hljs-comment"># Output</span>
<span class="hljs-comment"># [5, 7, 3, 6, 2, 9, 1, 4, 8]</span>
<span class="hljs-comment"># [1, 2, 3, 4, 5, 6, 7, 8, 9]</span>
</code></pre>
<h3 id="heading-slice">slice()</h3>
<p>To specify how to slice a sequence, use a slice object. You can define the beginning and ending points of the slicing. Additionally, you can specify the step, allowing you to, for example, slice only the remaining items.</p>
<pre><code class="lang-python">my_list = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]
my_slice = slice(<span class="hljs-number">1</span>, <span class="hljs-number">4</span>, <span class="hljs-number">2</span>)
print(my_list[my_slice])  <span class="hljs-comment"># Output: [2, 4]</span>
</code></pre>
<h3 id="heading-divmod">divmod()</h3>
<p>The divmod() is a method in python that takes two numbers as arguments and returns a pair of numbers consisting of their quotient and remainder. This is better when you have both remainder and quotient needed for something.</p>
<pre><code class="lang-python">a = <span class="hljs-number">6</span>
b = <span class="hljs-number">4</span>
print(divmod(a,b))
<span class="hljs-comment"># Output: (1, 2)</span>
</code></pre>
<h3 id="heading-reversed">reversed()</h3>
<p>The method returns an iterator that accesses the given sequence in reverse order. list.reverse() also does the same task but the original list is modified directly, and no new list is created. And with reversed() it does not modify the original list but instead returns a new list with the elements in reverse order.</p>
<pre><code class="lang-python">my_list = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]
reversed_list = list(reversed(my_list))
print(reversed_list)
<span class="hljs-comment"># Output: [5, 4, 3, 2, 1]</span>
</code></pre>
<h3 id="heading-callable"><strong>callable()</strong></h3>
<p>callable() is an internal function that, if the given object may be used as a function, returns <code>True</code>; otherwise, it returns <code>False</code>.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">foo</span>():</span>
    <span class="hljs-keyword">pass</span>

print(callable(foo))
<span class="hljs-comment"># Output: True</span>

x = <span class="hljs-number">5</span>
print(callable(x))
<span class="hljs-comment"># Output: False</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bar</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__call__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">pass</span>

b = Bar()
print(callable(b))
<span class="hljs-comment"># Output: True</span>

lst = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
print(callable(lst))
<span class="hljs-comment"># Output: False</span>
</code></pre>
<h3 id="heading-setattr-and-getattr">setattr() and getattr()</h3>
<p>The value of an attribute on an object is set with the <code>setattr()</code> function. Three parameters are required: the object whose attribute is to be set, the attribute's name as a string, and the value to set.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
    <span class="hljs-keyword">pass</span>

p = Person()
setattr(p, <span class="hljs-string">'name'</span>, <span class="hljs-string">'John'</span>)
print(p.name)
<span class="hljs-comment"># Output: John</span>
</code></pre>
<p>The value of an attribute of an object is retrieved by the <code>getattr()</code> function. It requires two arguments: the object whose attribute is to be obtained and the attribute's name as a string. AttributeError is raised if the attribute is missing.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
    name = <span class="hljs-string">'John'</span>

p = Person()
print(getattr(p, <span class="hljs-string">'name'</span>))
<span class="hljs-comment"># Output: John</span>
</code></pre>
<h3 id="heading-vars">vars()</h3>
<p>A built-in function called <code>vars()</code> gives the value of an object's <code>__dict__</code> attribute. It gives back a dictionary that contains the object's (local) symbol table, or all the attributes that were defined for the object.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, a, b</span>):</span>
        self.a = a
        self.b = b
obj = MyClass(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)
print(vars(obj))
<span class="hljs-comment"># output: {'a': 1, 'b': 2}</span>
</code></pre>
<h3 id="heading-filter">filter()</h3>
<p>It is possible to filter components from an iterable (like a list) based on a function by using the built-in function <code>filter()</code>. The <code>filter()</code> method accepts two arguments: an iterable and a function that returns either True or False (such as a list). Only the components for which the function returns True are included in the resulting iterable after being applied to each element in the iterable.</p>
<pre><code class="lang-python">numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>]

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">is_even</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-keyword">return</span> n % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>

even_numbers = list(filter(is_even, numbers))

print(even_numbers)
<span class="hljs-comment"># Output: [2, 4, 6, 8, 10]</span>
</code></pre>
<h3 id="heading-next">next()</h3>
<p>To get the next item from an iterator, use the built-in Python method next(). The next element in the sequence is returned when <code>next()</code> is invoked on an iterator. The StopIteration exception is raised if the sequence contains no additional components. To iterate over an iterator's components one by one, use the next() function in a loop.</p>
<pre><code class="lang-python">my_list = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]
my_iterator = iter(my_list)

print(next(my_iterator)) <span class="hljs-comment"># Output: 1</span>
print(next(my_iterator)) <span class="hljs-comment"># Output: 2</span>
print(next(my_iterator)) <span class="hljs-comment"># Output: 3</span>
print(next(my_iterator)) <span class="hljs-comment"># Output: 4</span>
print(next(my_iterator)) <span class="hljs-comment"># Output: 5</span>

<span class="hljs-comment"># This will raise the StopIteration exception</span>
print(next(my_iterator)) <span class="hljs-comment"># Output: StopIteration</span>
</code></pre>
<h3 id="heading-hash">hash()</h3>
<p>Python comes with a built-in function called <code>hash()</code> that gives an object's hash value. The hash value, which is a distinct integer that symbolises the object, can be used for several things, including comparing objects for equality and storing them in hash tables.</p>
<pre><code class="lang-python"><span class="hljs-comment"># hash a string</span>
my_string = <span class="hljs-string">"hello world"</span>
hash_value = hash(my_string)
print(hash_value)
<span class="hljs-comment"># Output: -7156188717690076749</span>
</code></pre>
<h3 id="heading-zip">zip()</h3>
<p>Python's <code>zip()</code> method accepts iterable as input and produces an iterator of tuples as a result. The matching elements from each iterable are contained in each tuple.</p>
<pre><code class="lang-python">numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
colors = [<span class="hljs-string">'red'</span>, <span class="hljs-string">'green'</span>, <span class="hljs-string">'blue'</span>]
result = zip(numbers, colors)
print(list(result))
<span class="hljs-comment"># Output: [(1, 'red'), (2, 'green'), (3, 'blue')]</span>
</code></pre>
<h3 id="heading-locals-and-globals">locals() and globals()</h3>
<p>Built-in functions called locals() and globals() return dictionaries with the current local and global symbol tables, respectively.</p>
<pre><code class="lang-python">x = <span class="hljs-number">10</span>  <span class="hljs-comment"># global variable</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_func</span>():</span>
    y = <span class="hljs-number">20</span>  <span class="hljs-comment"># local variable</span>
    print(<span class="hljs-string">"locals:"</span>, locals())
    print(<span class="hljs-string">"globals:"</span>, globals())

my_func()
<span class="hljs-comment"># Output:</span>
<span class="hljs-comment"># locals: {'y': 20}</span>
<span class="hljs-comment"># globals: {..., 'x': 10, 'my_func': &lt;function my_func at 0x7f5de5b72560&gt;}</span>
</code></pre>
<h3 id="heading-dis">dis()</h3>
<p>Python bytecodes can be disassembled using the dis module. It is primarily used to comprehend how the Python interpreter runs your code. A list of instructions containing the disassembled code is written to the console.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> dis

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_func</span>(<span class="hljs-params">a, b</span>):</span>
    c = a + b
    <span class="hljs-keyword">return</span> c

dis.dis(my_func)
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-python">  <span class="hljs-number">4</span>           <span class="hljs-number">0</span> LOAD_FAST                <span class="hljs-number">0</span> (a)
              <span class="hljs-number">2</span> LOAD_FAST                <span class="hljs-number">1</span> (b)
              <span class="hljs-number">4</span> BINARY_ADD
              <span class="hljs-number">6</span> STORE_FAST               <span class="hljs-number">2</span> (c)

  <span class="hljs-number">5</span>           <span class="hljs-number">8</span> LOAD_FAST                <span class="hljs-number">2</span> (c)
             <span class="hljs-number">10</span> RETURN_VALUE
</code></pre>
<h3 id="heading-eval">eval()</h3>
<p><code>eval()</code> is a Python function that returns the result of evaluating a string as a Python expression. The syntax for the eval() function is:</p>
<pre><code class="lang-python">eval(expression, globals=<span class="hljs-literal">None</span>, locals=<span class="hljs-literal">None</span>)
</code></pre>
<p>where expression is the string to be evaluated as a Python expression and globals and locals are optional dictionaries defining the global and local variable namespaces.</p>
<p>Here's an example of how to use <code>eval()</code>:</p>
<pre><code class="lang-python">x = <span class="hljs-number">10</span>
y = <span class="hljs-number">20</span>
expr = <span class="hljs-string">"x + y"</span>
result = eval(expr)
print(result)
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>There are several built-in operators and functions in Python, some of which are well-known while others are less well-known. In addition to performing numerous tasks like sorting, filtering, and data transformation, these functions and operators can assist developers in writing more concise and effective code. Certain lesser-known Python operators and functions, like <code>slice()</code>, <code>dis()</code>, <code>reduce()</code>, and <code>chain(), as well as some frequently used ones, likesorted()</code>, filter(), and <code>len()</code>, have been addressed in this blog. Even though it's impossible to go over every function and operator in Python, the examples we've given should aid developers in bettering their knowledge and comprehension of the language.</p>
]]></content:encoded></item><item><title><![CDATA[How to Receive GitHub Notifications on Discord in
Real-Time]]></title><description><![CDATA[Discord's versatility and personalization options have helped it gain popularity among developers. Discord's number of different communication options, such as voice, video, and text chat, can make it simpler to collaborate with team members who migh...]]></description><link>https://blog.akashrchandran.in/how-to-receive-github-notifications-on-discord-in-real-time</link><guid isPermaLink="true">https://blog.akashrchandran.in/how-to-receive-github-notifications-on-discord-in-real-time</guid><category><![CDATA[GitHub]]></category><category><![CDATA[discord]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[webhooks]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Akash R Chandran]]></dc:creator><pubDate>Sun, 19 Feb 2023 19:17:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676833399312/9184dce9-cf48-4a40-83c1-efc6953109b3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Discord's versatility and personalization options have helped it gain popularity among developers. Discord's number of different communication options, such as voice, video, and text chat, can make it simpler to collaborate with team members who might be in different places, which is one of the reasons developers use it. Developers can also build unique bots that automate processes or offer useful data like code snippets or documentation.</p>
<h1 id="heading-introduction">Introduction</h1>
<p>If you're a programmer or a member of a development team, you probably use GitHub to collaborate on code and manage projects. GitHub is a popular platform that allows developers to share and review code, track changes, and work together on projects.</p>
<p>You may find it difficult to keep track of changes and updates to your codebase when you are working on multiple projects simultaneously. Notifications can help in this situation. Notifications allow you to stay informed about new pull requests, issues, and other changes to your code without constantly checking GitHub.</p>
<p>One way to get GitHub notifications is to use Discord, a popular chat platform for gamers that has become increasingly popular among developers. You can set up a webhook in Discord to receive notifications from GitHub and post them to a particular channel there. You can easily keep track of changes to your code and work more productively with your team if you do this. We'll show you how to set up a webhook on Discord to receive GitHub notifications in this blog post. Everything will be covered, including setting up a webhook on Discord, customising your notifications, and troubleshooting frequent problems.</p>
<h2 id="heading-set-up-a-discord-webhook"><strong>Set Up a Discord Webhook</strong></h2>
<p>You must set up a webhook on Discord to begin receiving GitHub notifications on your channel. Sending automated messages from one app to another is possible using webhooks. In this instance, we'll make use of a webhook to send Discord notifications from GitHub. Follow these steps:-</p>
<ul>
<li>Open Discord and select the server where you want to receive GitHub notifications. Better to create a channel for only receiving GitHub notifications.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676827913006/7b7a6c2b-034c-442c-bee3-c610aea7b30d.png" alt="create a channel to receive notifications." class="image--center mx-auto" /></p>
<ul>
<li>Click on the server settings and select the <code>Integrations</code> tab. Click on the <code>Create Webhook</code> button and follow the prompts to create a new webhook. Give It a good name, anything you prefer.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676828511534/e40a77bb-d431-42a8-820b-a4f03ee973e8.png" alt="Create webhook and copy webhook url" class="image--center mx-auto" /></p>
<ul>
<li>You'll receive a webhook URL once you've finished creating the webhook. You'll use this URL to link your GitHub repository to your Discord channel; it's kind of like a secret code. Keep it secure because anyone with access to the URL can notify your Discord channel.</li>
</ul>
<p>That's it for setting up the webhook on Discord! In the next section, we'll show you how to configure your GitHub repository to send notifications to your Discord webhook.</p>
<h1 id="heading-connect-your-github-repository-to-your-discord-webhook"><strong>Connect Your GitHub Repository to Your Discord Webhook</strong></h1>
<p>Now that you've set up your webhook on Discord, you need to connect it to your GitHub repository so that you can receive notifications on your Discord channel. Follow these steps to do the same:-</p>
<ul>
<li><p>Select any one of your GitHub repositories and go to the <code>settings</code> tab and select</p>
<p>  <code>Webhook</code> tab.</p>
</li>
<li><p>Click on <code>Add Webhook</code> and enter the webhook URL from discord to payload URL space. And most important step add <code>/github</code> to the end of that URL.  </p>
<p>  for example: <code>https://discord.com/api/webhooks/104353453497/fmerooergkmrekgmergoemgergmergo-efoerjnrej/github</code></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676829254726/be266224-6b6c-4d0c-8ffb-5db17a2595b8.png" alt="Enter the webhook url" class="image--center mx-auto" /></p>
<ul>
<li><p>Configure the webhook to listen for the events you want to receive notifications for, such as pull requests, issues, or commits. I like to receive everything, but you can customize it.</p>
</li>
<li><p>Save the webhook and test it by making a change to your codebase and verifying that you receive a notification in your Discord channel.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676830965900/a67b4b44-508e-4b34-8a7d-63d8eba38083.png" alt class="image--center mx-auto" /></p>
<p>That completes the setup of the GitHub repository and Discord webhook connection! You can use these steps to enable notifications for any activity on your GitHub repository on Discord. We'll go over some suggestions for personalising your notifications to make them more useful in the following section.</p>
<h2 id="heading-customize-your-github-notifications"><strong>Customize Your GitHub Notifications</strong></h2>
<p>Now that you're receiving notifications on your Discord channel for activity on your GitHub repository, you may want to customize them to make them more useful. Some of the tips are given below:-</p>
<ul>
<li><p>Modify the webhook settings to receive notifications for only the events you care about. To do that, go to your GitHub repository's <code>Settings</code> page and select the "Webhooks" tab to change the webhook settings. Click the <code>Edit</code> button next to the Discord webhook you generated. The webhook can then be set up to listen to particular events from there.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676831425654/22e8062b-c13d-4adf-b325-09bf3b1a59c5.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<h1 id="heading-conclusion">Conclusion</h1>
<p>We've demonstrated how to configure GitHub notifications on your Discord channel in this article. You won't need to frequently check GitHub if you follow the instructions in this guide to keep up with activity in your GitHub repositories.</p>
<p>To deliver notifications to your Discord channel, we first created a webhook on Discord, which offers a special Address. We then instructed GitHub to deliver notifications to the webhook URL by adding the webhook URL to our GitHub repository's settings. The notification messages' format was then altered to make them easier to read. We can add the details we wish to see in our notifications by altering the JSON payload that is provided to the Discord webhook.</p>
<p>In case you encounter problems along the road, we have included some troubleshooting advice. These pointers ought to help you fix any problems and enable GitHub alerts for your Discord channel. You can expedite your development workflow and maintain project updates by utilising GitHub and Discord together. We sincerely hope that this guide was useful to you, and we strongly advise you to experiment with various webhook settings to discover the configuration that best suits your needs.</p>
<p>Thank you for reading, and happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[Deploying FastAPI application to Render]]></title><description><![CDATA[Recently, I came to know that Heroku is going to stop supporting free services. I have almost all the projects running in Heroku and I never tried any services. Many people pointed out that Render is the best free alternative to the Heroku. So I am g...]]></description><link>https://blog.akashrchandran.in/deploying-fastapi-application-to-render</link><guid isPermaLink="true">https://blog.akashrchandran.in/deploying-fastapi-application-to-render</guid><category><![CDATA[FastAPI]]></category><category><![CDATA[Python]]></category><category><![CDATA[deployment]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[python beginner]]></category><dc:creator><![CDATA[Akash R Chandran]]></dc:creator><pubDate>Tue, 01 Nov 2022 12:30:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1667305548960/X3lhH5FpM.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently, I came to know that Heroku is going to stop supporting free services. I have almost all the projects running in Heroku and I never tried any services. Many people pointed out that <a target="_blank" href="https://render.com/">Render</a> is the best free alternative to the Heroku. So I am giving it a try by hosting a FastAPI application. Render seems to directly support python frameworks like Flask, Django etc as their documentation mentions them. But we should be able to host FastAPI app as it supports building any python app, we just need to change the starting command. Let's get into it without wasting another minute.</p>
<h1 id="heading-creating-renderhttpsrendercom-account">Creating <a target="_blank" href="https://render.com/">Render</a> Account</h1>
<p>To host on Render, you'll need to sign up or create an account. It's free and supports direct login using google, GitHub and GitLab account. Or you can use email and password to signup. You need to verify your email to get full access to the platform. Just head to <a target="_blank" href="https://dashboard.render.com/register">render/register</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667276301389/gt22ZUVp5.png" alt="image.png" /></p>
<h1 id="heading-need-for-github-or-gitlab-account">Need for GitHub or GitLab account</h1>
<p>It's easier to deploy an application that has its source code hosted on GitHub or GitLab. Render connects with GitHub or GitLab to deploy your apps and websites automatically on every push to your project. This is very useful, as you don't have to manually deploy every time you make a change. You can either connect <a target="_blank" href="https://github.com/signup">GitHub</a> or <a target="_blank" href="https://gitlab.com/users/sign_up">GitLab</a> or both. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667288724821/nJSpN9UyJ.png" alt="image.png" /></p>
<h1 id="heading-lets-make-a-simple-api-using-fastapi">Let's make a simple API using FastAPI</h1>
<p>We need an application to deploy to the Render. Let's build a simple API app which echos <code>Hello World</code>.</p>
<h2 id="heading-setting-up-environment">Setting up environment</h2>
<p>You'll need to download and install <a target="_blank" href="https://www.python.org/">Python3</a> to your local machine. It's better to set up a virtual environment for the application.</p>
<h3 id="heading-windows">Windows</h3>
<p>For windows, just head to <a target="_blank" href="https://www.python.org/downloads/">python.org</a> and download the latest EXE file and install. Installation is pretty well interactive, you just need to follow the instructions shown.</p>
<p>Next, create a folder in your preferred directory and name <code>simple-api</code>. Next to set up virtual environment enter the command opening terminal or CMD.</p>
<pre><code class="lang-bash">py -3 -m venv .venv
.venv\scripts\activate
</code></pre>
<h3 id="heading-linux-or-mac-os">Linux or Mac OS</h3>
<blockquote>
<p>Most of the Linux Distributions come with python3 be installed by default, just check if it exists by using command</p>
</blockquote>
<pre><code>python3 --version
</code></pre><p>For mac users just head to <a target="_blank" href="https://www.python.org/downloads">python.org</a> and download the .pkg file and start installing.</p>
<p>Next to set up virtual environment, on Linux sometimes we need to install extra library. To do the same, just enter the command in your terminal. </p>
<pre><code class="lang-bash">sudo apt-get install python3-venv
</code></pre>
<p>Next, to initialize and activate a virtual environment on Mac and Linux, use the commands below.</p>
<pre><code class="lang-bash">python3 -m venv .venv
<span class="hljs-built_in">source</span> .venv/bin/activate
</code></pre>
<h1 id="heading-installing-requirements">Installing requirements</h1>
<p>Make sure your package manager that is <code>pip</code> is up-to-date.</p>
<pre><code class="lang-bash">python -m pip install --upgrade pip
</code></pre>
<p>Now install FastAPI, using <code>pip</code></p>
<pre><code class="lang-bash">pip install fastapi
</code></pre>
<p>FastAPI also requires an ASGI server, for production, such as Uvicorn or Hypercorn. I personally just use Uvicorn. </p>
<pre><code class="lang-bash">pip install <span class="hljs-string">"uvicorn[standard]"</span>
</code></pre>
<h1 id="heading-coding-the-api">Coding the API</h1>
<p>Open the folder in any text editors, you can use notepad or advanced IDE's like VS Code or Sublime Text 4. Make a new file called <code>main.py</code> and we use this file to write the code in.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667297849372/ABQUYVOTQ.png" alt="image.png" /></p>
<p>Just copy and paste the below lines to the file. If you're good with python or professional, then you can add or modify, making the API better.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI

app = FastAPI()

<span class="hljs-meta">@app.get("/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_root</span>():</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"Hello"</span>: <span class="hljs-string">"World"</span>}
</code></pre>
<p>Save the file. Let's try out the simple-api using the command: </p>
<pre><code class="lang-bash">uvicorn main:app --reload
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667298287004/x2tXl1-jA.png" alt="image.png" /></p>
<p>Head to <code>localhost:8000</code> or <code>http://127.0.0.1:8000</code>. You should see the <code>Hello World</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667298527955/vWaggp7uH.png" alt="image.png" /></p>
<p>All done. Now we just need to create some extra files which are need by Render to identify it as a python application.</p>
<h1 id="heading-creating-requirementstxt">Creating Requirements.txt</h1>
<p>Usually I use external library <a target="_blank" href="https://pypi.org/project/pipreqs/">pipreqs</a>, but you can just simply type  <code>fastapi</code> and <code>uvicorn</code> in the requirements.txt file. When deploying, render will install the latest version of these modules.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667299816413/yHl-oQCm4.png" alt="image.png" /></p>
<h1 id="heading-creating-a-gitignore-file">Creating a .gitignore file</h1>
<p><code>.gitignore</code> file helps to avoid uploading of unwanted or private files to the git clients such as GitHub or GitLab. When sharing your code with others, there are often files or parts of your project, you do not want to share. So these files or folders can be mentioned in the .gitignore file.</p>
<p>For this simple-api we don't want to upload <code>.venv</code> and <code>__pycache__</code> to the GitHub. So we mention them in the .gitignore file like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667300636574/GVe_fPtPG.png" alt="image.png" /></p>
<h1 id="heading-upload-to-github-or-gitlab">Upload to GitHub or GitLab</h1>
<p>I am using the GitHub here, but you can use GitLab as well. I have installed <a target="_blank" href="https://git-scm.com/download/">git</a>, and I have connected it to my GitHub account. You'll find many articles on how to do it, just google it. If you're using Visual Studio then it has in built GitHub plugin which makes it way easier.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667300190867/CSsAfm85e.png" alt="image.png" /></p>
<p>I have successfully uploaded to GitHub, you can find mine at <a target="_blank" href="https://github.com/akashrchandran/simple-api">akashrchandran/simple-api</a>. You should definitely add a readme.md to the repo, I will do it later.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667300972758/ehibPeKFM.png" alt="image.png" /></p>
<h1 id="heading-deploying-to-rendercom">Deploying to Render.com</h1>
<p>As we are not deploying a static site, we should choose the option <code>Web Service</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667302637873/HPSesfyBd.png" alt="firefox_6Ko2SbNN6r.png" /></p>
<p>If you have connected your GitHub account, then you can just search the repository name and find it there.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667302811886/LFMSurQ_s.png" alt="image.png" /></p>
<p>Give a name to your web-service, then to select the region which is nearest to you, for me is Singapore. Leave all other values default. For the Start command, copy and paste the below: </p>
<pre><code class="lang-bash">uvicorn main:app --host 0.0.0.0 --port 10000
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667303284903/-M7LNMQEs.png" alt="image.png" /></p>
<p>Deploying may take some time, so patiently wait. After successful deployment, you should see the message like this below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667303740868/ZbGt5Czak.png" alt="image.png" /></p>
<p>Congratulations, you have successfully deployed your FastAPI application to the render platform. You can view the site I deployed <a target="_blank" href="https://simple-api-hr3q.onrender.com/">here</a>.</p>
<h1 id="heading-summary">Summary</h1>
<p>It was so simple to deploy a FastAPI based application to render. If you don't want to code or waste time on making a FastAPI based app, then you can try deploying mine. It is available on <a target="_blank" href="https://github.com/akashrchandran/simple-api">GitHub</a>.</p>
<p><a target="_blank" href="render.com">Render</a> may the Heroku alternative thing you're looking for, as it gives out almost the same free specifications as Heroku free tier. Do give it a try!</p>
<p>Thanks for reading...</p>
]]></content:encoded></item><item><title><![CDATA[Simple movies Telegram bot using PHP]]></title><description><![CDATA[I have been using telegram for almost 4+ years and have made more than 30 bots during this period. I made the first one in PHP and the rest were build in Python and JavaScript. So today I thought why not make a simple telegram bot in PHP. That's why ...]]></description><link>https://blog.akashrchandran.in/simple-movies-telegram-bot-using-php</link><guid isPermaLink="true">https://blog.akashrchandran.in/simple-movies-telegram-bot-using-php</guid><category><![CDATA[PHP]]></category><category><![CDATA[PHP7]]></category><category><![CDATA[telegram bot]]></category><category><![CDATA[telegram]]></category><category><![CDATA[php8]]></category><dc:creator><![CDATA[Akash R Chandran]]></dc:creator><pubDate>Mon, 24 Oct 2022 07:31:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666596352276/myWletKcu.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have been using telegram for almost 4+ years and have made more than 30 bots during this period. I made the first one in PHP and the rest were build in Python and JavaScript. So today I thought why not make a simple telegram bot in PHP. That's why we are going to make a movie's bot in PHP. Let's begin without wasting time.</p>
<h1 id="heading-gathering-requirements">Gathering Requirements</h1>
<p>Before we start making our bot, we need two things. It won't take much time, only few minutes. The things we need are:</p>
<ul>
<li><p>Telegram Bot Token</p>
</li>
<li><p>TMDB API key</p>
</li>
</ul>
<p>TMDB is the site from which we will pull the movie information from. It's free, you just need to register and fill some forms for an API key. So let's start gathering them.</p>
<h2 id="heading-get-telegram-bot-token">Get Telegram Bot token</h2>
<p>It's actually pretty simple to get the token from telegram. But first you need is a telegram account. I assume that you have one. Search for a bot named BotFather or use this <a target="_blank" href="https://tx.me/BotFather">link</a>. It should have a verified emoji in its name.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665903526384/b8KOpi0si.png" alt="image.png" /></p>
<p>Click on the bot and press start, or if you don't see that option, then type <code>/start</code>. I should greet you with a help message. You can read through that if you want to, it lists all details about what the bot can do. Next is, type <code>/newbot</code> and press send. It will ask for the name of the bot. After that it will ask for bot username which must be unique and should end in bot like mine here is <code>phpmoviesbot</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665906428085/hpped5n9A.png" alt="4HOD9NPmBo.png" /></p>
<p>Now you will receive a message which has a http API token. This was the token we were looking for, save it somewhere because we will need it later.</p>
<h2 id="heading-get-api-key-from-tmdb">Get API key from TMDB</h2>
<p>Head to <a target="_blank" href="https://www.themoviedb.org/">TMDB</a> and find register or join now. Then create an account. Then find settings and on the left side you will see an option named API, press that or use this <a target="_blank" href="https://www.themoviedb.org/settings/api">link</a>. You will need to fill a form about what you will be using the API for etc, just fill it yourself. After that you will get an API Key (v3 auth), save it somewhere we need it later.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665907514115/DQWWgGzYK.png" alt="ELYBOncHjY.png" /></p>
<p>Now that we have what we wanted, let's start with the programming side.</p>
<h1 id="heading-setting-up-webhook">Setting up webhook</h1>
<p>Setting up the webhook through which your Telegram bot will communicate is the next step in the creation process. In order to avoid having to query the API every few minutes (or seconds) to see whether, for example, a new message has been received, APIs use webhooks to notify you that something has occurred.</p>
<p>Telegram only makes use of one form of webhook, which delivers an <code>update</code> object each time something occurs. The webhook configuration is really simple.
There are only two things you must be aware of: your API token (which you should already have from step one), and the URL at which your bot will be hosted.
It will have a URL similar as <code>https://yourdomain.com/yourbot.php</code>.
To ensure that Telegram sends the webhook, insert <code>https</code> at the beginning of the URL.</p>
<p>Go to <code>https://api.telegram.org/&lt;TELEGRAM_BOT_TOKEN&gt;/setwebhook?url=https://yourdomain.com/yourbot.php</code> in a standard web browser now. Do replace <code>&lt;TELEGRAM_BOT_TOKEN&gt;</code> with your telegram bot token.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666591475038/-VkfPORHR.png" alt="image.png" /></p>
<h1 id="heading-coding-part">Coding part</h1>
<p>For this, I am assuming you know basic PHP syntax, formattings etc. Let's start then, we know that PHP script start with <code>&lt;?php</code> and ends with <code>?&gt;</code> and we write the code in between.
We are receiving webhook, therefore let's get input from the POST body: </p>
<pre><code class="lang-php">$content = file_get_contents(<span class="hljs-string">'php://input'</span>);
$update = json_decode ($content, <span class="hljs-literal">true</span>);
</code></pre>
<p>The received data is in JSON, to decode it to PHP based array, we have to use <code>json_decode</code> function. Now let's declare some variables which will store some, data from the update like username, chat ID etc.</p>
<pre><code class="lang-php">$chat_id = $update[<span class="hljs-string">'message'</span>][<span class="hljs-string">'chat'</span>][<span class="hljs-string">'id'</span>];
$message = $update[<span class="hljs-string">'message'</span>][<span class="hljs-string">'text'</span>];
$username = $update[<span class="hljs-string">'message'</span>][<span class="hljs-string">'from'</span>][<span class="hljs-string">'username'</span>];
</code></pre>
<p>We would have to send many messages, so let's define it directly as a function to make it easier to reuse.</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">send_message</span> (<span class="hljs-params">$chat_id, $message</span>) </span>{
    $apiToken = &lt;TELEGRAM_BOT_TOKEN&gt;;
    $text = urlencode($message);
    file_get_contents(<span class="hljs-string">"https://api.telegram.org/bot<span class="hljs-subst">$apiToken</span>/sendMessage?chat_id=<span class="hljs-subst">$chat_id</span>&amp;text=<span class="hljs-subst">$text</span>"</span>);
}
</code></pre>
<p>Replace the <code>&lt;TELEGRAM_BOT_TOKEN&gt;</code> with the telegram bot token you made. Let's test the bot with a <code>/start</code> message, to do that we have to write some more code, just an if statement as below.</p>
<pre><code class="lang-php"><span class="hljs-keyword">if</span> ($message == <span class="hljs-string">'/start'</span>) 
{
    send_message ($chat_id, <span class="hljs-string">"Hey @<span class="hljs-subst">$username</span>  \nsend me any query to search for the movie."</span>);
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666584937091/88jUlYr05.png" alt="image.png" /></p>
<p>It seems to be working. Now let's complete it by adding the movie information fetching part. I want to make the bot search everything we text we send except <code>/start</code>. So we just add else to the pre-existing if statement. I am expecting you know how to parse JSON.</p>
<pre><code class="lang-php"><span class="hljs-keyword">else</span> {
    $req = file_get_contents(<span class="hljs-string">"https://api.themoviedb.org/3/search/movie?api_key=&lt;TMDB_API_KEY&gt;&amp;language=en-US&amp;page=1&amp;query=<span class="hljs-subst">$message</span>"</span> );
    $movie = json_decode ( $req, <span class="hljs-literal">true</span> )[<span class="hljs-string">'results'</span>];
    <span class="hljs-keyword">if</span> ($movie) {
        $movie = $movie[<span class="hljs-number">0</span>];
        $title = $movie[<span class="hljs-string">'title'</span>];
        $overview = $movie[<span class="hljs-string">'overview'</span>];
        $popularity = $movie[<span class="hljs-string">'popularity'</span>];
        $release_date = $movie[<span class="hljs-string">'release_date'</span>];
        $vote_count = $movie[<span class="hljs-string">'vote_count'</span>];
        send_message($chat_id, <span class="hljs-string">"
        Title: <span class="hljs-subst">$title</span>
        Description: <span class="hljs-subst">$overview</span>
        Popularity : <span class="hljs-subst">$popularity</span>
        Release Date : <span class="hljs-subst">$release_date</span>
        Votes: <span class="hljs-subst">$vote_count</span>"</span>);
    } 
    <span class="hljs-keyword">else</span> {
        send_message($chat_id, <span class="hljs-string">"Couldn't find any movie with that name!"</span>);
    }
</code></pre>
<p>Replace <code>&lt;TMDB_API_KEY&gt;</code> with the TMDB API KEY we gathered. Now let's try the bot, by sending a movie name.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666590852520/1b-UXeM8D.png" alt="image.png" />
Works perfectly, You can add more functions to it, but for now I am stopping it here.</p>
<h1 id="heading-summed-up">Summed up</h1>
<p>We learnt to create a small bot using webhooks. I will add an article about host the bot, for free, on vercel. The entire code for the bot is available below.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
$content = file_get_contents (<span class="hljs-string">'php://input'</span>);
$update = json_decode ($content, <span class="hljs-literal">true</span>);
$chat_id = $update[<span class="hljs-string">'message'</span>][<span class="hljs-string">'chat'</span>][<span class="hljs-string">'id'</span>];
$message = $update[<span class="hljs-string">'message'</span>][<span class="hljs-string">'text'</span>];
$username = $update[<span class="hljs-string">'message'</span>][<span class="hljs-string">'from'</span>][<span class="hljs-string">'username'</span>];

<span class="hljs-keyword">if</span> ($message == <span class="hljs-string">'/start'</span>) {
    send_message ($chat_id, <span class="hljs-string">"Hey @<span class="hljs-subst">$username</span>  \nsend me any query to search for the movie."</span>);
} <span class="hljs-keyword">else</span> {
    $req = file_get_contents(<span class="hljs-string">"https://api.themoviedb.org/3/search/movie?api_key=&lt;TMDB_API_KEY&gt;&amp;language=en-US&amp;page=1&amp;query=<span class="hljs-subst">$message</span>"</span> );
    $movie = json_decode ( $req, <span class="hljs-literal">true</span> )[<span class="hljs-string">'results'</span>];
    <span class="hljs-keyword">if</span> ($movie) {
        $movie = $movie[<span class="hljs-number">0</span>];
        $title = $movie[<span class="hljs-string">'title'</span>];
        $overview = $movie[<span class="hljs-string">'overview'</span>];
        $popularity = $movie[<span class="hljs-string">'popularity'</span>];
        $release_date = $movie[<span class="hljs-string">'release_date'</span>];
        $vote_count = $movie[<span class="hljs-string">'vote_count'</span>];
        send_message($chat_id, <span class="hljs-string">"
        Title: <span class="hljs-subst">$title</span>
        Description: <span class="hljs-subst">$overview</span>
        Popularity : <span class="hljs-subst">$popularity</span>
        Release Date : <span class="hljs-subst">$release_date</span>
        Votes: <span class="hljs-subst">$vote_count</span>"</span>);
    } 
    <span class="hljs-keyword">else</span> {
        send_message($chat_id, <span class="hljs-string">"Couldn't find any movie with that name!"</span>);
    }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">send_message</span> (<span class="hljs-params">$chat_id, $message</span>) </span>{
    $apiToken = &lt;TELEGRAM_BOT_TOKEN&gt;;
    $text = urlencode($message);
    file_get_contents(<span class="hljs-string">"https://api.telegram.org/bot<span class="hljs-subst">$apiToken</span>/sendMessage?chat_id=<span class="hljs-subst">$chat_id</span>&amp;text=<span class="hljs-subst">$text</span>"</span>);
}
<span class="hljs-meta">?&gt;</span>
</code></pre>
<p>Thanks for reading.</p>
]]></content:encoded></item><item><title><![CDATA[Some less popular git commands]]></title><description><![CDATA[Introduction
Git is pretty much used by every developer nowadays. Personally, even after using it for approximately two years, I continue to discover new git features. So here are some of the commands I discovered, and seems they aren't popular enoug...]]></description><link>https://blog.akashrchandran.in/some-less-popular-git-commands</link><guid isPermaLink="true">https://blog.akashrchandran.in/some-less-popular-git-commands</guid><category><![CDATA[GitHub]]></category><category><![CDATA[Git]]></category><category><![CDATA[Git Commands]]></category><category><![CDATA[GitLab]]></category><category><![CDATA[Gitcommands]]></category><dc:creator><![CDATA[Akash R Chandran]]></dc:creator><pubDate>Sat, 15 Oct 2022 13:29:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1665817607501/m7w4Vud37.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>Git is pretty much used by every developer nowadays. Personally, even after using it for approximately two years, I continue to discover new git features. So here are some of the commands I discovered, and seems they aren't popular enough. Without wasting time, let's dive into it.</p>
<h1 id="heading-check-logs-but-in-easier-ways">Check logs but in easier ways</h1>
<p><code>git log</code> a useful tool for looking back and reading the history of every action taken with a repository. A git log's multiple settings can be utilized to narrow down history.
The git log typically contains a list of commits. And sometimes the list is so big it's hard to find anything we need. Let me show you an easier way to do the same, but the output is short yet brief.</p>
<h2 id="heading-git-log-oneline">git log --oneline</h2>
<p>It's super helpful to check the latest commits. With the <code>--oneline</code> flag, each commit is reduced to a single line. It just shows the commit ID and the first line of the commit message by default. The output should look like:</p>
<pre><code><span class="hljs-number">1266</span>f06 (origin/develop) updated readme
<span class="hljs-number">33</span>bf5fb Merge branch <span class="hljs-string">'develop'</span>
bd99bba fixed error
<span class="hljs-number">19389</span>a7 Merge pull request #<span class="hljs-number">5</span> <span class="hljs-keyword">from</span> akashrchandran/develop
<span class="hljs-number">5</span>a2258e added exceptions
<span class="hljs-number">9</span>dbb9de updated readme
</code></pre><h2 id="heading-git-shortlog">git shortlog</h2>
<p>A modified version of the git log command called <code>git shortlog</code> is used mostly to make release notifications. It displays the first line of each commit message and groups each commit according to author. This makes it simple to determine who has been working on what.</p>
<pre><code>Akash R Chandran (<span class="hljs-number">4</span>):
      Initial commit
      fixed all errors
      added gitignore
      Added support <span class="hljs-keyword">for</span> heroku deployment

Paulo Martini(<span class="hljs-number">3</span>):
      added files via upload
      updated
      fixed requests errors
</code></pre><h2 id="heading-git-log-graph">git log --graph</h2>
<p>The branch structure of the commit history is represented via an ASCII graph when the <code>--graph</code> option is used. To make it simpler to determine which commit belongs to which branch, this is frequently used in conjunction with the <code>--oneline</code>  and <code>--decorate</code> commands: </p>
<pre><code>*   <span class="hljs-number">64</span>f95a3 (HEAD -&gt; main, origin/main, origin/HEAD) Merge pull request #<span class="hljs-number">6</span> <span class="hljs-keyword">from</span> akashrchandran/develop
|\
| * <span class="hljs-number">1266</span>f06 (origin/develop) updated readme
* | <span class="hljs-number">33</span>bf5fb Merge branch <span class="hljs-string">'develop'</span>
|\|
| * bd99bba fixed error
* | <span class="hljs-number">19389</span>a7 Merge pull request #<span class="hljs-number">5</span> <span class="hljs-keyword">from</span> akashrchandran/develop
|\|
| * <span class="hljs-number">5</span>a2258e added exceptions
|/
* <span class="hljs-number">9</span>dbb9de updated readme
</code></pre><p>To get more info on <code>git log</code> you can visit <a target="_blank" href="https://www.atlassian.com/git/tutorials/git-log">here</a>.</p>
<h1 id="heading-switching-branches">Switching branches</h1>
<p>The <code>git checkout</code> command can be used for a wide range of purposes.
Because of this, the Git community has decided to release a new command: <code>git switch</code>.
It was designed primarily for the process of switching branches, as the name suggests. </p>
<pre><code class="lang-bash">$ git switch develop
Switched to a new branch <span class="hljs-string">'develop'</span>
branch <span class="hljs-string">'develop'</span> <span class="hljs-built_in">set</span> up to track <span class="hljs-string">'origin/develop'</span>.
</code></pre>
<h2 id="heading-switch-back-and-forth-between-two-branches">Switch back and forth between two branches</h2>
<p><code>git switch</code> makes it very easy to switch between the same branches back to back. It doesn't even need the branch name to switch, just remove branch name and put a hyphen<code>(-)</code>:</p>
<pre><code class="lang-bash">$ git switch -
Switched to branch <span class="hljs-string">'main'</span>
Your branch is up to date with <span class="hljs-string">'origin/main'</span>.
</code></pre>
<p>Using the same command again will switch back to <code>develop</code>.</p>
<h1 id="heading-checking-the-changes-made-to-file">Checking the changes made to file</h1>
<p>The function of diffing outputs the differences between two input data sets.
A diff operation is performed on Git data sources when the Git command <code>git diff</code> is invoked. Commits, branches, files, and other types of data sources are examples. This document will go over typical <code>git diff</code> commands and diffing work flow patterns. <code>git diff</code>, <code>git status</code>, and <code>git log</code> are frequently used to examine the present state of a Git repository. </p>
<pre><code class="lang-bash">$ git diff 
diff --git a/spotify.php b/spotify.php
index 6987fef..bc766cf 100644
--- a/spotify.php
+++ b/spotify.php
@@ -64,6 +64,7 @@ class Spotify
                curl_setopt(<span class="hljs-variable">$ch</span>, CURLOPT_RETURNTRANSFER, TRUE);
                curl_setopt(<span class="hljs-variable">$ch</span>, CURLOPT_URL, <span class="hljs-variable">$formated_url</span>);
                <span class="hljs-variable">$result</span> = curl_exec(<span class="hljs-variable">$ch</span>);
+               <span class="hljs-built_in">echo</span> <span class="hljs-variable">$result</span>;
                <span class="hljs-built_in">return</span> <span class="hljs-variable">$result</span>;
        }
 }
</code></pre>
<h1 id="heading-restore-to-an-older-version-of-the-file">Restore to an older version of the file</h1>
<p>Another extremely useful option available with the git restore command is "—source."
You can quickly restore any earlier version of a particular file with the use of this option: </p>
<pre><code class="lang-bash">git restore --<span class="hljs-built_in">source</span> 6bcf266b index.html
</code></pre>
<h3 id="heading-adding-comments-to-your-commits">Adding comments to your commits</h3>
<p>To preserve a better development history, developers typically write clear and self-explanatory commit notes. Thanks to well-liked commit conventions, some development teams even automatically produce release notes with commit messages.
How can I include some extra notes in a commit?
Commit message additions will be reflected on remote Git hosting GUIs.
How can I record a message for a CI/CD server or add a hidden note to remember about any technical work? We can add extra comments for commits with the help of the built-in Git notes functionality.</p>
<p>To connect a note to the current commit, issue the following command:</p>
<pre><code class="lang-bash">$ git notes add -m <span class="hljs-string">"This is a test comment"</span>
</code></pre>
<p>By omitting the -m option, you can use the editor programme to write a multiline, lengthy note.
The git notes show command allows you to view the most recent note.
Additionally, the git log command by default displays notes.
Git notes were previously supported by GitHub as comments, but they are now deprecated in favour of web-based comments.</p>
<p>Git does not automatically push or pull notes, but you can manage remote notes explicitly using the following commands:</p>
<pre><code class="lang-bash">git push &lt;remote&gt; refs/notes/*
git fetch origin refs/notes/*:refs/notes/*
</code></pre>
<h1 id="heading-print-the-sha1-hashes">Print the SHA1 hashes</h1>
<p><code>git rev-parse</code> is an ancillary plumbing command primarily used for manipulation.
One common usage of <code>git rev-parse</code> is to print the SHA1 hashes given a revision specifier. In addition, it has various options to format this output, such as --short for printing a shorter unique SHA1.</p>
<pre><code class="lang-bash">$ git rev-parse HEAD
64f95a3edf8ecaf1f874b9a25fb7312a722f463a
</code></pre>
<h1 id="heading-conclusion">Conclusion</h1>
<p>These commands are mostly for better productivity and simplicity. It's good if you know what they do. Git is well known these days, but many of its powers are still unknown to the public. It's true that you can "survive" with a handful of commands like commit, push, and pull.</p>
<p>Thanks for reading 😊.</p>
]]></content:encoded></item></channel></rss>