It is always caching!

five keyboard keys on a black surface spelling out the work cache

In October I added multiple account deletion options to the Costs to Expect API – you can delete your data for a specific App, reset your data for one of our Apps or delete your account entirely.

There could be a large amount of data to delete so I decided to handle the deletes behind the scenes with jobs. This worked well and during all my testing, there was never an issue. If an issue does occur a notification gets sent and I can fix the issue.

However, after release, I tested with a throwaway account, and it wasn’t working. As a user I could reset my state but when I signed in again all my data was still showing.

For a little while I was perplexed. The API wasn’t erroring, the data was being removed but Budget still showed the old state. The first hint happened when I tried to do something in Budget; I immediately got an error from the API, a budget item couldn’t be created because the resource didn’t exist.

Aha! I knew what the problem was. I said to myself, “Budget has data, the API doesn’t, there must be a cache issue somewhere.

Budget doesn’t retain a cache so it can only be the API. I rush (really, I did) to my IDE and low and behold, my jobs don’t clear the cache after deleting the requested data – oops!

How did this happen?

Well, that’s easy. During development, I turn off the cache on my local instance of the API as I don’t want the cache getting in the way of any new features I’m writing or debugging. I test before I make a new release, manually and automatically. Though clearly, I’m not always turning cache back on.

The Solution

The solution is easy – do a better job of testing but it isn’t quite as simple as that. I’m going to update my automatic tests to include testing with and without caching enabled. More importantly though, I’m going to expose the API cache status.

It isn’t unusual for the development or staging version of your Apps to highlight their status – a bar at the top, a different background, a visual notifier of some kind. I’m going to update Budget and all the other Costs to Expect Apps to include this notifier and show the state of the API, is caching enabled? Is it in debug mode? That way when I’m testing a data state feature, I’m more likely to spot that status and think about the extra steps.

Invokable Controllers

Action class usage in my Laravel Apps

For several years I have been a fan of invokable classes, typically to act as action classes for forms and to create jobs for queues etc.

Simple Forms

With regards to simple forms, this works well. The validation and creation code are all contained in one class keeping the code out of the controller. If all you need is validation and a little logic before saving/updating, this model works well. The model breaks down when the complexity of the request goes up.

Invokable Controllers

On a recent freelance project, I needed to validate the request, convert the data and then generate lots of additional values. This Apps calculates the viability of pumps based on the request so there are a lot of fluid dynamic calculations. Once the calculations have been processed, I can again calculate the viability. Only once I have calculated the viability do I save the request.

Naming

My action classes have simple names – createGame, saveUser, – you get the idea. When you read the name of the action, you know what it does and when you look inside, you have an idea about what you will see. This doesn’t work when there are five or six steps that must happen before the “quote” is created.

We get this benefit with invokable controllers as well but rather than the class names telling you what is happening, the method names in the controller describe what is happening. We get all the benefits of invokable action classes without the negative of a giant action class which is doing more than its name suggests.

I rarely need to use invokable controllers but when I do, they are a life saver.

I’ve a detailed post on how I use action classes and how the specific use changes on the structure of the App. If you are a fan of invokable action classes, please give it a read.