Deleting Items and Flushing our Redis Cache
Not everyone is perfect, and one day you'll accidentally cache bad data and need a way to quickly clear it out. In this lesson, we'll learn how we can create two routes to clear a single Redis key or flush the entire database.
- Author
- Tom Gobich
- Published
- Feb 04
- Duration
- 6m 46s
Developer, dog lover, and burrito eater. Currently teaching AdonisJS, a fully featured NodeJS framework, and running Adocasts where I post new lessons weekly. Professionally, I work with JavaScript, .Net C#, and SQL Server.
Adocasts
Burlington, KY
Transcript
Deleting Items and Flushing our Redis Cache
-
[music]
-
So when we left off, we had our Redis cache working A-OK.
-
Our data was getting stored in the Redis. We were able to read it back out,
-
list it on our page, view the details of a single movie.
-
Everything was just working. Now, I've gone into the Redis cache
-
and manually altered the data so that it would be invalid.
-
So if I give the page a refresh here, we'll see unexpected token S,
-
and it's trying to read some bad, and I have data right here.
-
It's not valid JSON whenever we try to parse out the JSON in our get method.
-
You can see if we dive through the show frames here,
-
if we click on cache service, the error is happening right here within our get method
-
where we're trying to parse the value out.
-
We're finding a value. Our hazard is returning back that we have some sort of value
-
because the database itself has a value.
-
So we're getting to the JSON parse OK, but the parse is failing
-
because it's not valid JSON for it to actually parse out.
-
So as we try to refresh our server and refresh,
-
it's still just going to run into the same issue since it's just reading from our cache
-
over and over again, but our cache holds the invalid data.
-
So what we need to do is clear our cache out.
-
So let's hide our browser back away, and let's give ourselves a way to clear our cache out.
-
With our old singleton service that held everything in memory within that singleton,
-
all that we had to do was stop our server and restart it,
-
but Redis is running on a completely different server,
-
so we need to actually provide our application a way to clear it out.
-
So we'll define a new route within our routes,
-
and we'll call this router.delete, and we'll set this to /redis,
-
and then we'll have a particular slug that we can provide to delete it out.
-
Let's also create ourselves a controller to house this route.
-
So let's hide our text editor back away, stop our server, clear it out,
-
and let's do node ace, and there's a command called make controller,
-
and we can provide a name for this controller.
-
So we'll call ours Redis.
-
So now we have a new controller called Redis controller within our app controllers directory.
-
Let's go back into our text editor, and now we can define that controller.
-
So we'll do Redis controller, tab to auto import,
-
and let's define some methods on that controller.
-
So let's dive into our Redis controller.
-
Let's uncomment the HTTP context import, and let's do public async,
-
and we'll call one method destroy.
-
For this, we'll extract out our response, set the type to HTTP context,
-
and now we're ready to do the route handler.
-
I'm going to go ahead and copy this, paste it in,
-
and let's create another method called flush.
-
So within our destroy method, we will destroy a singular key.
-
Within our flush method, we will flush our database for Redis.
-
So we want to interact with our cache service,
-
so we can do await cache and hit tab to auto import that,
-
and we can call delete and pass in the key that we're getting from our params.
-
So let's also extract our params out of our HTTP context,
-
and we can do params.slug.
-
Then we can just return the user back to where the call came from.
-
So for that, we can return, we can utilize the response object
-
to redirect the user, and off of the redirect method,
-
we can chain an additional method called back
-
that will actually read from the referrer header
-
and send the user back to what referred them to this particular destroy handler.
-
Getting tired of the red squiggly, so I'm going to go ahead and hit save
-
so that the indentation happens.
-
Ah, I didn't like my public declaration there. Okay.
-
Within our flush method, we'll want to do something very similar,
-
except instead of calling delete with a particular slug,
-
we'll just call flush database.
-
So we'll wait, cache., we have our flush DB method.
-
It doesn't take anything in, so we're good there.
-
Now we'll just return response redirect.
-
Give that a save, and now we need to define routes for these.
-
So we'll dive back into our routes.ts, and we'll call destroy for this one.
-
As redis.destroy, we can copy this declaration,
-
and instead of slug, this will be flush,
-
and instead of destroy, this will be flush,
-
and for the name, it too will be flush.
-
Now here we've just come across something to learn.
-
Adonis, whenever it's searching for a route to match our request,
-
is going to use the first request that it finds matching for the route.
-
Flush is a valid slug, meaning that if we attempted to call redis/flush,
-
Adonis will never actually utilize this particular route definition
-
because it matches this one, and this one's defined first.
-
Since it stops the first match for the request,
-
our redis flush will always use this route handler.
-
So since we want redis flush to specifically use this route handler,
-
we're going to want to put it first.
-
With it being first, if the request is specifically for redis/flush,
-
this route handler will get used.
-
If it's any other type of slug, this route handler will get used.
-
So ordering does matter whenever you're defining your routes,
-
whether that be a delete, get, post, put, patch, or whatever.
-
And now we need a way to call these delete methods.
-
Now at this point, if we were to try to send these delete requests out,
-
that would get into a couple of things that we're not quite ready to talk about yet.
-
So although we would definitely want these to be something like a delete request,
-
let's switch these to a get request for right now.
-
Give these a save, and now all we have to do is send out a request to our browser,
-
and they'll work A-OK.
-
We'll switch these back to delete requests before we end this lesson now
-
so that they're correct.
-
So let's jump back into our browser.
-
We need to restart our server, so let's go ahead and dive back into our terminal.
-
npm run dev there. OK.
-
Let's first verify that we still have our issue. Yep, sure do.
-
So let's open up another tab, and let's go to localhost 3333/,
-
and we made our URL for flushing a single key, redis/,
-
and then whatever that slug is.
-
Well, the one that I intentionally sabotaged was awesomemoviethetrilogy.
-
So if we hit Enter here, this request will match our redis delete route,
-
and it will delete out the specific individual key for awesomemoviethetrilogy,
-
and it should clear out our error.
-
So let's go ahead and hit Enter here, and voila,
-
we got redirected right back to the home page after it cleared out that key.
-
If we jump back into this page where we had the error, give it a refresh,
-
everything's still working A-OK.
-
If we refresh again to make sure that we're reading from our cache,
-
everything is still working.
-
So we get rid of our extra tab now, jump back into our terminal,
-
and indeed we can see everything's coming from the cache.
-
Let's do this one more time.
-
I'm going to clear our terminal out by restarting our server
-
to give us a clean cache hit slate.
-
OK, let's go ahead and flush our database now.
-
So let's dive back into here.
-
We'll go to /redis/flush,
-
which should clear out all of the caches that we have stored so far,
-
which would just be our three movies.
-
So let's go ahead and hit Enter, and we got redirected back to the home page.
-
Since we had just booted up our server and we had just cleared our cache,
-
these three here should not have hit our cache at all.
-
So if we dive back into our terminal, sure enough, no cache hits.
-
If we give the page a refresh, jump back into our terminal,
-
there's our cache hits once more.
-
So now we know how to delete an individual cache item
-
or the entire cache database if we were to run into any issues.
-
Let's hide this away, jump back into our text editor,
-
and switch these back to deletes as they're supposed to be.
-
Whenever we get into talking about forms,
-
we'll break these up to actual forms so that we can utilize them.
-
Introduction
-
Fundamentals
-
2.0Routes and How To Create Them5m 23s
-
2.1Rendering a View for a Route6m 29s
-
2.2Linking Between Routes7m 51s
-
2.3Loading A Movie Using Route Parameters9m 17s
-
2.4Validating Route Parameters6m 6s
-
2.5Vite and Our Assets6m 38s
-
2.6Setting Up Tailwind CSS9m 5s
-
2.7Reading and Supporting Markdown Content4m 32s
-
2.8Listing Movies from their Markdown Files8m 51s
-
2.9Extracting Reusable Code with Services7m 4s
-
2.10Cleaning Up Routes with Controllers4m 52s
-
2.11Defining A Structure for our Movie using Models9m 38s
-
2.12Singleton Services and the Idea of Caching6m 11s
-
2.13Environment Variables and their Validation4m 16s
-
2.14Improved Caching with Redis10m 44s
-
2.15Deleting Items and Flushing our Redis Cache6m 46s
-
2.16Quick Start Apps with Custom Starter Kits6m 28s
-
2.17Easy Imports with NodeJS Subpath Imports8m 40s
-
-
Building Views with EdgeJS
-
3.0EdgeJS Templating Basics8m 49s
-
3.1HTML Attribute and Class Utilities6m 9s
-
3.2Making A Reusable Movie Card Component10m 24s
-
3.3Component Tags, State, and Props4m 53s
-
3.4Use Slots To Make A Button Component6m 56s
-
3.5Extracting A Layout Component5m 13s
-
3.6State vs Share Data Flow2m 59s
-
3.7Share vs Global Data Flow6m 7s
-
3.8Form Basics and CSRF Protection6m 13s
-
3.9HTTP Method Spoofing HTML Forms3m 3s
-
3.10Easy SVG Icons with Edge Iconify7m 57s
-
-
Database and Lucid ORM Basics
-
4.0Configuring Lucid and our Database Connection4m 3s
-
4.1Understanding our Database Schema9m 35s
-
4.2Introducing and Defining Database Migrations18m 35s
-
4.3The Flow of Migrations8m 28s
-
4.4Introducing Lucid Models5m 43s
-
4.5Defining Our Models6m 49s
-
4.6The Basics of CRUD11m 56s
-
4.7Defining Required Data with Seeders11m 11s
-
4.8Stubbing Fake Data with Model Factories13m 48s
-
4.9Querying Our Movies with the Query Builder15m 30s
-
4.10Unmapped and Computed Model Properties3m 24s
-
4.11Altering Tables with Migrations7m 6s
-
4.12Adding A Profile Model, Migration, Factory, and Controller2m 57s
-
4.13SQL Parameters and Injection Protection9m 19s
-
4.14Reusable Query Statements with Model Query Scopes8m 11s
-
4.15Tapping into Model Factory States9m 15s
-
4.16Querying Recently Released and Coming Soon Movies4m 59s
-
4.17Generating A Unique Movie Slug With Model Hooks7m 59s
-
-
Lucid ORM Relationships
-
5.0Defining One to One Relationships Within Lucid Models5m 49s
-
5.1Model Factory Relationships2m 54s
-
5.2Querying Relationships and Eager Vs Lazy Loading5m 17s
-
5.3Cascading and Deleting Model Relationships5m 16s
-
5.4Defining One to Many Relationships with Lucid Models6m 56s
-
5.5Seeding Movies with One to Many Model Factory Relationships5m 24s
-
5.6Listing A Director's Movies with Relationship Existence Queries8m 41s
-
5.7Listing and Counting a Writer's Movies8m 41s
-
5.8Using Eager and Lazy Loading to Load A Movie's Writer and Director5m 18s
-
5.9Defining Many-To-Many Relationships and Pivot Columns9m 48s
-
5.10Many-To-Many Model Factory Relationships4m 50s
-
5.11A Deep Dive Into Relationship CRUD with Models18m 5s
-
5.12How To Create Factory Relationships from a Pool of Data13m 55s
-
5.13How To Query, Sort, and Filter by Pivot Table Data9m 47s
-
-
Working With Forms
-
6.0Accepting Form Data12m 15s
-
6.1Validating Form Data with VineJS9m 29s
-
6.2Displaying Validation Errors and Validating from our Request7m 16s
-
6.3Reusing Old Form Values After A Validation Error2m 3s
-
6.4Creating An EdgeJS Form Input Component5m 28s
-
6.5Creating A Login Form and Validator5m 1s
-
6.6How To Create A Custom VineJS Validation Rule9m 7s
-
-
Authentication & Middleware
-
7.0The Flow of Middleware7m 49s
-
7.1Authenticating A Newly Registered User4m 14s
-
7.2Checking For and Populating an Authenticated User2m 10s
-
7.3Logging Out An Authenticated User2m 24s
-
7.4Logging In An Existing User6m 54s
-
7.5Remembering A User's Authenticated Session6m 55s
-
7.6Protecting Routes with Auth, Guest, and Admin Middleware5m 36s
-
-
Filtering and Paginating Queries
-
8.0Creating A Movie List Page3m 43s
-
8.1Filtering A Query By Pattern Likeness7m 9s
-
8.2Filtering Our List by Movie Status5m 47s
-
8.3How To Apply A Dynamic Sort Filter To Your Query7m 12s
-
8.4Joining SQL Tables To Order By A Related Column4m 49s
-
Validating Query String Filter Values7m 23s
-
How To Paginate Filtered Query Results9m 15s
-
Pagination First, Last, Next, and Previous Buttons4m 2s
-
-
User Watchlist
-
An Alternative Approach to Many-To-Many Relationships4m 56s
-
Toggling A Movie in an Authenticated User's Watchlist9m 56s
-
Listing and Filtering User Watchlist Items7m 34s
-
Allowing Users To Toggle A Movie As Watched4m 44s
-
Filtering By User's Watched Status6m 7s
-
Defining A Composite Unique Constraint4m 46s
-
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!