The day a PHP namespace ruined all notifications

If you’re familiar with Laravel, you know that your classes live in a child namespace of the App namespace. However, moving from Laravel 7.x to 8.x, the models (that lived directly in App) were non-forcefully moved to the App\Models namespace. I’ll be honest, I loved this idea because I hated opening the app directory to be greeted by countless classes.

This is a story of the day I learned the hard way that you don’t only need to check whether your apps throw errors and whatnot: you also need to check that your namespaces match older data and your tasks are refreshed.

Database notifications keep the PSR-4 string of each notification and notifiable class.

Me. I said this. If it’s written somewhere else, I didn’t know.

Welp, that’s a problem. I can easily adapt my application to the new App\Models namespace scheme and update the thousands of notifications on the database. However, the problem is I forgot about the latter entirely.

Yes, this blockhead here did not update those rows nor the supervisor running the notification queue. Guess what? The users stopped receiving notifications in real-time and older notifications (including unread ones) disappeared. The app was sending them new ones, but they could only see them after a refresh.

Ugh, such an idiot. I can’t be this stupid. These notifications literally help synchronize the work of several people within a clinic. A darn medical center! Not getting notifications telling them to do what they’re supposed to and when they’re supposed to is a huge problem. Not just for the establishment but the patients, too.

Here’s a list of the issues that arose from this otherwise insignificant detail:

  • Secretaries had a lot of trouble giving out allergy vaccination kits to patients because they couldn’t see the unread notification of a prepared kit. Notifications give them quick access to all the kit information. Note: some patients who live far form the clinic take these kits to have a local nurse vaccinate them instead.
  • Nurses weren’t notified when a patient was outside the vaccination room so the line got longer and longer by the minute and they didn’t even know this was happening. Note: this vaccination takes less than a minute, it’s so quick and painless you can spend 3 minutes at most in your visit to the clinic that day if you were the only one there.
  • Nurses weren’t notified about people in the waiting room who needed a test done. There are many allergy tests done in the clinic including the infamous prick test. By the way, it’s not as bad as most people say: it doesn’t hurt at all and you may want to scratch but it only takes some daydreaming to get the urge out of your system.
  • Physicians weren’t notified about patients in the waiting room either. They sat there waiting for a number to pop up but it never did. Just imagine their reaction when they refreshed the page and saw a number greater than 5 in the notification bell.

I don’t want to remember the number of calls I got that morning. What a morning that was. At first, I didn’t know what was happening, but then it dawned on me that I had updated the namespace and when I checked the database, I saw it. All notifications prior to that day had the following (reduced) structure:

typenotifiable_type
App\Notifications\SomeNotificationApp\User
Reduced structure prior to the update
typenotifiable_type
App\Notifications\SomeNotificationApp\Models\User
Reduced structure after the update

So, when the users loaded the app, they couldn’t see older notifications because they were logging in as App\Models\User but all older notifications were sent out to App\User. That explains why they couldn’t see older notifications.

What about not seeing real-time notifications? Well, I use supervisorctl to have php artisan queue:work and php artisan websockets:serve run in the background. The problem with this is it remembers the complete state of your app in the moment you run the command. Since the server is working 24/7, albeit locally, the update was undetected by my tasks. What’s the solution? Run sudo supervisorctl restart all. EZ PZ.

As soon as all that was done, peace was restored at the clinic and life went on. They told me, later that day, that they had huge delays but not angry patients, fortunately. They were very understanding of the issue and said that it ended up not being much of a problem because I fixed it relatively quickly so things got back to normal in about half an hour or so.

Takeaways

These are easy solutions but the point of this post is that these issues should have been avoided to begin with. The clinic should not have even noticed that a change was made. All updates should run seamlessly with no repercussions. But that wasn’t the case of today’s story.

Here’s what I’d suggest: if you manage many apps, make a checklist of all the things you may want to check whenever you make a huge update like this, especially about the Laravel services you use. For example, this app uses Events, Notifications, Jobs, Console, Broadcasting, and Mail. So, my list will look something like this:

  • Check namespace changes.
  • Check .env file.
  • Check config files.
  • Check views.
  • Check Providers.
  • Check Events.
  • Check Notifications.
  • Update notifications table according to the namespace scheme, if necessary.
  • Check Jobs.
  • Check Console.
  • Check Broadcasting.
  • Check Mail.
  • Test workflows.
  • Grab some coffee. Deploy.
  • Restart supervisor task.
  • Restart job queue task.
  • Hope my phone doesn’t ring any time soon.

But your mileage may vary.

Leave a comment

Your email address will not be published. Required fields are marked *