<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mohamed Said</title>
    <description>The latest articles on Forem by Mohamed Said (@themsaid).</description>
    <link>https://forem.com/themsaid</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F321235%2F6f586cc6-ef09-4b08-b994-5114a7fcd57b.jpg</url>
      <title>Forem: Mohamed Said</title>
      <link>https://forem.com/themsaid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/themsaid"/>
    <language>en</language>
    <item>
      <title>Asynchronous PHP — Multiprocessing, Multithreading &amp; Coroutines</title>
      <dc:creator>Mohamed Said</dc:creator>
      <pubDate>Thu, 01 Apr 2021 11:08:36 +0000</pubDate>
      <link>https://forem.com/themsaid/asynchronous-php-multiprocessing-multithreading-coroutines-32m2</link>
      <guid>https://forem.com/themsaid/asynchronous-php-multiprocessing-multithreading-coroutines-32m2</guid>
      <description>&lt;p&gt;Let's take a look at this typical PHP code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'data.location/products'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nv"&gt;$names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nv"&gt;$names&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$names&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We send an HTTP request that returns an array of items, then we store the name of each item in a &lt;code&gt;$names&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;Executing this function will take time that's equal to the duration of the request plus the time it took to build the array. What if we want to run this function multiple times for different data sources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;names&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/products'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;names&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/users'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this code takes time that's equal to the duration of both functions combined:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP request to collect products: 1.5 seconds
Building products names array:    0.01 seconds
HTTP request to collect users:    3.0 seconds
Building users names array:       0.01 seconds
Total:                            4.52 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is called Synchronous code execution, or executing one thing at a time. To make this code run faster, you may want to execute it asynchronously. So what are our options if we want to achieve that?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Execute in different processes.&lt;/li&gt;
&lt;li&gt;Execute in different threads.&lt;/li&gt;
&lt;li&gt;Execute in coroutines/fibers/green-threads.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Execute in different processes
&lt;/h1&gt;

&lt;p&gt;Running each of these function calls in a separate process gives the operation System the task of running them in parallel. If you have a multi-core processor, we all have now, and there are 2 idle cores sitting around, the OS will use both cores to execute the processes in parallel (at the same time). However, in most cases there are other processes running on the machine that need to use the available cores. In that case, the OS will share the CPU time between those processes. In other words, the available cores will switch between processing our two processes and other processes. In that case, our processes will be executed concurrently.&lt;/p&gt;

&lt;p&gt;The execution time for those two processes will be something like 3.03 seconds (not 100% accurate I know). This conclusion is based on the fact that the slowest request takes 3 seconds, the 2 network calls took 10 milliseconds, and both loops for collecting names each takes 10 milliseconds.&lt;/p&gt;

&lt;p&gt;The execution inside the core will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Switch to process 1
Start HTTP request to collect products
Switch to process 2
Start HTTP request to collect users
Switch to process 1
If a response came, then build products names array
Switch to process 2
If a response came, then build users names array
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So while the CPU waits for a response on the first request, it sends the second request. Then waits until any of the requests return before it continues the process.&lt;/p&gt;

&lt;p&gt;Multiprocessing is an easy way to achieve asynchronous code execution in PHP. However, it's not the most performant. Because creating processes is relatively expensive and each process requires its own private space in memory. Switching between processes (context switching) also has an overhead.&lt;/p&gt;

&lt;p&gt;You could use Laravel queues and start a fixed number of workers (processes) and keep them alive to process your tasks. That way you won't have to create new processes each time you want to run something async. However, the overhead of context switching and memory allocation will still apply. Also with workers, you need to manage how you can receive the results from your code execution inside the workers.&lt;/p&gt;

&lt;p&gt;Multiprocessing and Laravel workers have been doing great for millions of apps. So when I say that it's not the most performant I'm speaking relative to the other options. Don't just read this and think that multiprocessing and queues are bad. Ok?&lt;/p&gt;

&lt;h1&gt;
  
  
  Execute in different threads
&lt;/h1&gt;

&lt;p&gt;A process has its own private space in memory, a process may have multiple threads. All threads live in the same memory space as the process. That makes spawning threads less expensive than spawning processes.&lt;/p&gt;

&lt;p&gt;However, context switching still happens. When you have too many threads, as the case with too many processes, everything on your machine will slow down. Because the CPU cores are switching between a lot of contexts.&lt;/p&gt;

&lt;p&gt;Also, with the same memory space being accessed by multiple threads at the same time, race conditions may happen.&lt;/p&gt;

&lt;p&gt;In addition to all this, multithreading in PHP is &lt;a href="https://github.com/krakjoe/pthreads/issues/929"&gt;not supported anymore&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Execute in coroutines/fibers/green-threads
&lt;/h1&gt;

&lt;p&gt;This "thing" has many names. But let's call it "coroutines" because it's the most used term.&lt;/p&gt;

