Skip to content

Add caching experiment users #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions Modules/AbRouter/Console/RunUsersExperimentsIndexer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace Modules\AbRouter\Console;

use Illuminate\Console\Command;
use Modules\AbRouter\Models\Events\Event;
use Modules\AbRouter\Models\RelatedUsers\RelatedUser;
use Exception;
use Modules\AbRouter\Services\UsersExperiments\ProcessAllUsersExperimentsService;

class RunUsersExperimentsIndexer extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'abrouter:users-experiments-indexer';

/**
* The console command description.
*
* @var string
*/
protected $description = '';

/**
* @throws Exception
*/
public function handle()
{
/**
* @var ProcessAllUsersExperimentsService $processAllUsersExperiments
*/
$processAllUsersExperiments = app()->make(ProcessAllUsersExperimentsService::class);
$processAllUsersExperiments->processAll();
}
}
15 changes: 14 additions & 1 deletion Modules/AbRouter/Http/Controllers/ExperimentsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Modules\AbRouter\Http\Controllers;

use AbRouter\JsonApiFormatter\DataSource\DataProviders\SimpleDataProvider;
use Illuminate\Http\Response;
use Laravel\Passport\Token;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
Expand All @@ -17,6 +18,7 @@
use Modules\AbRouter\Http\Transformers\Experiments\SimpleRunTransformer;
use Modules\AbRouter\Http\Transformers\Experiments\UserExperimentsTransformer;
use Modules\AbRouter\Models\Experiments\Experiment;
use Modules\AbRouter\Repositories\AllUsersExperimentsHotStorageRepository;
use Modules\AbRouter\Repositories\Experiments\ExperimentBranchUserRepository;
use Modules\AbRouter\Repositories\Experiments\ExperimentUsersRepository;
use Modules\AbRouter\Services\Experiment\ExperimentService;
Expand Down Expand Up @@ -157,9 +159,20 @@ public function deleteUserFromExperiment(
public function allUsersExperiments(
ExperimentUsersRepository $repository,
AuthDecorator $authDecorator,
AllUsersExperimentsTransformer $allUsersExperimentsTransformer
AllUsersExperimentsTransformer $allUsersExperimentsTransformer,
AllUsersExperimentsHotStorageRepository $allUsersExperimentsHotStorageRepository
) {
$ownerId = $authDecorator->get()->getId();
if ($allUsersExperimentsHotStorageRepository->get($ownerId)) {
return response([
'status' => false,
'message' => 'Calculating, try in 5 minutes',
'data' => [
'retryIn' => 300,
],
Response::HTTP_PROCESSING
]);
}

return $allUsersExperimentsTransformer->getAllUsersExperiments(
$repository->getAllUsersExperiments($ownerId)
Expand Down
30 changes: 30 additions & 0 deletions Modules/AbRouter/Managers/AllUsersExperimentsHotStorageManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);

namespace Modules\AbRouter\Managers;

use Illuminate\Support\Collection;
use Modules\AbRouter\Transformers\HotKvStorageKeysTransformer;

class AllUsersExperimentsHotStorageManager
{
private HotKvStorageManager $hotKvStorageManager;

private HotKvStorageKeysTransformer $hotKvStorageKeysTransformer;

public function __construct(
HotKvStorageManager $hotKvStorageManager,
HotKvStorageKeysTransformer $hotKvStorageKeysTransformer
) {
$this->hotKvStorageManager = $hotKvStorageManager;
$this->hotKvStorageKeysTransformer = $hotKvStorageKeysTransformer;
}

public function store(int $ownerId, Collection $collection)
{
$this->hotKvStorageManager->store(
$this->hotKvStorageKeysTransformer->getAllUsersKey($ownerId),
serialize($collection)
);
}
}
14 changes: 14 additions & 0 deletions Modules/AbRouter/Managers/HotKvStorageManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);

namespace Modules\AbRouter\Managers;

use Illuminate\Support\Facades\Redis;

class HotKvStorageManager
{
public function store(string $key, string $data): bool
{
return Redis::connection()->client()->set($key, $data);
}
}
10 changes: 7 additions & 3 deletions Modules/AbRouter/Providers/AbRouterServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Eloquent\Factory;
use Modules\AbRouter\Console\CreateDatabase;
use Modules\AbRouter\Console\DropDatabase;
use Modules\AbRouter\Console\FillOwnerIdExperimentUserBranches;
use Modules\AbRouter\Console\MigrateTemporaryUser;

class AbRouterServiceProvider extends ServiceProvider
{
Expand All @@ -21,9 +24,9 @@ public function boot()
$this->registerConfig();
$this->registerViews();
$this->registerFactories();
$this->commands([\Modules\AbRouter\Console\CreateDatabase::class]);
$this->commands([\Modules\AbRouter\Console\DropDatabase::class]);
$this->commands([\Modules\AbRouter\Console\MigrateTemporaryUser::class]);
$this->commands([CreateDatabase::class]);
$this->commands([DropDatabase::class]);
$this->commands([MigrateTemporaryUser::class]);
$this->commands([FillOwnerIdExperimentUserBranches::class]);

$this->loadMigrationsFrom(module_path('AbRouter', 'Database/Migrations'));
Expand All @@ -37,6 +40,7 @@ public function boot()
public function register()
{
$this->app->register(RouteServiceProvider::class);
$this->app->register(KernelProvider::class);
}

/**
Expand Down
21 changes: 21 additions & 0 deletions Modules/AbRouter/Providers/KernelProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Modules\AbRouter\Providers;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Modules\AbRouter\Services\UsersExperiments\ProcessAllUsersExperimentsService;

class KernelProvider extends ConsoleKernel
{
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
/**
* @var ProcessAllUsersExperimentsService $processAllUsersExperiments
*/
$processAllUsersExperiments = app()->make(ProcessAllUsersExperimentsService::class);
$processAllUsersExperiments->processAll();
})->everyThirtyMinutes();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);

