Select Page
Laravel Queue: archiving PDF Files

Laravel Queue: archiving PDF Files

I’ve been working with Laravel Queues lately and it is indeed a pleasant experience. If you are not yet familiar with Laravel Queue you can read more about it here.

Queues are typically used in tasks that require an intensive amount of resources. For example, generating a large CSV report might take a while to finish. You can delegate the task in a queue that runs as a background task (managed by Supervisor) and just give the users feedback over time. This way, end-users will not wait for a long time for the report to finish. Most, users will even think that there your application might be crashing.

In one of my projects I need to create a Zip Archive of PDF Files for about hundreds of users. Generating PDF Files usually takes time and resource. As such, I do it via Queue. Each Job not only generates PDF File it also updates the Zip Archive.

GeneratePDFResult.php:

<?php

namespace App\Jobs;

use App\Models\Result;
use App\ResultCheckers\NISResultChecker;
use Illuminate\Bus\Batchable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Storage;
use PDF;
use ZipArchive;

// Supports local driver, for now.
class GeneratePDFResult implements ShouldQueue
{
    use Batchable, Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    private const CACHE_TTL = 31556926;
    public $tries = 1;
    public $result;

    public function __construct(Result $result)
    {
        $this->result = $result;
    }

    public function handle()
    {
        $payload = [
            'scores' => $this->result->scores,
            'details' => $this->result->details,
        ];
        
        $batchId = $this->batch()->id;
        $pdf = PDF::loadView('neuro_report', [ 'payload' => $payload ])->setPaper('legal', 'portrait');
        $fileName =  sprintf('%s %s %s.pdf',
            $payload['details']['exam_date'],
            $payload['details']['first_name'],
            $payload['details']['last_name'],
        );
        
        $pdfFilePath = '/results/' . $batchId . '/' . $fileName;
        Storage::disk('local')->put($pdfFilePath, $pdf->output());

        $this->updateZipArchive($batchId, $pdfFilePath, $fileName);
    }
    
    private function updateZipArchive($batchId, $pdfFilePath, $fileName)
    {
        $zip = new ZipArchive();
        $zipFilePath = Storage::disk('local')->path('/results/' . $this->batchId . '/' . $this->batchId . '.zip');
        $pdfLocalFilePath = Storage::disk('local')->path($pdfFilePath);

        if ($zip->open($zipFilePath, ZipArchive::CREATE) === TRUE) {
            $zip->addFromString($fileName, Storage::disk('local')->get($pdfFilePath));
            $zip->close();
        } else {
            logger('Failed opening zip file:' . $zipFilePath);
        }
    }
}

As you’ve noticed, I used a 3rd party library called laravel-dompdf to generate PDF Files from HTML. I’ve used the ZipArchive class of PHP for creating and updating the Zip Archives. I’ve batched the jobs so that they are logically grouped and I can monitor them as a whole. Also you can notice how the Storage face works perfectly with these two.

That’s it! I hope you learn something new that you can apply on your backend applications.

Javascript optional chaining

Javascript optional chaining

2020 is a hell of a year for most of us but not with Javascript as it has introduced a lot of new cool features including one of my favorites: Optional Chaining.

If you haven’t tried Typescript before, this might be new to you but this functionality is very much used in Typescript. Let’s dive into the code, shall we?

Suppose you have the following code:

const human = { job: null }

What if you want to access a particular property of job like so:

const salary = human.job.salary

This code will throw an error telling us that it can’t read salary of null. Typically devs will use ternary operator to avoid the error like so:

const salary = human.job ? human.job.salary : undefined

While this will work the code will be easily repetitive when you are trying to read lots of properties from a huge object that might or might not exist. Thanks for Javascript, you can now do it elegantly in your code like so:

const salary = human.job?.salary

The code will not produce an error. If the job property happened to not exist, then it will just return an undefined.

So where’s the chaining part? Suppose human might or might not exist then your code can look as following:

const salary = human?.job?.salary // outputs undefined

That’s it for Optional Chaining.  2020 for Javscript have been awesome there are other of cool stuffs that have been introduced like Object.fromEntries, matchAll(), dynamic import,  Promise.allSettled, Null Coalescing and others.

Let’s keep rockin with Javascript!

Javascript optional chaining

TF is noop and what’s the use of it (JS)?

Have you encountered a function or a variable that is called noop in any source code you are reading? Have you asked yourself what the hell is that for?

Well, noop just means NO OPERATION. Meaning do not do something, return undefined or return an empty function. It is literally simple as that.

So what is the need for this noop at all?

Backup callback / Legacy code

Supposed you have a function like that accepts a function like so:

function displayInfo(callbackFn) {
  // execute callbackFn and and perform other complex things
}

and supposed your code will run in different environments like desktop, web, and mobile.

Now you need to provide displayInfo() a valid callback function that might only be available for a particular environment. Typically developers will create an empty function that will do nothing, thus noop. Like so:

 const callbackFn = environmentFn ? environmentFn : () => {} 

But writing an empty function every time you need it is not good in the eyes right? As such, developers separate it on a separate function like so:

const noop = () => {} 

That’s it! If ever you think of another usage of the noop function feel free to comment it below. 

It’s okay to be unproductive

It’s okay to be unproductive

Or is it? Maybe sometimes.

Have you ever felt that you just want to spend the rest of the weekends just lying on the bed? binge-watch Netflix? play your favorite computer games? But have you noticed that after doing nothing productive in a day there is somehow a weird feeling of guilt? I have the same feeling too. I noticed that there are several factors when I felt this and those are what I listed below:

 

I used to be too much productive

I have a full-time job and 2 side hustles all of which are related to development. In my regular job, I spent hours coding features from different repositories (group of codes based on functions), and during the weekends I do my other projects with my clients. Some days, I answer on-call support during weekdays too.  This routine of being productive is tiring but when you get used to it, your self tends to be missing something if ever you decided to be lazy for a day or two.

I loss my motivation

I used to be so motivated when working especially that I love what I am creating. But this year is the worst for me. I lost my favorite person in the entire world, my mom. Now, I am working just for the sake of earning a living.  This loss of motivation made me feel guilty even more knowing I haven’t accomplished anything of value and here I am lying in the bed browsing social media like never before.

But it’s okay…

Sometimes, taking it easy is the best way you can reward yourself. It is not your job to be the best every single day of your life.  Do not be too hard on yourself if there are days that you just feel like doing nothing.  Is it a sin to take a break after a hell of a week in the office? or after many troubles life thrown at you? Definitely NOT. Binge-watch your favorite Netflix series, play the games you’ve always wanted to play but you are just too busy, read a book while sipping coffee overlooking a beautiful nature view. Do these things with zero guilt. Take your time to reset and give yourself all the time you need. What’s important at the end of the day is your happiness and your peace of mind.

Believe in Dreams

Believe in Dreams

As I am checking on my things, I have seen my wallet from 10 years ago. Inside, I saw a note that says “Believe in Dreams.”

I smile because I remember who gave me this. It was my ex-girlfriend. She gave me this when we separated ways. It’s somehow what I needed to be reminded of right now. To still believe in my dreams and that everything will be all right.

This year is the worst year of my life. My mom died and everything started to fell apart. My dream, my motivation, my happiness. Everything seems to be getting out of hand. I have no hope, no inspiration, and no motivation. But I hope someday, I will start to believe in dreams again.

To my ex-girlfriend, if it happened you read this, thank you for everything and sorry for everything I’ve done. My immaturity, my mistakes, my selfishness, everything. I wish you nothing but success and happy life. I know it’s been 10 years since to say all of this but many words are still left unsaid.