&lt;p&gt;A coroutine is like a thread in that it shares the memory of the process it was created inside, but it's not an actual thread because the OS knows nothing about it. There's no context switching between coroutines on the OS level. The runtime controls when the switching happens, which is less expensive than the OS context switching.&lt;/p&gt;

&lt;p&gt;Let's convert our code to using coroutines. This code is for demonstration only, it won't work if you run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nf"&gt;go&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;names&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/products'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nf"&gt;go&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;names&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/users'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea behind coroutines is that the runtime is going to schedule running those callbacks concurrently. Inside each coroutine, the code may explicitly yield control to the runtime so it can run another coroutine. At any given time, only one coroutine is being executed.&lt;/p&gt;

&lt;p&gt;So if we break down our code, it comes to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;go&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'data.location/products'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// yields&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;go&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'data.location/users'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// yields&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The runtime will execute the first coroutine until it yields, then execute the second coroutine until it yields, and then go back to where it stopped in the first coroutine. Until all coroutines are executed. And then, it'll continue code execution in the regular synchronous fashion.&lt;/p&gt;

&lt;p&gt;Now you may have two question; first, when should the yielding happen? second, how do we make it happen?&lt;/p&gt;

&lt;p&gt;Inside each coroutine in our example there are two operations; one I/O bound and one CPU bound. Sending the HTTP request is an I\O bound operation, we're sending a request (input) and waiting for a response (output). The loop, on the other hand, is a CPU bound operation, we are looping over a set of records and calculating results. Calculations are done by the CPU, that's why it's called CPU bound.&lt;/p&gt;

&lt;p&gt;CPU bound work will take the same amount of time if it runs in the same process. The only way to make the work take less time is if you execute it in different processes or threads. On the other hand, I\O bound work can run concurrently inside the same process; while one I\O operation is waiting for output, another operation can start.&lt;/p&gt;

&lt;p&gt;Looking at our example, the execution inside the runtime will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start coroutine 1
Start HTTP request to collect products
Coroutine 1 yields
Switch to coroutine 2
Start HTTP request to collect users
Coroutine 2 yields
Switch to coroutine 1
If a response came, then build products names array
Switch to coroutine 2
If a response came, then build users names array
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using coroutines, we can take the time an I\O operation spends waiting and use it to do other work. By doing so, we are running all the coroutines concurrently.&lt;/p&gt;

&lt;p&gt;Now let's move to our second question: how do we make the yielding happen? We don't.&lt;/p&gt;

&lt;p&gt;Different frameworks and libraries must support asynchronous execution by yielding control whenever an I\O operation is waiting. There's a popular term for this that you should know "Non-blocking I\O". Libraries that communicate with databases, caches, filesystem, networking, etc... must be adapted to become non-blocking.&lt;/p&gt;

&lt;p&gt;If you use a blocking library inside a coroutine, it'll never yield and thus your coroutines will be executed synchronously. The main process will wait until the I\O operations receive the output before continuing with the rest of the program.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;There's a lot more to say about coroutines and asynchronous execution. My plan is to explore ways we can make Laravel play nicely with coroutines and share my findings in the process.&lt;/p&gt;

&lt;p&gt;Until then, embrace the synchronous code execution of PHP. It worked very well for over 25 years. Send I\O bound work that you need to cut to a queue worker and act on the results later. This should cover many of the use cases.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
    </item>
    <item>
      <title>Features and Changes Coming to Laravel 8's Queue System</title>
      <dc:creator>Mohamed Said</dc:creator>
      <pubDate>Fri, 04 Sep 2020 07:02:24 +0000</pubDate>
      <link>https://forem.com/themsaid/features-and-changes-coming-to-laravel-8-s-queue-system-5amg</link>
      <guid>https://forem.com/themsaid/features-and-changes-coming-to-laravel-8-s-queue-system-5amg</guid>
      <description>&lt;p&gt;Laravel 8 ships with cool new features as well as some changes to the queue system. In this post we'll look into these features and changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Changes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Backoff
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;retryAfter()&lt;/code&gt; method and the &lt;code&gt;retryAfter&lt;/code&gt; property of queued jobs, mailers, notifications, and listeners has been renamed to &lt;code&gt;backoff&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--delay&lt;/code&gt; option of the &lt;code&gt;php artisan queue:work&lt;/code&gt; command has been renamed to &lt;code&gt;--backoff&lt;/code&gt; as well.&lt;/p&gt;

&lt;p&gt;You should also know that you can now pass an array to the &lt;code&gt;backoff&lt;/code&gt; property to instruct the worker to implement an exponential backoff:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$backoff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Or return an array from the &lt;code&gt;backoff()&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;backoff&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Using an exponential backoff here, we instructed the worker to delay retrying the job 30 seconds after the first failure, then 60 seconds for each failure after that.&lt;/p&gt;