namespace Modules\AbRouter\Repositories;

use Illuminate\Support\Collection;
use Modules\AbRouter\Transformers\HotKvStorageKeysTransformer;

class AllUsersExperimentsHotStorageRepository
{
private HotKvStorageRepository $hotKvStorageRepository;

private HotKvStorageKeysTransformer $hotKvStorageKeysTransformer;

public function __construct(
HotKvStorageRepository $hotKvStorageRepository,
HotKvStorageKeysTransformer $hotKvStorageKeysTransformer
) {
$this->hotKvStorageRepository = $hotKvStorageRepository;
$this->hotKvStorageKeysTransformer = $hotKvStorageKeysTransformer;
}

public function get(int $ownerId): ?Collection
{
$data = $this->hotKvStorageRepository->get($this->hotKvStorageKeysTransformer->getAllUsersKey($ownerId));
if (empty($data)) {
return null;
}

return unserialize($data);
}
}
18 changes: 18 additions & 0 deletions Modules/AbRouter/Repositories/HotKvStorageRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);

namespace Modules\AbRouter\Repositories;

use Illuminate\Support\Facades\Redis;

class HotKvStorageRepository
{
/**
* @param string $key
* @return false|mixed|string
*/
public function get(string $key)
{
return Redis::connection()->client()->get($key);
}
}
26 changes: 26 additions & 0 deletions Modules/AbRouter/Repositories/Users/UsersRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);

namespace Modules\AbRouter\Repositories\Users;

use App\Models\User;
use Illuminate\Support\Collection;
use Modules\Core\Repositories\BaseRepository;

class UsersRepository extends BaseRepository
{
public function getUsersWithExperimentExists(): Collection
{
return $this
->query()
->select('users.*')
->join('experiments', 'users.id', '=', 'experiments.owner_id')
->whereNotNull('experiments.id')
->get();
}

protected function getModel()
{
return new User();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php
declare(strict_types =1);

namespace Modules\AbRouter\Services\UsersExperiments;

use App\Models\User;
use Modules\AbRouter\Repositories\Users\UsersRepository;

class ProcessAllUsersExperimentsService
{
private ProcessUsersExperimentsService $processUsersExperimentsService;

private UsersRepository $usersRepository;

public function __construct(
ProcessUsersExperimentsService $processUsersExperimentsService,
UsersRepository $usersRepository
) {
$this->processUsersExperimentsService = $processUsersExperimentsService;
$this->usersRepository = $usersRepository;
}

public function processAll(): void
{
$allUsers = $this->usersRepository->getUsersWithExperimentExists();
$allUsers->each(function (User $user) {
$this->processUsersExperimentsService->processByOwnerId($user->id);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php
declare(strict_types =1);

namespace Modules\AbRouter\Services\UsersExperiments;

use Modules\AbRouter\Managers\AllUsersExperimentsHotStorageManager;
use Modules\AbRouter\Repositories\Experiments\ExperimentUsersRepository;
use Modules\AbRouter\Transformers\AllUsersExperimentsTransformer;

class ProcessUsersExperimentsService
{
private ExperimentUsersRepository $experimentUsersRepository;

private AllUsersExperimentsTransformer $allUsersExperimentsTransformer;

private AllUsersExperimentsHotStorageManager $allUsersExperimentsHotStorageManager;

public function __construct(
ExperimentUsersRepository $experimentUsersRepository,
AllUsersExperimentsTransformer $allUsersExperimentsTransformer,
AllUsersExperimentsHotStorageManager $allUsersExperimentsHotStorageManager
) {
$this->experimentUsersRepository = $experimentUsersRepository;
$this->allUsersExperimentsTransformer = $allUsersExperimentsTransformer;
$this->allUsersExperimentsHotStorageManager = $allUsersExperimentsHotStorageManager;
}

public function processByOwnerId(int $ownerId): void
{
$allUsersExperiments = $this->allUsersExperimentsTransformer->getAllUsersExperiments(
$this->experimentUsersRepository->getAllUsersExperiments($ownerId)
);
$this->allUsersExperimentsHotStorageManager->store($ownerId, collect($allUsersExperiments));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function getAllUsersExperiments(Collection $usersExperiments): array
return $allUsersExperiments;
}

public function getExperiments(Collection $experimentUsers): array
private function getExperiments(Collection $experimentUsers): array
{
$experiments = [];

Expand Down
11 changes: 11 additions & 0 deletions Modules/AbRouter/Transformers/HotKvStorageKeysTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Modules\AbRouter\Transformers;

class HotKvStorageKeysTransformer
{
public function getAllUsersKey(int $ownerId): string
{
return sprintf('all-users-' . $ownerId);
}
}