Skip to content
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

[Feat] Insert multiple records from single event in chunks #149

Merged
merged 6 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
47 changes: 47 additions & 0 deletions migrations/Version202310191436392752_taoEventLog.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace oat\taoEventLog\migrations;

use common_ext_ExtensionsManager;
use Doctrine\DBAL\Schema\Schema;
use oat\oatbox\event\EventManager;
use oat\tao\scripts\tools\migrations\AbstractMigration;
use oat\taoEventLog\model\eventLog\LoggerService;

final class Version202310191436392752_taoEventLog extends AbstractMigration
{
public function getDescription(): string
{
return 'Attach DacChangedEvent to LoggerService';
}

public function up(Schema $schema): void
{
if ($this->getExtensionsManager()->isEnabled('taoDacSimple')) {
$this->getEventManager()->attach(
'oat\taoDacSimple\model\event\DacChangedEvent',
[LoggerService::class, 'log']
);
}
}

public function down(Schema $schema): void
{
$this->getEventManager()->detach(
'oat\taoDacSimple\model\event\DacChangedEvent',
[LoggerService::class, 'log']
);
}

private function getExtensionsManager(): common_ext_ExtensionsManager
{
return $this->getServiceLocator()->get(common_ext_ExtensionsManager::SERVICE_ID);
}

private function getEventManager(): EventManager
{
return $this->getServiceLocator()->get(EventManager::SERVICE_ID);
}
}
5 changes: 5 additions & 0 deletions model/StorageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ interface StorageInterface
*/
public function log(LogEntity $logEntity);

/**
* @param LogEntity[] $logEntities
*/
public function logMultiple(array $logEntities): bool;
gabrielfs7 marked this conversation as resolved.
Show resolved Hide resolved
gabrielfs7 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Search records in log which are meet the search criteria
*
Expand Down
56 changes: 39 additions & 17 deletions model/eventLog/LoggerService.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@
use common_exception_Error;
use common_session_Session;
use common_session_SessionManager;
use common_user_User;
use Context;
use DateTimeImmutable;
use JsonSerializable;
use oat\dtms\DateInterval;
use oat\oatbox\event\BulkEvent;
use oat\oatbox\event\Event;
use oat\oatbox\service\ServiceManager;
use oat\oatbox\user\User;
use oat\taoEventLog\model\storage\RdsStorage as DeprecatedRdsStorage;
use oat\dtms\DateTime;
use oat\taoEventLog\model\AbstractLog;
Expand Down Expand Up @@ -75,24 +76,26 @@ public function setAction($action = '')
*/
public function log(Event $event)
{
/** @var common_session_Session $session */
$session = common_session_SessionManager::getSession();

/** @var common_user_User $currentUser */
$currentUser = $session->getUser();

$data = is_subclass_of($event, JsonSerializable::class) ? $event : [];

$logEntity = new EventLogEntity(
$event,
$this->getAction(),
$currentUser,
(new DateTime('now', new \DateTimeZone('UTC'))),
$data
);
$currentUser = $this->getUser();

try {
$this->getStorage()->log($logEntity);
if ($event instanceof BulkEvent) {
$this->getStorage()->logMultiple(
array_map(
fn (array $eventData): EventLogEntity => $this->createEventLogEntity(
$event,
$currentUser,
$eventData
),
$event->getValues()
)
);

return;
}

$data = is_subclass_of($event, JsonSerializable::class) ? $event : [];
$this->getStorage()->log($this->createEventLogEntity($event, $currentUser, $data));
} catch (\Exception $e) {
\common_Logger::e('Error logging to DB ' . $e->getMessage());
}
Expand Down Expand Up @@ -137,4 +140,23 @@ protected function getStorage()
$storage = $this->getServiceManager()->get(self::SERVICE_ID)->getOption(self::OPTION_STORAGE);
return $this->getServiceManager()->get($storage);
}

private function getUser(): User
{
/** @var common_session_Session $session */
$session = common_session_SessionManager::getSession();

return $session->getUser();
}

