Skip to content

Commit dd70b0d

Browse files
committed
cache user objects in session to reduce database hits. however, we need to move mediumtext fields away from the users table before adopting this
1 parent 3bb2e92 commit dd70b0d

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

lib/Wing/Role/Result/User.pm

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,12 @@ sub generate_password_reset_code {
605605
return $code;
606606
}
607607

608+
after update => sub {
609+
my $self = shift;
610+
# Mark that this user has changed so sessions can update their cached data
611+
Wing->cache->set('user-changed-'.$self->id, 1, 60 * 60 * 24 * 7); # cache for 7 days
612+
};
613+
608614
before delete => sub {
609615
my $self = shift;
610616
$self->apikeypermissions->delete_all;
@@ -631,4 +637,31 @@ sub determine_avatar_uri {
631637
}
632638
}
633639

640+
sub user_to_json {
641+
my $self = shift;
642+
my $data = {};
643+
644+
foreach my $column ($self->result_source->columns) {
645+
my $value = $self->$column;
646+
if (defined $value && ref($value) eq 'DateTime') {
647+
$data->{$column} = Wing->to_mysql($value);
648+
}
649+
else {
650+
$data->{$column} = $value;
651+
}
652+
}
653+
654+
return $data;
655+
}
656+
657+
sub user_from_json {
658+
my ($class, $db, $data) = @_;
659+
660+
# Create a new user object with the data
661+
my $user = $db->resultset('User')->new($data);
662+
$user->in_storage(1);
663+
664+
return $user;
665+
}
666+
634667
1;

lib/Wing/Session.pm

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,22 @@ has user => (
9494
default => sub {
9595
my $self = shift;
9696
return undef unless $self->has_user_id;
97+
98+
# Check if we have cached user data first
99+
my $session_data = Wing->cache->get($self->key);
100+
if (defined $session_data && ref $session_data eq 'HASH' &&
101+
exists $session_data->{user_data} && defined $session_data->{user_data}) {
102+
# Recreate user object from cached data
103+
eval {
104+
my $user = Wing::DB::Result::User->user_from_json($self->db, $session_data->{user_data});
105+
if ($user && !$user->permanently_deactivated) {
106+
$user->current_session($self);
107+
return $user;
108+
}
109+
};
110+
}
111+
112+
# Fall back to database lookup
97113
my $user = $self->db->resultset('User')->find($self->user_id);
98114
if (defined $user && ! $user->permanently_deactivated) {
99115
$user->current_session($self);
@@ -132,6 +148,34 @@ sub check_permissions {
132148

133149
sub extend {
134150
my $self = shift;
151+
152+
# Check if user data has changed
153+
my $user_changed_key = 'user-changed-' . $self->user_id;
154+
if (Wing->cache->get($user_changed_key)) {
155+
# User data has changed, need to refresh
156+
my $user = $self->db->resultset('User')->find($self->user_id);
157+
158+
if (!defined $user || $user->permanently_deactivated) {
159+
# User no longer exists or is deactivated
160+
$self->end;
161+
}
162+
163+
# Check if password has changed
164+
elsif ($self->password_hash ne $user->password) {
165+
Wing->log->debug("SESSION: Password changed for user id:". $self->user_id . ", ending session");
166+
$self->end;
167+
}
168+
169+
# Password hasn't changed, update the cached user data
170+
else {
171+
$user->current_session($self);
172+
$self->user($user);
173+
$self->clear_user; # Clear the cached user attribute so it will reload
174+
}
175+
# Remove the user-changed marker
176+
Wing->cache->remove($user_changed_key);
177+
}
178+
135179
if ($self->password_hash ne $self->user->password) {
136180
Wing->log->debug("SESSION: Password hashes do not match, ending session for user id:". $self->user->id);
137181
Wing->log->debug("SESSION: Password hash sample: ".substr($self->password_hash,0,5));
@@ -150,6 +194,7 @@ sub extend {
150194
api_key_id => $self->api_key_id,
151195
ip_address => $self->ip_address,
152196
session_id => $self->id,
197+
user_data => $self->user->user_to_json,
153198
},
154199
60 * 60 * 24 * 7,
155200
);

0 commit comments

Comments
 (0)