&lt;p&gt;You can also use an exponential backoff on the &lt;code&gt;queue:work&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan queue:Work --backoff=30,60
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Job Expiration
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;timeoutAt&lt;/code&gt; property of queued jobs, notifications, and listeners has been renamed to &lt;code&gt;retryUntil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;$retryUntil&lt;/code&gt; instructs the worker to keep retrying the job until a certain time in the future.&lt;/p&gt;

&lt;p&gt;You can add &lt;code&gt;retryUntil&lt;/code&gt; as a public property on the job class or a &lt;code&gt;retryUntil&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;retryUntil&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addDay&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  New Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Queued Closures
&lt;/h3&gt;

&lt;p&gt;You can now chain a &lt;code&gt;catch()&lt;/code&gt; method while dispatching a queued closure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Job logic...&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Throwable&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle Failure...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The closure provided to the &lt;code&gt;catch()&lt;/code&gt; method will be invoked if the job fails.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database Driver Reliability
&lt;/h3&gt;

&lt;p&gt;When releasing a job back to the queue while using the database queue driver, Laravel will perform the operation inside a transaction now. That means the job will not be deleted from the queue unless the new—released—instance is added. This decreases the chance of losing jobs significantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Redis Driver Efficiency
&lt;/h3&gt;

&lt;p&gt;When dispatching a group of jobs in bulk while using the redis queue driver, Laravel will perform the operation by sending a single command to redis. Previously, Laravel used to send multiple &lt;code&gt;rpush&lt;/code&gt; command to redis; one for each job.&lt;/p&gt;

&lt;h3&gt;
  
  
  Worker Graceful Termination
&lt;/h3&gt;

&lt;p&gt;Starting Laravel 8, workers will exit gracefully and call any terminating callbacks registered by &lt;code&gt;App::terminating()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Worker Self Termination
&lt;/h3&gt;

&lt;p&gt;In order to avoid memory leaks, it's a common practice to terminate your workers every now and then and let your process monitoring tool start new ones. This was usually done by adding a CRON job that runs the &lt;code&gt;queue:restart&lt;/code&gt; artisan command.&lt;/p&gt;

&lt;p&gt;In Laravel 8, you can instruct workers to exit after processing a certain number of jobs or after running for a specific number of seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;php&lt;/span&gt; &lt;span class="n"&gt;artisan&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;work&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Naming Workers
&lt;/h3&gt;

&lt;p&gt;You can now add a &lt;code&gt;--name&lt;/code&gt; option to the &lt;code&gt;queue:work&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;php&lt;/span&gt; &lt;span class="n"&gt;artisan&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;work&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;notifications&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This feature was mainly added to allow people to customize how the worker picks which queue to process jobs from at runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;popUsing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'notifications'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$pop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$queues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;atNight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
        &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'mail'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'webhooks'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
        &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'push-notifications'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'sms'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'mail'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'webhooks'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$queues&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$queue&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$job&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Job Batching
&lt;/h3&gt;

&lt;p&gt;Laravel's job batching allows you to dispatch a number of jobs to be processed in parallel by your workers. You can perform an action after all jobs in the batch are processed or if any of the batch jobs fail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Bus&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProcessFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProcessFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProcessFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can find more information on Job Batching in the &lt;a href="https://laravel.com/docs/master/queues#job-batching"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Job Chaining
&lt;/h3&gt;

&lt;p&gt;You can now dispatch a chain of jobs using the &lt;code&gt;Bus&lt;/code&gt; facade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Bus&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ExtractReports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GenerateReport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SendResults&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can also add a &lt;code&gt;catch()&lt;/code&gt; callback that'll be invoked if any of the jobs in the chain fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Bus&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ExtractReports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GenerateReport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SendResults&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle the chain failure.&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Horizon Balancing Rate
&lt;/h3&gt;

&lt;p&gt;Two new configuration options were added to Horizon; &lt;code&gt;balanceMaxShift&lt;/code&gt; and &lt;code&gt;balanceCooldown&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt; &lt;span class="s1"&gt;'environments'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'environment'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'supervisor-1'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'balanceMaxShift'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;balanceMaxShift&lt;/code&gt; sets the maximum number of worker processes to add or remove each time Horizon scales the workers pool. In previous versions on Horizon, only a single worker was added or removed, now you can control that number.&lt;/p&gt;

&lt;p&gt;As for &lt;code&gt;balanceCooldown&lt;/code&gt;, it sets the number of seconds to wait between each scaling action. This was hard-coded to 3 seconds in previous versions of Horizon.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt; &lt;span class="s1"&gt;'environments'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'environment'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'supervisor-1'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'balanceCooldown'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>laravel</category>
    </item>
    <item>
      <title>The Backend-for-frontend Pattern For Monoliths</title>
      <dc:creator>Mohamed Said</dc:creator>
      <pubDate>Sun, 24 May 2020 15:44:13 +0000</pubDate>
      <link>https://forem.com/themsaid/the-backend-for-frontend-pattern-for-monoliths-2535</link>
      <guid>https://forem.com/themsaid/the-backend-for-frontend-pattern-for-monoliths-2535</guid>
      <description>&lt;p&gt;The &lt;a href="https://twitter.com/dhh/status/962452557502201856"&gt;majestic monolith&lt;/a&gt; is how I build backends since I started. Microservices seemed like too much work for the small teams I worked with. However, some of the patterns used to build and service applications running in a microservice architecture can be useful for monoliths.&lt;/p&gt;

