Description:
I have a "logout" mechanism in my project. Basically, it creates a record into a DB table and I check if the logged_out_at
has a value.
Now, to make sure this mechanism is proper, I've implemented it into a custom middleware that gets called whenever the api
gets called.
[1] $record = Logout::where("user_id", Auth::id())->where("logged_out_at", null)->first()
When the logout record exists, I'd call ->update
and the set a value for logged_out_at
. Then, redirect the user to a logout route or issue a 401 Not authorized
response.
[2] Logout::where("user_id", Auth::id())->where("logged_out_at", null)->update($params);
Problem:
Imagine the user clicking "refresh" or opening multiple microservices that request the api
multiple times at the same time.
[1] will be called, [2] will be executed. In the second middleware call, the [1] will be called, the [2] of previous could be in execution process, therefore, I'd get a [1] valid response, which shouldn't be!
Solution
I've tried using Redis
cache, use Auth::id()
as key. If the cache exists, I return and don't search for anything. Nevertheless, I've faced the same problem. Redis
would still take time to execute, save and retrieve the pair
.
I've tried using a global variable (array with Auth::id()
is key), but it would be a mess if I have over 1K users.
I believe my way of verifying the logout
is wrong, but I couldn't find any helpful resources for this.
CodePudding user response:
Since your needs are that an event (notification), that is triggered when you "logout", needs to trigger only once then you can make them tightly dependent via the result of the method update()
update()
returns the number of rows affected by the query and since the query is conditioned on logged_out_at
being null
then:
$loggedOut = Logout::where("user_id", Auth::id())->where("logged_out_at", null)->update($params);
if ($loggedOut) {
sendNotification();
}