perf: only update last time when current value outdated (#3230)

* perf: only update last seen time when current > 120s ago

* perf: only update `last_activity_at` every 2 mins

* docs: add comment

* fix: add missing param

* test: add tests

* tests: attempt tests fix

* fix(tests): call `$this->app()`

* chore: extract hard-coded values out to private consts

* chore: increase diff

* Apply suggestions from code review
This commit is contained in:
David Wheatley 2021-12-28 00:39:42 +01:00 committed by GitHub
parent 64dab138c4
commit 2e94e31bb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 80 additions and 9 deletions

View File

@ -63,6 +63,12 @@ class AccessToken extends AbstractModel
*/
protected static $lifetime = 0;
/**
* Difference from the current `last_activity_at` attribute value before `updateLastSeen()`
* will update the attribute on the DB. Measured in seconds.
*/
private const LAST_ACTIVITY_UPDATE_DIFF = 90;
/**
* Generate an access token for the specified user.
*
@ -95,7 +101,11 @@ class AccessToken extends AbstractModel
*/
public function touch(ServerRequestInterface $request = null)
{
$this->last_activity_at = Carbon::now();
$now = Carbon::now();
if ($this->last_activity_at === null || $this->last_activity_at->diffInSeconds($now) > AccessToken::LAST_ACTIVITY_UPDATE_DIFF) {
$this->last_activity_at = $now;
}
if ($request) {
$this->last_ip_address = $request->getAttribute('ipAddress');

View File

@ -120,6 +120,12 @@ class User extends AbstractModel
*/
protected static $passwordCheckers;
/**
* Difference from the current `last_seen` attribute value before `updateLastSeen()`
* will update the attribute on the DB. Measured in seconds.
*/
private const LAST_SEEN_UPDATE_DIFF = 180;
/**
* Boot the model.
*
@ -564,7 +570,11 @@ class User extends AbstractModel
*/
public function updateLastSeen()
{
$this->last_seen_at = Carbon::now();
$now = Carbon::now();
if ($this->last_seen_at === null || $this->last_seen_at->diffInSeconds($now) > User::LAST_SEEN_UPDATE_DIFF) {
$this->last_seen_at = $now;
}
return $this;
}

View File

@ -12,6 +12,7 @@ namespace Flarum\Tests\integration\api\users;
use Carbon\Carbon;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Flarum\User\User;
class UpdateTest extends TestCase
{
@ -33,6 +34,15 @@ class UpdateTest extends TestCase
'password' => '$2y$10$LO59tiT7uggl6Oe23o/O6.utnF6ipngYjvMvaxo1TciKqBttDNKim', // BCrypt hash for "too-obscure"
'email' => 'normal2@machine.local',
'is_email_confirmed' => 1,
'last_seen_at' => Carbon::now()->subSecond(),
],
[
'id' => 4,
'username' => 'normal3',
'password' => '$2y$10$LO59tiT7uggl6Oe23o/O6.utnF6ipngYjvMvaxo1TciKqBttDNKim', // BCrypt hash for "too-obscure"
'email' => 'normal3@machine.local',
'is_email_confirmed' => 1,
'last_seen_at' => Carbon::now()->subHour(),
]
],
]);
@ -200,7 +210,7 @@ class UpdateTest extends TestCase
'relationships' => [
'groups' => [
'data' => [
['id'=> 1, 'type' => 'group']
['id' => 1, 'type' => 'group']
]
]
],
@ -323,7 +333,7 @@ class UpdateTest extends TestCase
'relationships' => [
'groups' => [
'data' => [
['id'=> 1, 'type' => 'group']
['id' => 1, 'type' => 'group']
]
]
],
@ -469,7 +479,7 @@ class UpdateTest extends TestCase
'relationships' => [
'groups' => [
'data' => [
['id'=> 4, 'type' => 'group']
['id' => 4, 'type' => 'group']
]
]
],
@ -517,7 +527,7 @@ class UpdateTest extends TestCase
'relationships' => [
'groups' => [
'data' => [
['id'=> 1, 'type' => 'group']
['id' => 1, 'type' => 'group']
]
]
],
@ -542,7 +552,7 @@ class UpdateTest extends TestCase
'relationships' => [
'groups' => [
'data' => [
['id'=> 1, 'type' => 'group']
['id' => 1, 'type' => 'group']
]
]
],
@ -649,8 +659,7 @@ class UpdateTest extends TestCase
'data' => [
'relationships' => [
'groups' => [
'data' => [
]
'data' => []
]
],
]
@ -659,4 +668,46 @@ class UpdateTest extends TestCase
);
$this->assertEquals(403, $response->getStatusCode());
}
/**
* @test
*/
public function last_seen_not_updated_quickly()
{
$this->app();
$user = User::find(3);
$response = $this->send(
$this->request('GET', '/api/users/3', [
'authenticatedAs' => 3,
'json' => [],
])
);
$body = json_decode($response->getBody(), true);
$last_seen = $body['data']['attributes']['lastSeenAt'];
$this->assertTrue(Carbon::parse($last_seen)->equalTo($user->last_seen_at));
}
/**
* @test
*/
public function last_seen_updated_after_long_time()
{
$this->app();
$user = User::find(4);
$response = $this->send(
$this->request('GET', '/api/users/4', [
'authenticatedAs' => 4,
'json' => [],
])
);
$body = json_decode($response->getBody(), true);
$last_seen = $body['data']['attributes']['lastSeenAt'];
$this->assertFalse(Carbon::parse($last_seen)->equalTo($user->last_seen_at));
}
}