&lt;p&gt;One of these patterns is the backend-for-frontend pattern. The idea is to have a dedicated backend for your frontends. It can be a separate backend for each type of frontend or one backend for all frontends.&lt;/p&gt;

&lt;p&gt;To understand how this pattern can be useful, let's imagine we're building an online store. We have our backend exposing a public REST API, this API can be consumed by our web UI, mobile apps, and other 3rd party consumers. Authentication to our backend is done using OAuth2.0, all consumers must send a bearer token to protected routes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication
&lt;/h2&gt;

&lt;p&gt;Storing the authentication token in the mobile app is fine, but there's &lt;a href="https://www.rdegges.com/2018/please-stop-using-local-storage/"&gt;no way to store the tokens in the browser securely&lt;/a&gt;. Using a dedicated backend for our web frontend, we can use that BFF (Backend For Frontend) as a gateway to the actual backend and store the token in it.&lt;/p&gt;

&lt;p&gt;So to log the user in to our web frontend, the frontend will make a request to the BFF which will send a login request to the backend, receive the token, and then store it in the session.&lt;/p&gt;

&lt;p&gt;Communication between the web frontend and the BFF is authenticated using sessions, while the BFF communicates with the backend using token-based authentication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization
&lt;/h2&gt;

&lt;p&gt;Roles and permissions for an app that's used to make orders and browser products are different from ones for an app that's used to manage inventory and suppliers.&lt;/p&gt;

&lt;p&gt;Using a BFF for each type of client, we can run the authorization checks in the BFF and keep our backend as much open as we want it to be. Allowing us to build more clients in the future without having to change the backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aggregation
&lt;/h2&gt;

&lt;p&gt;To render a screen that displays all products, featured products, and recommended products. A client may need to make 3 requests to 3 different backend endpoints. Even if these requests are made concurrently, the client still has to send 3 requests and wait for the responses.&lt;/p&gt;

&lt;p&gt;Using a BFF, the client can make a single request to a /products-list endpoint on the BFF and the BFF will aggregate the response needed by making the 3 requests to the backend.&lt;/p&gt;

&lt;p&gt;Server-to-server communication will experience less latency and we can add a caching layer in the BFF which will make things even better.&lt;/p&gt;

&lt;h2&gt;
  
  
  BFF and Laravel
&lt;/h2&gt;

&lt;p&gt;In the following video, I discuss the BFF pattern and explain how we can implement it using Laravel.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/zazeGmFmUxg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>laravel</category>
    </item>
    <item>
      <title>Multi-tenancy in Laravel: Migrations, Testing, and switching tenants</title>
      <dc:creator>Mohamed Said</dc:creator>
      <pubDate>Wed, 29 Apr 2020 09:13:39 +0000</pubDate>
      <link>https://forem.com/themsaid/multi-tenancy-in-laravel-migrations-testing-and-switching-tenants-4cb8</link>
      <guid>https://forem.com/themsaid/multi-tenancy-in-laravel-migrations-testing-and-switching-tenants-4cb8</guid>
      <description>&lt;p&gt;In this video, we discuss how we can achieve multitenancy in Laravel using the database-per-tenant approach. We cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Managing multiple DB connections&lt;/li&gt;
&lt;li&gt;Migrating &amp;amp; seeding tenants &amp;amp; admin databases&lt;/li&gt;
&lt;li&gt;Running tests against tenant &amp;amp; admin databases&lt;/li&gt;
&lt;li&gt;Connecting to the correct tenant on requests/jobs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/592EgykFOz4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>database</category>
      <category>testing</category>
    </item>
    <item>
      <title>Laravel Sanctum - Hitting all the rough edges</title>
      <dc:creator>Mohamed Said</dc:creator>
      <pubDate>Sat, 11 Apr 2020 05:59:46 +0000</pubDate>
      <link>https://forem.com/themsaid/laravel-sanctum-hitting-all-the-rough-edges-5015</link>
      <guid>https://forem.com/themsaid/laravel-sanctum-hitting-all-the-rough-edges-5015</guid>
      <description>&lt;p&gt;In this video I'm going to use Laravel Sanctum to authenticate requests to an API using session-based and token-based authentication. While doing so, I'm going to show you all the possible errors that you might get and how to fix them.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Kd3hcrxtTHA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>authentication</category>
      <category>security</category>
    </item>
    <item>
      <title>When does PHP call __destruct()?</title>
      <dc:creator>Mohamed Said</dc:creator>
      <pubDate>Wed, 19 Feb 2020 06:05:20 +0000</pubDate>
      <link>https://forem.com/themsaid/when-does-php-call-destruct-1167</link>
      <guid>https://forem.com/themsaid/when-does-php-call-destruct-1167</guid>
      <description>&lt;p&gt;In PHP, &lt;code&gt;__construct()&lt;/code&gt; is called while creating an object and &lt;code&gt;__destruct()&lt;/code&gt; is called while the object is being removed from memory. Using this knowledge, we can create more fluent APIs as demonstrated by Freek Van der Herten in this &lt;a href="https://freek.dev/1545-how-to-avoid-large-function-signatures-by-using-pending-objects"&gt;short video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now let's see when PHP calls &lt;code&gt;__destruct()&lt;/code&gt; exactly.&lt;/p&gt;