private function createEventLogEntity(Event $event, User $user, array $data): EventLogEntity
{
return new EventLogEntity(
$event,
$this->getAction(),
$user,
(new DateTime('now', new \DateTimeZone('UTC'))),
$data
);
}
}
56 changes: 56 additions & 0 deletions model/eventLog/RdsStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use oat\taoEventLog\model\LogEntity;
use Doctrine\DBAL\Schema\SchemaException;
use oat\taoEventLog\model\storage\AbstractRdsStorage;
use Throwable;

/**
* Class RdsStorage
Expand All @@ -36,6 +37,8 @@ class RdsStorage extends AbstractRdsStorage

public const SERVICE_ID = 'taoEventLog/eventLogStorage';

public const OPTION_INSERT_CHUNK_SIZE = 'insertChunkSize';

public const EVENT_LOG_ID = self::ID;
public const EVENT_LOG_EVENT_NAME = 'event_name';
public const EVENT_LOG_ACTION = 'action';
Expand All @@ -44,6 +47,8 @@ class RdsStorage extends AbstractRdsStorage
public const EVENT_LOG_OCCURRED = 'occurred';
public const EVENT_LOG_PROPERTIES = 'properties';

private const DEFAULT_INSERT_CHUNK_SIZE = 1000;

/**
* @return string
*/
Expand Down Expand Up @@ -73,6 +78,52 @@ public function log(LogEntity $logEntity)
return $result === 1;
}

/**
* @param LogEntity[] $logEntities
*/
public function logMultiple(array $logEntities): bool
{
$inserts = array_map(
static fn (LogEntity $logEntity): array => [
self::EVENT_LOG_EVENT_NAME => $logEntity->getEvent()->getName(),
self::EVENT_LOG_ACTION => $logEntity->getAction(),
self::EVENT_LOG_USER_ID => $logEntity->getUser()->getIdentifier(),
self::EVENT_LOG_USER_ROLES => implode(',', $logEntity->getUser()->getRoles()),
self::EVENT_LOG_OCCURRED => $logEntity->getTime()->format(self::DATE_TIME_FORMAT),
self::EVENT_LOG_PROPERTIES => json_encode($logEntity->getData()),
],
$logEntities
);

try {
$persistence = $this->getPersistence();

$persistence->transactional(function () use ($inserts, $persistence) {
$insertCount = count($inserts);
$insertChunkSize = $this->getInsertChunkSize();

foreach (array_chunk($inserts, $insertChunkSize) as $index => $chunk) {
$this->logDebug(
sprintf(
'Processing chunk %d/%d with %d log entries',
$index + 1,
ceil($insertCount / $insertChunkSize),
count($chunk)
)
);

$persistence->insertMultiple($this->getTableName(), $chunk);
}
});

return true;
} catch (Throwable $exception) {
$this->logError('Error when inserting log entries: ' . $exception->getMessage());

return false;
}
}

/**
* @param array $params
* @deprecated use $this->search() instead
Expand Down Expand Up @@ -161,4 +212,9 @@ public static function install($persistence)
$persistence->exec($query);
}
}

private function getInsertChunkSize(): int
{
return $this->getOption(self::OPTION_INSERT_CHUNK_SIZE, self::DEFAULT_INSERT_CHUNK_SIZE);
}
}
5 changes: 5 additions & 0 deletions model/storage/RdsStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ public function log(LogEntity $logEntity)
{
}

public function logMultiple(array $logEntities): bool
{
return true;
}

public static function tableColumns()
{
}
Expand Down
4 changes: 4 additions & 0 deletions scripts/install/RegisterLoggerService.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ public function __invoke($params)
'oat\\taoDacSimple\\model\\event\\DacRemovedEvent',
[LoggerService::class, 'logEvent']
);
$this->registerEvent(
'oat\taoDacSimple\model\event\DacChangedEvent',
[LoggerService::class, 'log']
);
}

if ($extensionManager->isEnabled('taoTestTaker')) {
Expand Down
Loading