&lt;p&gt;An object is removed from memory if you explicitly remove it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nb"&gt;unset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// __destruct will be called immediately.&lt;/span&gt;

&lt;span class="nv"&gt;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// __destruct will be called immediately.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It's also called when the scope where the object live is about to be terminated, for example at the end of a controller method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nv"&gt;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

   &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// __destruct will be called here.&lt;/span&gt;

   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'welcome'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Even if we're within a long running process, queued job for example, __destruct will be called before the end of the handle method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nv"&gt;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

   &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// __destruct will be called here.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It'll also be called when the script is being terminated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nv"&gt;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

   &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// __destruct will be called here.&lt;/span&gt;
&lt;span class="err"&gt;﻿&lt;/span&gt;
   &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>php</category>
    </item>
    <item>
      <title>Running a task after the response is sent</title>
      <dc:creator>Mohamed Said</dc:creator>
      <pubDate>Fri, 07 Feb 2020 11:53:51 +0000</pubDate>
      <link>https://forem.com/themsaid/running-a-task-after-the-response-is-sent-51o</link>
      <guid>https://forem.com/themsaid/running-a-task-after-the-response-is-sent-51o</guid>
      <description>&lt;p&gt;Normally, if you want to run a task and don't want the user to wait until it's done you'd dispatch a queued job. However, sometimes that task is really simple and short that putting it in a queue might be an overkill.&lt;/p&gt;

&lt;p&gt;Using Laravel, you can run such tasks after sending the response to the user. It works by keeping the PHP process alive to run the tasks after closing the connection with the browser. You can do that using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terminable Middleware.&lt;/li&gt;
&lt;li&gt;Terminating callbacks (e.g. App::terminating(function(){ }))&lt;/li&gt;
&lt;li&gt;Job::dispatchAfterResponse() using Laravel v6.14.0 or higher.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have a job called ClearCache, you can run it after the response is sent like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;// Do some work&lt;/span&gt;

 &lt;span class="nx"&gt;ClearCache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;dispatchAfterResponse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Remember, this is only a good idea if the task is really short. For long running tasks, dispatching to queue is recommended.&lt;/p&gt;

</description>
      <category>laravel</category>
    </item>
    <item>
      <title>Where to look when you see "Job has been attempted too many times or run too long"</title>
      <dc:creator>Mohamed Said</dc:creator>
      <pubDate>Fri, 31 Jan 2020 16:55:53 +0000</pubDate>
      <link>https://forem.com/themsaid/where-to-look-when-you-see-job-has-been-attempted-too-many-times-or-run-too-long-342</link>
      <guid>https://forem.com/themsaid/where-to-look-when-you-see-job-has-been-attempted-too-many-times-or-run-too-long-342</guid>
      <description>&lt;p&gt;If you've seen this MaxAttemptsExceededException in your error logs or failed_jobs table and you don't have a clue what happened to the job, let me try to explain what may have happened. It's either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The job timed out and it can't be attempted again.&lt;/li&gt;
&lt;li&gt;The job was released back to the queue and it can't be attempted again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your job processing time exceeded the timeout configuration, the worker will check the maximum attempts allowed and the expiration date for the job and decide if it can be attempted again. If that's not possible, the worker will just mark the job as failed and throw that MaxAttemptsExceededException.&lt;/p&gt;

&lt;p&gt;Also if the job was released back to the queue and a worker picks it up, it'll first check if the maximum attempts allowed was exceeded or the job has expired and throw MaxAttemptsExceededException in that case.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>queues</category>
    </item>
    <item>
      <title>A production-ready database queue diver for Laravel</title>
      <dc:creator>Mohamed Said</dc:creator>
      <pubDate>Thu, 30 Jan 2020 12:26:46 +0000</pubDate>
      <link>https://forem.com/themsaid/a-production-ready-database-queue-diver-for-laravel-22eh</link>
      <guid>https://forem.com/themsaid/a-production-ready-database-queue-diver-for-laravel-22eh</guid>
      <description>&lt;p&gt;The database queue driver was not recommended to run in production environments due to the problem of deadlocks with Relational database. Let's see how a deadlock happens:&lt;/p&gt;

&lt;p&gt;A worker puts a lock on a job to process it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Another worker finds the same job locked and it waits for the lock to be released.&lt;/li&gt;
&lt;li&gt;The first worker is done with the job and wants to delete it, so it requests another lock.&lt;/li&gt;
&lt;li&gt;Now we have a deadlock, multiple transactions waiting for each other to release the same locks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MySQL 8.0.1 and Postgres 9.5 allows skipping a locked record and ignore it. This allowed us to prevents workers from fighting over the same job and thus cause a deadlock.&lt;/p&gt;

&lt;p&gt;Starting the next Laravel release, you can use the queue database driver even if your environment is under heavy load. I've tested the changes processing 516,783 jobs by 50 workers and it resulted no deadlocks.&lt;/p&gt;

&lt;p&gt;The database driver is easy to setup since you don't need to worry about configuring and maintaining another tool "redis", it also opens the door for complex custom rules like funneling jobs per tenant or ensuring groups of jobs run in a certain order. In addition to this, you can easily configure database backups to ensure you don't lose the jobs in store in case the server crashed.&lt;/p&gt;

&lt;p&gt;However, you should know that the database queue driver is not the best driver performance-wise, but it's still pretty efficient as the test results shared above implicate.&lt;/p&gt;

&lt;p&gt;If you run MySQL &amp;gt;=8.0.1 or Postgres &amp;gt;=9.5, you don't need to change anything in your app. Just configure the database connection, run php artisan queue:table and php artisan migrate, and set the QUEUE_CONNECTION to database in your .env file.&lt;/p&gt;

</description>
      <category>laravel</category>
    </item>
    <item>
      <title>APP_KEY is a secret. Here's what it's used for &amp; how you can rotate it</title>
      <dc:creator>Mohamed Said</dc:creator>
      <pubDate>Sun, 26 Jan 2020 16:42:25 +0000</pubDate>
      <link>https://forem.com/themsaid/appkey-is-a-secret-here-s-what-it-s-used-for-how-you-can-rotate-it-3mki</link>
      <guid>https://forem.com/themsaid/appkey-is-a-secret-here-s-what-it-s-used-for-how-you-can-rotate-it-3mki</guid>
      <description>&lt;p&gt;People often think  APP_KEY is used to hash passwords, it isn't. Here's what this key is used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encrypting cookies.&lt;/li&gt;
&lt;li&gt;Creating the signature for signed URLs and queued closures.&lt;/li&gt;
&lt;li&gt;Encrypting values using the encrypt() and decrypt() helpers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should deal with the &lt;code&gt;APP_KEY&lt;/code&gt; as a secret. If you think it has been exposed, you MUST change it. However, make sure you re-encrypt any stored encrypted values. Also understand that there'll be some side effects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All previously queued closures won't be able to run.&lt;/li&gt;
&lt;li&gt;All users will be logged out and all token values will be lost.&lt;/li&gt;
&lt;li&gt;All previously created signed routes won't work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can override the encrypter in your app to use an old key if it failed to decrypt a value with the new key. That way you can keep your app running fully after rotation until all the values are re-encrypted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Providers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;App\Encrypter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Illuminate\Support\Str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Illuminate\Support\ServiceProvider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppServiceProvider&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;ServiceProvider&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Register any application services.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'encrypter'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="nv"&gt;$config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'config'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'key'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s1"&gt;'base64:'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;base64_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Encrypter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'cipher'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Illuminate\Support\Str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Encrypter&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;\Illuminate\Encryption\Encrypter&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Decrypt the given value.
     *
     * @param  string  $payload
     * @param  bool  $unserialize
     * @return mixed
     *
     * @throws \Illuminate\Contracts\Encryption\DecryptException
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$unserialize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$unserialize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;\Throwable&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="nv"&gt;$currentKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app.old_key'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'base64:'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;base64_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app.old_key'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                            &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app.old_key'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$unserialize&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$currentKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$currentKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>laravel</category>
    </item>
    <item>
      <title>What is AWS Lambda, and how Laravel Vapor uses it</title>
      <dc:creator>Mohamed Said</dc:creator>
      <pubDate>Thu, 23 Jan 2020 07:48:36 +0000</pubDate>
      <link>https://forem.com/themsaid/what-is-aws-lambda-and-how-laravel-vapor-uses-it-1j98</link>
      <guid>https://forem.com/themsaid/what-is-aws-lambda-and-how-laravel-vapor-uses-it-1j98</guid>
      <description>&lt;p&gt;&lt;a href="https://vapor.laravel.com/"&gt;Vapor&lt;/a&gt; is a serverless deployment platform for Laravel powered by AWS Lambda. A lot is happening under the hood, some real magic, but the most interesting part of the whole thing is the serverless technology underneath. Let's dive into serverless as I'll try to explain what happens when you run your laravel application serverless.&lt;/p&gt;

&lt;p&gt;If you take a look at the index.php file of your laravel app, you'll see this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$kernel&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nv"&gt;$request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Illuminate\Http\Request&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When you send a request to your application, the &lt;code&gt;Kernel::handle&lt;/code&gt; method will process that request and send the response back to your browser.&lt;/p&gt;

&lt;p&gt;You normally host this application on a server that waits for any incoming requests and calls &lt;code&gt;index.php&lt;/code&gt; whenever one comes. Let's say you host it in a small DigitalOcean droplet and paying $5/month for the server.&lt;/p&gt;

&lt;p&gt;Imagine if you can just upload that &lt;code&gt;Kernel::handle&lt;/code&gt; method to a service, and you only pay when that method runs. You don't worry about provisioning a server, upgrading the different libraries, managing the storage, and all this work. Just upload the function and you only pay when the function runs.&lt;/p&gt;

&lt;p&gt;That's basically what running serverless is all about.&lt;/p&gt;

&lt;p&gt;Lambda is AWS's FaaS (Function as a service), Laravel Vapor uses it to run your Laravel applications as a function that's only invoked when needed. Upload your app to Vapor, and that's it. Never worry about servers again.&lt;/p&gt;

&lt;p&gt;Lambda is mainly used as part of a Microservices architecture, a lambda is meant to be doing only one job:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You upload an image to S3, a lambda gets invoked &amp;amp; generates a thumbnail version of your image.&lt;/li&gt;
&lt;li&gt;You send a job to queue, a lambda is invoked &amp;amp; processes that job.&lt;/li&gt;
&lt;li&gt;You schedule a job and AWS invokes a lambda each time the alarm goes off.&lt;/li&gt;
&lt;li&gt;You send an HTTP request to an endpoint, and a lambda is invoked and generates a response.&lt;/li&gt;
&lt;li&gt;You could also invoke a lambda as per your request anytime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This usually means you have to divide your application code into multiple different services where each service has its own code base, and you deploy these different functions to AWS and instruct it as to when to run which lambda.&lt;/p&gt;

&lt;p&gt;A user submits an order, you instruct AWS to run the "new-order" lambda. A user asks for an invoice, you instruct AWS to run the "generate-invoice" lambda. A user asks for a list of products, you instruct AWS to run the "products-list" lambda.&lt;/p&gt;

&lt;p&gt;While the Microservices architecture is very beneficial in many cases, it adds a lot of complexity to your project as you need to handle the "wiring" of all these services working together. Laravel Vapor takes your codebase and converts it to a single function; depends on the event that triggers this function, Vapor runs a certain part of your application. This way all the wiring is done by Laravel under the hood.&lt;/p&gt;

&lt;p&gt;So for example; when the user visits the &lt;code&gt;/api/products&lt;/code&gt; endpoint, Vapor will dispatch the HTTP request to the Laravel router and sends the response back. Or when a job is available on SQS, Vapor will marshal that job to a worker to process it.&lt;/p&gt;

&lt;p&gt;That way you can have all the benefits of running serverless without having to change the way you write your Laravel applications. Vapor takes care of all the work needed to convert your Laravel app to work serverless.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;As we said earlier, Vapor converts your application to a single lambda. However, to allow you to set different configuration values for your HTTP and CLI environments, Vapor creates 2 identical Lambdas on AWS.&lt;/p&gt;

&lt;p&gt;The HTTP lambda is responsible for serving HTTP requests; you can configure the amount of memory AWS should allocate to your HTTP requests, the timeout value, and the concurrency limit.&lt;/p&gt;

&lt;p&gt;The CLI lambda is responsible for running artisan commands, processing queued jobs, and running scheduled jobs. You can also configure memory, timeout, and concurrency limits.&lt;/p&gt;

&lt;p&gt;For the HTTP lambda, it's invoked via the API Gateway or an Application Load Balancer. We'll talk about the difference between both services in another post.&lt;/p&gt;

&lt;p&gt;For queued jobs, Vapor configures your laravel application to use SQS to dispatch and process jobs. The CLI lambda will be invoked whenever a job is available in SQS.&lt;/p&gt;

&lt;p&gt;Scheduled jobs are configured using CloudWatch/EventBridge, Vapor creates a rule that runs every minute and invokes your CLI lambda with the php artisan schedule:run command.&lt;/p&gt;

&lt;p&gt;Finally, when you run vapor:command and provide the artisan command you wish to run, Vapor invokes the CLI lambda and instructs it to run the provided command.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>aws</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Working with a database-per-tenant model in Laravel</title>
      <dc:creator>Mohamed Said</dc:creator>
      <pubDate>Wed, 22 Jan 2020 09:09:27 +0000</pubDate>
      <link>https://forem.com/themsaid/working-with-a-database-per-tenant-model-in-laravel-4adi</link>
      <guid>https://forem.com/themsaid/working-with-a-database-per-tenant-model-in-laravel-4adi</guid>
      <description>&lt;p&gt;In this article, we're going to explore one of the most confusing aspects of multi-tenancy in laravel applications; communicating with multiple databases.&lt;/p&gt;

&lt;p&gt;The majority of applications just communicate with a single database. However, a considerable portion of laravel applications communicates with multiple databases.  There are some neat packages that help with managing multiple connections, but it'd be useful if we understand how database connections work in Laravel, so let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Establishing a connection with the Database
&lt;/h2&gt;

&lt;p&gt;When you run a query in Laravel, the Illuminate\Database\DatabaseManager takes care of configuring a database connection to run the query on. Each connection has a unique name and you get to choose a default connection to be used when no connection name is explicitly provided:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Uses the default connection.&lt;/span&gt;
&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Uses the "tenant" connection.&lt;/span&gt;
&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tenant'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The connection is created once and then re-used every time you need to run a query during the application life cycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  The PHP Data Objects (PDO)
&lt;/h2&gt;

&lt;p&gt;The PDO is a standard interface for accessing databases in PHP, Laravel uses the PDO to run all kinds of queries. However, you can configure a connection to use a separate read &amp;amp; write PDO objects for read/write operations. You can find more details on that subject in the official docs.&lt;/p&gt;

&lt;p&gt;Most multi-tenancy apps that use a separate database for each tenant has a central database where details on all tenants are stored. So basically in a single application you might have a system connection and a tenant connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s1"&gt;'tenant'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s1"&gt;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'mysql'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'host'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DB_HOST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'127.0.0.1'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="s1"&gt;'port'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DB_PORT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'3306'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;

&lt;span class="s1"&gt;'system'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s1"&gt;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'mysql'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'host'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DB_HOST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'127.0.0.1'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="s1"&gt;'port'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DB_PORT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'3306'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The system connection always connects to the same database, so the configuration set in the config file can always be used, and queries to this connection are pretty easy to do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'system'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tenants'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It gets interesting though for when you want to run a query on the tenant connection. Since the tenant connection configurations are based on who is the current tenant, we can't put the configuration in the config/database.php file, instead we want to configure the connection on the fly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'database.connections.tenant.database'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'tenant1'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This line of code will set the tenant connection configuration to read from the "tenant1" database, you can change any connection parameters in the same manner; like the username, password, read/write connections, anything.&lt;/p&gt;

&lt;p&gt;Now when the DatabaseManager tries to build the tenant connection, it will use the configurations you set on the fly in the step above. However, if the tenant connection was already resolved before any changes to the config file won't take effect since the connection is cached first time it's created and Laravel won't create a new instance of the connection.&lt;/p&gt;

&lt;p&gt;To overcome this, you need to make sure no connection is resolved before you can set the new configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'database.connections.tenant.database'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'tenant1'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tenant'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;reconnect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tenant'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Using purge() and reconnect() will ensure any query that runs in the future on the tenant connection will use the configuration from above.&lt;/p&gt;

&lt;p&gt;Where to put this piece of code&lt;br&gt;
There are several entry points to a laravel application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP Requests.&lt;/li&gt;
&lt;li&gt;Console Commands.&lt;/li&gt;
&lt;li&gt;Queued Jobs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's create a new &lt;code&gt;TenancyProvider&lt;/code&gt; and add it to our &lt;code&gt;config/app.php&lt;/code&gt; file. In the register method of this provider we can configure the current tenant like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;runningInConsole&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getHttpHost&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'tenant1.app.com'&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
      &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'database.connections.tenant.database'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'tenant1'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

      &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tenant'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;reconnect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tenant'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We check the HTTP host of the current request and then assign the configuration to respect the current tenant.&lt;/p&gt;

&lt;p&gt;As for queued jobs, we can store the tenant_id in the payload of all jobs, and while precessing the job we set the current tenant configuration same as above.&lt;/p&gt;

&lt;p&gt;So in our service provider, we add this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'queue'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;createPayloadUsing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Tenant&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
              &lt;span class="s1"&gt;'tenant_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Tenant&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;
             &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To simplify things I use Tenant::get() that should be holding the logic that identifies who is the current tenant.&lt;/p&gt;

&lt;p&gt;Now the payload of each job will include a tenant_id if a tenant is discovered, now we can listen to the JobProcessing event and configure our database for the current tenant if one exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'events'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;\Illuminate\Queue\Events\JobProcessing&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s1"&gt;'tenant_id'&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Tenant&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s1"&gt;'tenant_id'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;﻿&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As for Console Commands; you will need to specify who is the tenant to run the code against. So each time you run a command you need to send details about which tenant to be used, and inside the command code you configure the tenant database connection as seen above.&lt;/p&gt;

</description>
      <category>laravel</category>
    </item>
  </channel>
</rss>
