diff --git a/.github/workflows/matomo-tests.yml b/.github/workflows/matomo-tests.yml
index 11b5185..c39d3c7 100644
--- a/.github/workflows/matomo-tests.yml
+++ b/.github/workflows/matomo-tests.yml
@@ -1,7 +1,7 @@
# Action for running tests
# This file has been automatically created.
# To recreate it you can run this command
-# ./console generate:test-action --plugin="QueuedTracking" --php-versions="7.2,8.3" --enable-redis --schedule-cron="0 2 * * 6"
+# ./console generate:test-action --plugin="QueuedTracking" --php-versions="7.2,8.4" --enable-redis --schedule-cron="0 2 * * 6"
name: Plugin QueuedTracking Tests
@@ -33,11 +33,11 @@ concurrency:
jobs:
PluginTests:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
- php: [ '7.2', '8.3' ]
+ php: [ '7.2', '8.4' ]
target: ['minimum_required_matomo', 'maximum_supported_matomo']
steps:
- uses: actions/checkout@v3
@@ -57,7 +57,7 @@ jobs:
artifacts-pass: ${{ secrets.ARTIFACTS_PASS }}
upload-artifacts: ${{ matrix.php == '7.2' && matrix.target == 'maximum_supported_matomo' }}
UI:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
with:
diff --git a/.github/workflows/phpcs.yml b/.github/workflows/phpcs.yml
new file mode 100644
index 0000000..5331d9d
--- /dev/null
+++ b/.github/workflows/phpcs.yml
@@ -0,0 +1,43 @@
+name: PHPCS check
+
+on: pull_request
+
+permissions:
+ actions: read
+ checks: read
+ contents: read
+ deployments: none
+ issues: read
+ packages: none
+ pull-requests: read
+ repository-projects: none
+ security-events: none
+ statuses: read
+
+jobs:
+ phpcs:
+ name: PHPCS
+ runs-on: ubuntu-24.04
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ lfs: false
+ persist-credentials: false
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '7.4'
+ tools: cs2pr
+ - name: Install dependencies
+ run:
+ composer init --name=matomo/queuedtracking --quiet;
+ composer --no-plugins config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true -n;
+ composer config repositories.matomo-coding-standards vcs https://github.com/matomo-org/matomo-coding-standards -n;
+ composer require matomo-org/matomo-coding-standards:dev-master;
+ composer install --dev --prefer-dist --no-progress --no-suggest
+ - name: Check PHP code styles
+ id: phpcs
+ run: ./vendor/bin/phpcs --report-full --standard=phpcs.xml --report-checkstyle=./phpcs-report.xml
+ - name: Show PHPCS results in PR
+ if: ${{ always() && steps.phpcs.outcome == 'failure' }}
+ run: cs2pr ./phpcs-report.xml --prepend-filename
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 517ee21..953176e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,33 @@
## Changelog
+5.1.3 - 2025-09-01
+- Add support for Sentinel password
+- Security hardening
+
+5.1.2 - 2025-07-07
+- Textual changes
+
+5.1.1 - 2024-10-23
+- Fixed fatal error when running queuedtracking:monitor command on Windows
+
+5.1.0 - 2024-10-21
+- Increased number of queue tracking workers to 4096
+- Enhance queue monitor and process commands
+- Added Redis cluster option
+
+5.0.7 - 2024-08-26
+- Fixed old redis sentinel config issue
+
+5.0.6
+- Fixed unable to configure redis socket with port 0
+
+5.0.5
+- Improved plugin reliability
+- Added system settings to list of text that can be translated
+
+5.0.4
+- Added plugin category for Marketplace
+
5.0.3
- Added code to skip maxmemory config check when --skip-max-memory-config-check=1
diff --git a/Commands/LockStatus.php b/Commands/LockStatus.php
index 8ffce4c..ab85bfb 100644
--- a/Commands/LockStatus.php
+++ b/Commands/LockStatus.php
@@ -1,4 +1,5 @@
setName('queuedtracking:lock-status');
diff --git a/Commands/Monitor.php b/Commands/Monitor.php
index 9b9be38..b9298d7 100644
--- a/Commands/Monitor.php
+++ b/Commands/Monitor.php
@@ -1,4 +1,5 @@
setName('queuedtracking:monitor');
- $this->setDescription('Shows and updates the current state of the queue every 2 seconds.');
+ if ($this->interactiveCapability()) {
+ $this->setDescription("Shows and updates the current state of the queue every 2 seconds.\n Key ,=first page, .=last page, 0-9=move to page section, arrow LEFT=prev page, RIGHT=next page, UP=next 10 pages, DOWN=prev 10 pages, q=quit");
+ } else {
+ $this->setDescription("Shows and updates the current state of the queue every 2 seconds.");
+ }
$this->addRequiredValueOption('iterations', null, 'If set, will limit the number of monitoring iterations done.');
+ $this->addRequiredValueOption('rowperpage', 'r', 'Number of queue worker displayed per page.', 16);
+ $this->addRequiredValueOption('jumptopage', 'p', 'Jump to page (p).', 1);
}
/**
@@ -58,34 +64,136 @@ protected function doExecute(): int
$output->writeln('The command ./console queuedtracking:process has to be executed to process request sets within queue');
}
- $output->writeln(sprintf('Up to %d workers will be used', $manager->getNumberOfAvailableQueues()));
- $output->writeln(sprintf('Processor will start once there are at least %s request sets in the queue',
- $manager->getNumberOfRequestsToProcessAtSameTime()));
+ $output->writeln(sprintf('Up to %d> workers will be used', $manager->getNumberOfAvailableQueues()));
+ $output->writeln(sprintf(
+ 'Processor will start once there are at least %s> request sets in the queue',
+ $manager->getNumberOfRequestsToProcessAtSameTime()
+ ));
$iterationCount = 0;
+ $qCurrentPage = $this->getJumpToPageFromArg();
+ $qCount = count($queues);
+ $qPerPAge = min(max($this->getPerPageFromArg(), 1), $qCount);
+ $qPageCount = ceil($qCount / $qPerPAge);
+
+ if ($this->interactiveCapability()) {
+ readline_callback_handler_install('', function () {
+ });
+ stream_set_blocking(STDIN, false);
+ }
+
+ $output->writeln(str_repeat("-", 30));
+ $output->writeln("" . str_pad(" Q INDEX", 10) . str_pad(" | REQUEST SETS", 20) . ">");
+ $output->writeln(str_repeat("-", 30));
+
+ $lastStatsTimer = microtime(true) - 2;
+ $lastSumInQueue = false;
+ $diffSumInQueue = 0;
+ $keyPressed = "";
+
+ $output->write(str_repeat("\r\n", $qPerPAge + 5));
+
while (1) {
- $memory = $backend->getMemoryStats(); // I know this will only work with redis currently as it is not defined in backend interface etc. needs to be refactored once we add another backend
+ if (microtime(true) - $lastStatsTimer >= 2 || $keyPressed != "") {
+ $output->write("\e[" . ($qPerPAge + 5) . "A\e[0G");
+
+ $qCurrentPage = min(max($qCurrentPage, 1), $qPageCount);
+ $memory = $backend->getMemoryStats(); // I know this will only work with redis currently as it is not defined in backend interface etc. needs to be refactored once we add another backend
- $numInQueue = array();
- foreach ($queues as $queue) {
- $numInQueue[] = $queue->getNumberOfRequestSetsInQueue();
+ $sumInQueue = 0;
+ foreach ($queues as $sumQ) {
+ $sumInQueue += $sumQ->getNumberOfRequestSetsInQueue();
+ }
+
+ if ($lastSumInQueue !== false) {
+ $diffSumInQueue = $lastSumInQueue - $sumInQueue;
+ $diffRps = round($diffSumInQueue / (microtime(true) - $lastStatsTimer), 2);
+ $diffSumInQueue = $diffSumInQueue < 0 ? "" . number_format(abs($diffRps)) . ">" : "" . number_format($diffRps) . ">";
+ }
+
+ $numInQueue = 0;
+ for ($idxPage = 0; $idxPage < $qPerPAge; $idxPage++) {
+ $idx = ($qCurrentPage - 1) * $qPerPAge + $idxPage;
+ if (isset($queues[$idx])) {
+ $q = $queues[$idx]->getNumberOfRequestSetsInQueue();
+ $numInQueue += (int)$q;
+ $output->writeln(str_pad($idx, 10, " ", STR_PAD_LEFT) . " | " . str_pad(number_format($q), 16, " ", STR_PAD_LEFT));
+ } else {
+ $output->writeln(str_pad("", 10) . " | " . str_pad("", 16));
+ }
+ }
+
+ $output->writeln(str_repeat("-", 30));
+ $output->writeln("" . str_pad(" " . ($qCount) . " Q", 10) . " | " . str_pad(number_format($sumInQueue) . " R", 16) . ">");
+ $output->writeln(str_repeat("-", 30));
+ $output->writeln(sprintf(
+ "Q [%s-%s] | page %s/%s>" . ($this->interactiveCapability() ? " | press (0-9.,q) or arrow(L,R,U,D)>" : " | use -p arg to jump to specific page>") . " | diff/sec %s \n" .
+ "%s used memory (%s peak). %d> workers active." . str_repeat(" ", 15),
+ ($idx - $qPerPAge + 1),
+ $idx,
+ $qCurrentPage,
+ $qPageCount,
+ $diffSumInQueue,
+ $memory['used_memory_human'] ?? 'Unknown',
+ $memory['used_memory_peak_human'] ?? 'Unknown',
+ $lock->getNumberOfAcquiredLocks()
+ ));
+
+ if (!is_null($iterations)) {
+ $iterationCount += 1;
+ if ($iterationCount >= $iterations) {
+ break;
+ }
+ }
+
+ $lastSumInQueue = $sumInQueue;
+ $lastStatsTimer = microtime(true);
}
- $message = sprintf('%s (%s) request sets left in queue. %s used memory (%s peak). %d workers active. ',
- array_sum($numInQueue),
- implode('+', $numInQueue),
- $memory['used_memory_human'],
- $memory['used_memory_peak_human'],
- $lock->getNumberOfAcquiredLocks());
- $output->write("\x0D");
- $output->write($message);
- if (!is_null($iterations)) {
- $iterationCount += 1;
- if ($iterationCount >= $iterations) {
- break;
+ if ($this->interactiveCapability()) {
+ $keyStroke = stream_get_contents(STDIN, 3);
+ $keyPressed = strlen($keyStroke) == 3 ? $keyStroke[2] : (strlen($keyStroke) > 0 ? $keyStroke[0] : "");
+ if ($keyPressed != "" and in_array($keyPressed, array(".", ",", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "q"))) {
+ switch ($keyPressed) {
+ case "0":
+ case "1":
+ case "2":
+ case "3":
+ case "4":
+ case "5":
+ case "6":
+ case "7":
+ case "8":
+ case "9":
+ $keyPressed = $keyPressed != "0" ? $keyPressed : "10";
+ $qCurrentPage = floor(($qCurrentPage - 0.1) / 10) * 10 + (int)$keyPressed;
+ break;
+ case "C":
+ $qCurrentPage++;
+ break;
+ case "D":
+ $qCurrentPage--;
+ break;
+ case "A":
+ $qCurrentPage += 10;
+ break;
+ case "B":
+ $qCurrentPage -= 10;
+ break;
+ case ",":
+ $qCurrentPage = 1;
+ break;
+ case ".":
+ $qCurrentPage = $qPageCount;
+ break;
+ case "q":
+ $output->writeln('');
+ die;
+ }
}
}
- sleep(2);
+
+ usleep(5000);
}
return self::SUCCESS;
@@ -112,4 +220,50 @@ private function getIterationsFromArg()
return $iterations;
}
+ /**
+ * Loads the `rowperpage` argument from the commands arguments.
+ *
+ * @return int|null
+ */
+ private function getPerPageFromArg()
+ {
+ $perPage = $this->getInput()->getOption('rowperpage');
+ if (!is_numeric($perPage)) {
+ throw new \Exception('rowperpage needs to be numeric');
+ } else {
+ $perPage = (int)$perPage;
+ if ($perPage <= 0) {
+ throw new \Exception('rowperpage needs to be a non-zero positive number');
+ }
+ }
+ return $perPage;
+ }
+
+ /**
+ * Loads the `jumptopage` argument from the commands arguments.
+ *
+ * @return int|null
+ */
+ private function getJumpToPageFromArg()
+ {
+ $perPage = $this->getInput()->getOption('jumptopage');
+ if (!is_numeric($perPage)) {
+ throw new \Exception('jumptopage needs to be numeric');
+ } else {
+ $perPage = (int)$perPage;
+ if ($perPage <= 0) {
+ throw new \Exception('jumptopage needs to be a non-zero positive number');
+ }
+ }
+ return $perPage;
+ }
+
+ /**
+ *
+ * @return bool
+ */
+ private function interactiveCapability()
+ {
+ return function_exists('readline_callback_handler_install');
+ }
}
diff --git a/Commands/PrintQueuedRequests.php b/Commands/PrintQueuedRequests.php
index 7dfd1dc..9628360 100644
--- a/Commands/PrintQueuedRequests.php
+++ b/Commands/PrintQueuedRequests.php
@@ -1,4 +1,5 @@
setName('queuedtracking:print-queued-requests');
@@ -54,7 +54,6 @@ protected function doExecute(): int
$output->writeln(var_export($requests, 1));
$output->writeln(sprintf('These were the requests of queue %s. Use --queue-id=%s to print only information for this queue.', $thisQueueId, $thisQueueId));
-
}
return self::SUCCESS;
diff --git a/Commands/Process.php b/Commands/Process.php
index 27e5c4d..1290fa8 100644
--- a/Commands/Process.php
+++ b/Commands/Process.php
@@ -1,4 +1,5 @@
setName('queuedtracking:process');
- $this->addRequiredValueOption('queue-id', null, 'If set, will only work on that specific queue. For example "0" or "1" (if there are multiple queues). Not recommended when only one worker is in use. If for example 4 workers are in use, you may want to use 0, 1, 2, or 3.');
- $this->addRequiredValueOption('force-num-requests-process-at-once', null, 'If defined, it overwrites the setting of how many requests will be picked out of the queue and processed at once. Must be a number which is >= 1. By default, the configured value from the settings will be used. This can be useful for example if you want to process every single request within the queue. If otherwise a batch size of say 100 is configured, then there may be otherwise 99 requests left in the queue. It can be also useful for testing purposes.');
- $this->setDescription('Processes all queued tracking requests in case there are enough requests in the queue and in case they are not already in process by another script. To keep track of the queue use the --verbose option or execute the queuedtracking:monitor command.');
+ $this->addRequiredValueOption(
+ 'queue-id',
+ null,
+ 'If set, will only work on that specific queue. For example "0" or "1" (if there are multiple queues). Not recommended when only one worker is in use. If for example 4 workers are in use, you may want to use 0, 1, 2, or 3.'
+ );
+ $this->addRequiredValueOption(
+ 'force-num-requests-process-at-once',
+ null,
+ 'If defined, it overwrites the setting of how many requests will be picked out of the queue and processed at once. Must be a number which is >= 1. By default, the configured value from the settings will be used.' .
+ ' This can be useful for example if you want to process every single request within the queue.' .
+ ' If otherwise a batch size of say 100 is configured, then there may be otherwise 99 requests left in the queue. It can be also useful for testing purposes.'
+ );
+ $this->addRequiredValueOption('cycle', 'c', 'The proccess will automatically loop for "n" cycle time(s), set "0" to infinite.', 1);
+ $this->addRequiredValueOption('sleep', 's', 'Take a nap for "n" second(s) before recycle, minimum is 1 second.', 1);
+ $this->addRequiredValueOption('delay', 'd', 'Delay before finished', 0);
+ $this->setDescription('Processes all queued tracking requests in case there are enough requests in the queue and in case they are not already in process by another script. To keep track of the queue use the --verbose' .
+ ' option or execute the queuedtracking:monitor command.');
}
/**
@@ -76,28 +90,83 @@ protected function doExecute(): int
throw new \Exception('Number of requests to process must be a number and at least 1');
}
- $output->writeln("Starting to process request sets, this can take a while");
-
register_shutdown_function(function () use ($queueManager) {
$queueManager->unlock();
});
- $startTime = microtime(true);
- $processor = new Processor($queueManager);
- $processor->setNumberOfMaxBatchesToProcess(500);
- $tracker = $processor->process();
- $neededTime = (microtime(true) - $startTime);
- $numRequestsTracked = $tracker->getCountOfLoggedRequests();
- $requestsPerSecond = $this->getNumberOfRequestsPerSecond($numRequestsTracked, $neededTime);
- Piwik::postEvent('Tracker.end');
+ $numberOfProcessCycle = $input->getOption('cycle');
+ if (!is_numeric($numberOfProcessCycle)) {
+ throw new \Exception('"cycle" needs to be numeric');
+ }
+ $numberOfProcessCycle = (int)$numberOfProcessCycle;
+ $infiniteCycle = $numberOfProcessCycle == 0;
+
+ $delayedBeforeFinish = (int)$input->getOption('delay');
+
+ $napster = max(1, $input->getOption('sleep'));
+ if (!is_numeric($napster)) {
+ throw new \Exception('"nap" needs to be numeric');
+ }
+ $napster = (int)$napster;
+
+ $lastTimeGotMoreThanZeroTrackedReq = microtime(true);
+ $originalNumberOfRequestsToProcessAtSameTime = $queueManager->getNumberOfRequestsToProcessAtSameTime();
+
+ while ($numberOfProcessCycle > 0 || $infiniteCycle) {
+ $wipingOutQueue = false;
+ if (microtime(true) - $lastTimeGotMoreThanZeroTrackedReq > 10) {
+ $queueManager->setNumberOfRequestsToProcessAtSameTime(1);
+ $wipingOutQueue = true;
+ $lastTimeGotMoreThanZeroTrackedReq = microtime(true);
+ }
+
+ if ($wipingOutQueue) {
+ $output->writeln(" TRYING TO WIPE OUT THE QUEUE >");
+ }
+ $output->writeln("Starting to process request sets, this can take a while");
+
+ $startTime = microtime(true);
+ $processor = new Processor($queueManager);
+ $processor->setNumberOfMaxBatchesToProcess(500);
+ $tracker = $processor->process();
+
+ $neededTime = (microtime(true) - $startTime);
+ $numRequestsTracked = $tracker->getCountOfLoggedRequests();
+ $requestsPerSecond = $this->getNumberOfRequestsPerSecond($numRequestsTracked, $neededTime);
+
+ $this->writeSuccessMessage(
+ array(sprintf('This worker finished queue processing with %sreq/s (%s requests in %02.2f seconds)', $requestsPerSecond, $numRequestsTracked, $neededTime))
+ );
+ Piwik::postEvent('Tracker.end');
+
+ if ($numRequestsTracked > 0) {
+ $lastTimeGotMoreThanZeroTrackedReq = microtime(true);
+ }
+
+ if (!$infiniteCycle) {
+ $numberOfProcessCycle--;
+ }
+ if ($numberOfProcessCycle > 0 || $infiniteCycle) {
+ $cTogo = $infiniteCycle ? "infinite" : $numberOfProcessCycle;
+ $output->writeln("===========================================================================");
+ $output->writeln("Taking a nap for {$napster} second(s), before re-running the process. ({$cTogo}) cyle(s) to go.");
+ $output->writeln("===========================================================================");
+ sleep($napster);
+ }
+
+ if ($wipingOutQueue) {
+ $queueManager->setNumberOfRequestsToProcessAtSameTime($originalNumberOfRequestsToProcessAtSameTime);
+ }
+ }
+ // Piwik::postEvent('Tracker.end');
$trackerEnvironment->destroy();
- $this->writeSuccessMessage(
- array(sprintf('This worker finished queue processing with %sreq/s (%s requests in %02.2f seconds)', $requestsPerSecond, $numRequestsTracked, $neededTime))
- );
+ if ($delayedBeforeFinish > 0) {
+ sleep($delayedBeforeFinish);
+ }
return self::SUCCESS;
}
diff --git a/Commands/Test.php b/Commands/Test.php
index 92df691..038f0a0 100644
--- a/Commands/Test.php
+++ b/Commands/Test.php
@@ -1,4 +1,5 @@
writeln('Timeout: ' . $settings->redisTimeout->getValue());
$output->writeln('Password: ' . $settings->redisPassword->getValue());
$output->writeln('Database: ' . $settings->redisDatabase->getValue());
- $output->writeln('UseSentinelBackend: ' . (int) $settings->useSentinelBackend->getValue());
+ $output->writeln('RedisBackendType: ' . $settings->getRedisType());
$output->writeln('SentinelMasterName: ' . $settings->sentinelMasterName->getValue());
$output->writeln('');
@@ -91,7 +92,7 @@ protected function doExecute(): int
$extension = new \ReflectionExtension('redis');
$output->writeln('PHPRedis version: ' . $extension->getVersion());
- } catch(\Exception $e) {
+ } catch (\Exception $e) {
$output->writeln('No PHPRedis extension (not a problem if sentinel is used):' . $e->getMessage());
}
}
@@ -107,12 +108,14 @@ protected function doExecute(): int
$redis = $backend->getConnection();
if ($isUsingRedis && !$shouldSkipCheckingMemoryConfigValues) {
-
$evictionPolicy = $this->getRedisConfig($redis, 'maxmemory-policy');
$output->writeln('MaxMemory Eviction Policy config: ' . $evictionPolicy);
if ($evictionPolicy !== 'allkeys-lru' && $evictionPolicy !== 'noeviction') {
- $output->writeln('The eviction policy can likely lead to errors when memory is low. We recommend to use eviction policy allkeys-lru or alternatively noeviction. Read more here: http://redis.io/topics/lru-cache');
+ $output->writeln(
+ 'The eviction policy can likely lead to errors when memory is low. We recommend to use eviction policy allkeys-lru or alternatively noeviction.' .
+ ' Read more here: http://redis.io/topics/lru-cache'
+ );
}
$evictionPolicy = $this->getRedisConfig($redis, 'maxmemory');
@@ -126,7 +129,7 @@ protected function doExecute(): int
$output->writeln('Redis is connected: ' . (int) $redis->isConnected());
}
- if ($backend->testConnection()){
+ if ($backend->testConnection()) {
$output->writeln('Connection works in general');
} else {
$output->writeln('Connection does not actually work: ' . $redis->getLastError());
@@ -144,7 +147,7 @@ protected function doExecute(): int
if (!$backend->setIfNotExists('foo', 'bar', 5)) {
$message = "setIfNotExists(foo, bar, 1) does not work, most likely we won't be able to acquire a lock: " . $backend->getLastError();
$output->writeln($message);
- } else{
+ } else {
$initialTtl = $backend->getTimeToLive('foo');
if ($initialTtl >= 3000 && $initialTtl <= 5000) {
$output->writeln('Initial expire seems to be set correctly');
@@ -195,7 +198,6 @@ protected function doExecute(): int
$backend->appendValuesToList('fooList', array('value1', 'value2', 'value3'));
$values = $backend->getFirstXValuesFromList('fooList', 2);
if ($values == array('value1', 'value2')) {
-
$backend->removeFirstXValuesFromList('fooList', 1);
$backend->removeFirstXValuesFromList('fooList', 1);
$values = $backend->getFirstXValuesFromList('fooList', 2);
@@ -204,7 +206,6 @@ protected function doExecute(): int
} else {
$output->writeln('List feature seems to work only partially: ' . var_export($values, 1));
}
-
} else {
$output->writeln('List feature seems to not work fine: ' . $redis->getLastError() . '');
}
@@ -222,9 +223,14 @@ protected function doExecute(): int
*/
private function getRedisConfig($redis, $configName)
{
- $config = $redis->config('GET', $configName);
- $value = strtolower(array_shift($config));
+ if ($redis instanceof \RedisCluster) {
+ $config = $redis->config('CONFIG', 'GET', $configName);
+ unset($config[0]);
+ } else {
+ $config = $redis->config('GET', $configName);
+ }
+ $value = strtolower(array_shift($config));
return $value;
}
@@ -242,11 +248,11 @@ private function testRedis($redis, $method, $params, $keyToCleanUp)
$result = call_user_func_array(array($redis, $method), $params);
- $paramsMapped = array_map(function($item) {
+ $paramsMapped = array_map(function ($item) {
if (is_string($item)) {
return $item;
}
-
+
return str_replace(["\r", "\n", " "], '', var_export($item, true));
}, $params);
$paramsInline = implode(', ', $paramsMapped);
diff --git a/Configuration.php b/Configuration.php
index ad54131..d55f1d6 100644
--- a/Configuration.php
+++ b/Configuration.php
@@ -1,4 +1,5 @@
getEngine();
- $statement = sprintf("CREATE TABLE IF NOT EXISTS `%s` ( %s ) ENGINE=%s DEFAULT CHARSET=utf8 ;",
+ $statement = sprintf(
+ "CREATE TABLE IF NOT EXISTS `%s` ( %s ) ENGINE=%s DEFAULT CHARSET=utf8 ;",
$table,
$createDefinition,
- $engine);
+ $engine
+ );
// DbHelper::createTable() won't work in tracker mode!
Db::get()->query($statement);
@@ -70,7 +74,6 @@ public function testConnection()
{
try {
return '1' == Db::get()->fetchOne('SELECT 1');
-
} catch (\Exception $e) {
Log::debug($e->getMessage());
}
@@ -96,7 +99,7 @@ public function appendValuesToList($key, $values)
{
$table = $this->makePrefixedKeyListTableName($key);
- $query = sprintf('INSERT INTO %s (`list_value`) VALUES (?)', $table);
+ $query = sprintf('INSERT INTO `%s` (`list_value`) VALUES (?)', $table);
foreach ($values as $value) {
if (empty($value)) {
continue;
@@ -105,7 +108,6 @@ public function appendValuesToList($key, $values)
$value = gzcompress($value);
try {
-
$result = Db::query($query, array($value));
if ($result === false) {
@@ -115,11 +117,9 @@ public function appendValuesToList($key, $values)
}
unset($result);
-
} catch (\Exception $e) {
// anything else but Mysqli in tracker mode (eg PDO or Mysqli in regular mode)
if ($this->isErrorTableNotExists($e)) {
-
// we create list tables only on demand
$this->createListTable($key);
Db::query($query, array($value));
@@ -143,7 +143,7 @@ public function getFirstXValuesFromList($key, $numValues)
}
$table = $this->makePrefixedKeyListTableName($key);
- $sql = sprintf('SELECT SQL_NO_CACHE list_value FROM %s ORDER BY idqueuelist ASC LIMIT %d OFFSET 0', $table, (int)$numValues);
+ $sql = sprintf('SELECT SQL_NO_CACHE list_value FROM `%s` ORDER BY idqueuelist ASC LIMIT %d OFFSET 0', $table, (int)$numValues);
try {
$values = Db::fetchAll($sql);
@@ -172,7 +172,7 @@ public function hasAtLeastXRequestsQueued($key, $numValuesRequired)
}
$table = $this->makePrefixedKeyListTableName($key);
- $sql = sprintf('SELECT SQL_NO_CACHE idqueuelist FROM %s LIMIT %d', $table, (int)$numValuesRequired);
+ $sql = sprintf('SELECT SQL_NO_CACHE idqueuelist FROM `%s` LIMIT %d', $table, (int)$numValuesRequired);
try {
$values = Db::fetchAll($sql);
@@ -194,7 +194,7 @@ public function removeFirstXValuesFromList($key, $numValues)
}
$table = $this->makePrefixedKeyListTableName($key);
- $sql = sprintf('DELETE FROM %s ORDER BY idqueuelist ASC LIMIT %d', $table, (int)$numValues);
+ $sql = sprintf('DELETE FROM `%s` ORDER BY idqueuelist ASC LIMIT %d', $table, (int)$numValues);
try {
Db::query($sql);
@@ -210,7 +210,7 @@ public function removeFirstXValuesFromList($key, $numValues)
public function getNumValuesInList($key)
{
$table = $this->makePrefixedKeyListTableName($key);
- $sql = sprintf('SELECT SQL_NO_CACHE max(idqueuelist) - min(idqueuelist) as num_entries FROM %s', $table);
+ $sql = sprintf('SELECT SQL_NO_CACHE max(idqueuelist) - min(idqueuelist) as num_entries FROM `%s`', $table);
try {
$value = Db::fetchOne($sql);
if ($value === null || $value === false) {
@@ -265,22 +265,26 @@ public function setIfNotExists($key, $value, $ttlInSeconds)
// todo: we could combine get() and keyExists() in one query!
if ($this->keyExists($key)) {
// most of the time an expired key should not exist... we don't want to lock the row unncessarily therefore we check first
- // if value exists...
+ // if value exists...
$sql = sprintf('DELETE FROM %s WHERE queue_key = ? and not (%s)', $this->tablePrefixed, $this->getQueryPartExpiryTime());
Db::query($sql, array($key));
}
- $query = sprintf('INSERT INTO %s (`queue_key`, `queue_value`, `expiry_time`)
+ $query = sprintf(
+ 'INSERT INTO %s (`queue_key`, `queue_value`, `expiry_time`)
VALUES (?,?,(UNIX_TIMESTAMP() + ?))',
- $this->tablePrefixed);
+ $this->tablePrefixed
+ );
// we make sure to update the row if the key is expired and consider it as "deleted"
try {
$query = Db::query($query, array($key, $value, (int) $ttlInSeconds));
} catch (\Exception $e) {
- if ($e->getCode() == 23000
+ if (
+ $e->getCode() == 23000
|| strpos($e->getMessage(), 'Duplicate entry') !== false
- || strpos($e->getMessage(), ' 1062 ') !== false) {
+ || strpos($e->getMessage(), ' 1062 ') !== false
+ ) {
return false;
}
throw $e;
@@ -431,5 +435,4 @@ public function flushAll()
$this->dropTable($table);
}
}
-
}
diff --git a/Queue/Backend/Redis.php b/Queue/Backend/Redis.php
index 62c80dd..e9d6f9c 100644
--- a/Queue/Backend/Redis.php
+++ b/Queue/Backend/Redis.php
@@ -1,4 +1,5 @@
connectIfNeeded();
return 'TEST' === $this->redis->echo('TEST');
-
} catch (\Exception $e) {
Log::debug($e->getMessage());
}
@@ -117,11 +118,11 @@ public function getFirstXValuesFromList($key, $numValues)
$this->connectIfNeeded();
$values = $this->redis->lRange($key, 0, $numValues - 1);
- foreach($values as $key => $value) {
+ foreach ($values as $key => $value) {
$tmpValue = @gzuncompress($value); // Avoid warning if not compressed
-
+
// if empty, string is not compressed. Use original value
- if(empty($tmpValue)) {
+ if (empty($tmpValue)) {
$values[$key] = $value;
} else {
$values[$key] = $tmpValue;
@@ -214,7 +215,7 @@ public function getKeysMatchingPattern($pattern)
{
$this->connectIfNeeded();
- return $this->redis->keys($pattern);
+ return $this->redis->keys($pattern) ?: [];
}
public function expireIfKeyHasValue($key, $value, $ttlInSeconds)
@@ -273,8 +274,13 @@ protected function connect()
return $success;
}
- public function setConfig($host, $port, $timeout, $password)
- {
+ public function setConfig(
+ $host,
+ $port,
+ $timeout,
+ #[\SensitiveParameter]
+ $password
+ ) {
$this->disconnect();
$this->host = $host;
diff --git a/Queue/Backend/RedisCluster.php b/Queue/Backend/RedisCluster.php
new file mode 100644
index 0000000..a9a4d0e
--- /dev/null
+++ b/Queue/Backend/RedisCluster.php
@@ -0,0 +1,354 @@
+connectIfNeeded();
+ return 'TEST' === $this->redis->echo('TEST_ECHO', 'TEST');
+ } catch (\Exception $e) {
+ Log::debug($e->getMessage());
+ }
+
+ return false;
+ }
+
+ public function getServerVersion()
+ {
+ $this->connectIfNeeded();
+
+ $server = $this->redis->info('server');
+
+ if (empty($server)) {
+ return '';
+ }
+
+ $version = $server['redis_version'];
+
+ return $version;
+ }
+
+ public function getLastError()
+ {
+ $this->connectIfNeeded();
+
+ return $this->redis->getLastError();
+ }
+
+ /**
+ * Returns converted bytes to B,K,M,G,T.
+ * @param int|float|double $bytes byte number.
+ * @param int $precision decimal round.
+ * * @return string
+ */
+ private function formatBytes($bytes, $precision = 2)
+ {
+ $units = array('B', 'K', 'M', 'G', 'T');
+
+ $bytes = max($bytes, 0);
+ $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
+ $pow = min($pow, count($units) - 1);
+ $bytes /= (1 << (10 * $pow));
+
+ return round($bytes, $precision) . $units[$pow];
+ }
+
+ public function getMemoryStats()
+ {
+ $this->connectIfNeeded();
+
+ $hosts = explode(',', $this->host);
+ $ports = explode(',', $this->port);
+
+ $memory = array (
+ 'used_memory_human' => 0,
+ 'used_memory_peak_human' => 0
+ );
+
+ foreach ($hosts as $idx => $host) {
+ $info = $this->redis->info(array($host, (int)$ports[$idx]), 'memory');
+ $memory['used_memory_human'] += $info['used_memory'] ?? 0;
+ $memory['used_memory_peak_human'] += $info['used_memory_peak'] ?? 0;
+ }
+
+ $memory['used_memory_human'] = $this->formatBytes($memory['used_memory_human']);
+ $memory['used_memory_peak_human'] = $this->formatBytes($memory['used_memory_peak_human']);
+
+ return $memory;
+ }
+
+ /**
+ * Returns the time to live of a key that can expire in ms.
+ * @param $key
+ * @return int
+ */
+ public function getTimeToLive($key)
+ {
+ $this->connectIfNeeded();
+
+ $ttl = $this->redis->pttl($key);
+
+ if ($ttl == -1) {
+ // key exists but has no associated expire
+ return 99999999;
+ }
+
+ if ($ttl == -2) {
+ // key does not exist
+ return 0;
+ }
+
+ return $ttl;
+ }
+
+ public function appendValuesToList($key, $values)
+ {
+ $this->connectIfNeeded();
+
+ foreach ($values as $value) {
+ $this->redis->rPush($key, gzcompress($value));
+ }
+
+ // usually we would simply do call_user_func_array(array($redis, 'rPush'), $values); as rpush supports multiple values
+ // at once but it seems to be not implemented yet see https://github.com/nicolasff/phpredis/issues/366
+ // doing it in one command should be much faster as it requires less tcp communication. Anyway, we currently do
+ // not write multiple values at once ... so it is ok!
+ }
+
+ public function getFirstXValuesFromList($key, $numValues)
+ {
+ if ($numValues <= 0) {
+ return array();
+ }
+
+ $this->connectIfNeeded();
+ $values = $this->redis->lRange($key, 0, $numValues - 1);
+ foreach ($values as $key => $value) {
+ $tmpValue = @gzuncompress($value); // Avoid warning if not compressed
+
+ // if empty, string is not compressed. Use original value
+ if (empty($tmpValue)) {
+ $values[$key] = $value;
+ } else {
+ $values[$key] = $tmpValue;
+ }
+ }
+
+ return $values;
+ }
+
+ public function removeFirstXValuesFromList($key, $numValues)
+ {
+ if ($numValues <= 0) {
+ return;
+ }
+
+ $this->connectIfNeeded();
+ $this->redis->ltrim($key, $numValues, -1);
+ }
+
+ public function hasAtLeastXRequestsQueued($key, $numValuesRequired)
+ {
+ if ($numValuesRequired <= 0) {
+ return true;
+ }
+
+ $numActual = $this->getNumValuesInList($key);
+
+ return $numActual >= $numValuesRequired;
+ }
+
+ public function getNumValuesInList($key)
+ {
+ $this->connectIfNeeded();
+
+ return $this->redis->lLen($key);
+ }
+
+ public function setIfNotExists($key, $value, $ttlInSeconds)
+ {
+ $this->connectIfNeeded();
+ $wasSet = $this->redis->set($key, $value, array('nx', 'ex' => $ttlInSeconds));
+
+ return $wasSet;
+ }
+
+ /**
+ * @internal for tests only
+ * @return \RedisCluster
+ */
+ public function getConnection()
+ {
+ return $this->redis;
+ }
+
+ /**
+ * @internal for tests only
+ */
+ public function delete($key)
+ {
+ $this->connectIfNeeded();
+
+ return $this->redis->del($key) > 0;
+ }
+
+ public function deleteIfKeyHasValue($key, $value)
+ {
+ if (empty($value)) {
+ return false;
+ }
+
+ $this->connectIfNeeded();
+
+ // see http://redis.io/topics/distlock
+ $script = 'if redis.call("GET",KEYS[1]) == ARGV[1] then
+ return redis.call("DEL",KEYS[1])
+else
+ return 0
+end';
+
+ // ideally we would use evalSha to reduce bandwidth!
+ return (bool) $this->evalScript($script, array($key), array($value));
+ }
+
+ protected function evalScript($script, $keys, $args)
+ {
+ return $this->redis->eval($script, array_merge($keys, $args), count($keys));
+ }
+
+ public function getKeysMatchingPattern($pattern)
+ {
+ $this->connectIfNeeded();
+
+ return $this->redis->keys($pattern);
+ }
+
+ public function expireIfKeyHasValue($key, $value, $ttlInSeconds)
+ {
+ if (empty($value)) {
+ return false;
+ }
+
+ $this->connectIfNeeded();
+
+ $script = 'if redis.call("GET",KEYS[1]) == ARGV[1] then
+ return redis.call("EXPIRE",KEYS[1], ARGV[2])
+else
+ return 0
+end';
+ // ideally we would use evalSha to reduce bandwidth!
+ return (bool) $this->evalScript($script, array($key), array($value, (int) $ttlInSeconds));
+ }
+
+ public function get($key)
+ {
+ $this->connectIfNeeded();
+
+ return $this->redis->get($key);
+ }
+
+ /**
+ * @internal
+ */
+ public function flushAll()
+ {
+ $this->connectIfNeeded();
+
+ $hosts = explode(',', $this->host);
+ $ports = explode(',', $this->port);
+
+ foreach ($hosts as $idx => $host) {
+ $this->redis->flushDB(array($host, (int)$ports[$idx]));
+ }
+ }
+
+ private function connectIfNeeded()
+ {
+ if (!$this->isConnected()) {
+ $this->connect();
+ }
+ }
+
+ protected function connect()
+ {
+ $hosts = explode(',', $this->host);
+ $ports = explode(',', $this->port);
+
+ if (count($hosts) !== count($ports)) {
+ throw new Exception(Piwik::translate('QueuedTracking_NumHostsNotMatchNumPorts'));
+ }
+
+ $hostsPorts = array_map(fn($host, $port): string => "$host:$port", $hosts, $ports);
+
+ try {
+ $this->redis = new \RedisCluster(null, $hostsPorts, $this->timeout, $this->timeout, true, $this->password);
+ return true;
+ } catch (Exception $e) {
+ throw new Exception('Could not connect to redis cluster: ' . $e->getMessage());
+ }
+ }
+
+ public function setConfig(
+ $host,
+ $port,
+ $timeout,
+ #[\SensitiveParameter]
+ $password
+ ) {
+ $this->disconnect();
+
+ $this->host = $host;
+ $this->port = $port;
+ $this->timeout = $timeout;
+
+ if (!empty($password)) {
+ $this->password = $password;
+ }
+ }
+
+ private function disconnect()
+ {
+ if ($this->isConnected()) {
+ $this->redis->close();
+ }
+
+ $this->redis = null;
+ }
+
+ private function isConnected()
+ {
+ return isset($this->redis);
+ }
+
+ public function setDatabase($database)
+ {
+ $this->database = $database;
+ }
+}
diff --git a/Queue/Backend/Sentinel.php b/Queue/Backend/Sentinel.php
index 93bf1fe..fc73d8a 100644
--- a/Queue/Backend/Sentinel.php
+++ b/Queue/Backend/Sentinel.php
@@ -1,4 +1,5 @@
host);
@@ -34,12 +41,15 @@ protected function connect()
$configuredClient = new \Credis_Client($host, $ports[$index], $timeout = 0.5, $persistent = false);
$configuredClient->forceStandalone();
$configuredClient->connect();
+ if ($this->usePasswordForSentinelInstances && !empty($this->password)) {
+ $configuredClient->auth($this->password);
+ }
$configuredSentinel = new \Credis_Sentinel($configuredClient);
$master = $configuredSentinel->getMasterAddressByName($this->masterName);
if (!empty($master)) {
if (!class_exists('\Redis') && $this->timeout == 0) {
- $this->timeout === 0.05;
+ $this->timeout = 0.05;
}
$client = new \Credis_Client($master[0], $master[1], $this->timeout, $persistent = false, $this->database, $this->password);
@@ -49,7 +59,6 @@ protected function connect()
return true;
}
-
} catch (Exception $e) {
Log::debug($e->getMessage());
}
@@ -63,9 +72,13 @@ public function setSentinelMasterName($name)
$this->masterName = $name;
}
+ public function setUsePasswordForSentinelInstances(bool $usePasswordForSentinelInstances)
+ {
+ $this->usePasswordForSentinelInstances = $usePasswordForSentinelInstances;
+ }
+
protected function evalScript($script, $keys, $args)
{
return $this->redis->eval($script, $keys, $args);
}
-
}
diff --git a/Queue/Factory.php b/Queue/Factory.php
index 6db34cd..e2d4c28 100644
--- a/Queue/Factory.php
+++ b/Queue/Factory.php
@@ -1,4 +1,5 @@
setSentinelMasterName($masterName);
+ $redis->setDatabase($database);
+ if (!empty($settings->getUsePasswordForSentinelInstances())) {
+ $redis->setUsePasswordForSentinelInstances(true);
+ }
}
+ } elseif ($settings->isUsingClusterBackend()) {
+ $redis = new Queue\Backend\RedisCluster();
} else {
$redis = new Queue\Backend\Redis();
+ $redis->setDatabase($database);
}
$redis->setConfig($host, $port, $timeout, $password);
- $redis->setDatabase($database);
-
return $redis;
}
-
}
diff --git a/Queue/Lock.php b/Queue/Lock.php
index 5b6189f..84a9561 100644
--- a/Queue/Lock.php
+++ b/Queue/Lock.php
@@ -1,4 +1,5 @@
createQueue($queueId);
while ($requestSets = $queue->getRequestSetsToProcess()) {
-
foreach ($requestSets as $requestSet) {
$this->addRequestSetToQueues($requestSet);
}
@@ -213,12 +214,14 @@ private function getVisitorIdFromRequest(Tracker\Request $request)
protected function getQueueIdForVisitor($visitorId)
{
- $visitorId = strtolower(substr($visitorId, 0, 1));
-
- if (isset($this->mappingLettersToNumeric[$visitorId])) {
- $id = $this->mappingLettersToNumeric[$visitorId];
+ $visitorId = strtolower(substr($visitorId, 0, 3));
+ if (ctype_xdigit($visitorId) === true) {
+ $id = hexdec($visitorId);
} else {
- $id = ord($visitorId);
+ $pos1 = ord($visitorId);
+ $pos2 = isset($visitorId[1]) ? ord($visitorId[1]) : $pos1;
+ $pos3 = isset($visitorId[2]) ? ord($visitorId[2]) : $pos2;
+ $id = $pos1 + $pos2 + $pos3;
}
return $id % $this->numQueuesAvailable;
@@ -261,7 +264,7 @@ public function lockNext()
if ($shouldProcess && $this->lock->acquireLock($this->forceQueueId)) {
return $queue;
}
-
+
// do not try to acquire a different lock
return;
}
diff --git a/Queue/Processor.php b/Queue/Processor.php
index 439945d..e69a327 100644
--- a/Queue/Processor.php
+++ b/Queue/Processor.php
@@ -1,4 +1,5 @@
queueManager->lockNext()) {
Common::printDebug('Acquired lock for queue ' . $queue->getId());
@@ -157,7 +157,6 @@ public function process(Tracker $tracker = null)
$this->queueManager->unlock();
}
-
} catch (Exception $e) {
Common::printDebug('Failed to process a request set: ' . $e->getMessage());
@@ -243,5 +242,4 @@ private function forceRollbackAndThrowExceptionAsAnotherProcessMightProcessSameR
$this->handler->rollBack($tracker);
throw new LockExpiredException(sprintf("Rolled back during %s as we no longer have lock or the lock was never acquired. So far tracker processed %s requests", $activity, $tracker->getCountOfLoggedRequests()));
}
-
}
diff --git a/Queue/Processor/Handler.php b/Queue/Processor/Handler.php
index a9543c1..f0cdb7b 100644
--- a/Queue/Processor/Handler.php
+++ b/Queue/Processor/Handler.php
@@ -1,4 +1,5 @@
Piwik::translate('QueuedTracking_AvailableRedisBackendTypeStandAlone'),
+ 2 => Piwik::translate('QueuedTracking_AvailableRedisBackendTypeSentinel'),
+ 3 => Piwik::translate('QueuedTracking_AvailableRedisBackendTypeCluster')
+ );
+ }
+
+ protected function assignValueIsIntValidator(FieldConfig $field)
+ {
+ $field->validate = function ($value) {
+ if ((is_string($value) && !ctype_digit($value)) || (!is_string($value) && !is_int($value))) {
+ throw new \Exception(Piwik::translate('QueuedTracking_ExceptionValueIsNotInt'));
+ }
+ };
+ }
+
protected function init()
{
$this->backend = $this->createBackendSetting();
- $this->useSentinelBackend = $this->createUseSentinelBackend();
+ $this->useWhatRedisBackendType = $this->createUseWhatRedisBackendType();
$this->sentinelMasterName = $this->createSetSentinelMasterName();
+ $this->usePasswordForSentinelInstances = $this->createUsePasswordForSentinelInstances();
$this->redisHost = $this->createRedisHostSetting();
$this->redisPort = $this->createRedisPortSetting();
$this->redisTimeout = $this->createRedisTimeoutSetting();
@@ -74,7 +100,17 @@ protected function init()
public function isUsingSentinelBackend()
{
- return $this->useSentinelBackend->getValue();
+ return $this->useWhatRedisBackendType->getValue() === 2;
+ }
+
+ public function isUsingClusterBackend()
+ {
+ return $this->useWhatRedisBackendType->getValue() === 3;
+ }
+
+ public function getRedisType()
+ {
+ return $this->useWhatRedisBackendType->getValue();
}
public function getSentinelMasterName()
@@ -82,6 +118,11 @@ public function getSentinelMasterName()
return $this->sentinelMasterName->getValue();
}
+ public function getUsePasswordForSentinelInstances()
+ {
+ return $this->usePasswordForSentinelInstances->getValue();
+ }
+
public function isUsingUnixSocket()
{
return substr($this->redisHost->getValue(), 0, 1) === '/';
@@ -92,22 +133,21 @@ private function createRedisHostSetting()
$self = $this;
return $this->makeSetting('redisHost', $default = '127.0.0.1', FieldConfig::TYPE_STRING, function (FieldConfig $field) use ($self) {
- $field->title = 'Redis host or unix socket';
+ $field->title = Piwik::translate('QueuedTracking_RedisHostFieldTitle');
$field->condition = 'backend=="redis"';
$field->uiControl = FieldConfig::UI_CONTROL_TEXT;
$field->uiControlAttributes = array('size' => 500);
- $field->inlineHelp = 'Remote host or unix socket of the Redis server. Max 500 characters are allowed.';
+ $field->inlineHelp = Piwik::translate('QueuedTracking_RedisHostFieldHelp') . ''
+ . Piwik::translate('QueuedTracking_RedisHostFieldHelpExtended') . '';
- if ($self->isUsingSentinelBackend()) {
- $field->inlineHelp .= $self->getInlineHelpSentinelMultipleServers('hosts');
+ if ($self->isUsingSentinelBackend() || $self->isUsingClusterBackend()) {
+ $field->inlineHelp .= '' . Piwik::translate('QueuedTracking_RedisHostFieldHelpExtendedSentinel') . '';
}
$field->validate = function ($value) use ($self) {
$self->checkMultipleServersOnlyConfiguredWhenSentinelIsEnabled($value);
- if (strlen($value) > 500) {
- throw new \Exception('Max 500 characters allowed');
- }
+ (new CharacterLength(1, 500))->validate($value);
};
$field->transform = function ($value) use ($self) {
@@ -128,36 +168,29 @@ private function createRedisPortSetting()
}
return $this->makeSetting('redisPort', $default, FieldConfig::TYPE_STRING, function (FieldConfig $field) use ($self) {
- $field->title = 'Redis port';
+ $field->title = Piwik::translate('QueuedTracking_RedisPortFieldTitle');
$field->condition = 'backend=="redis"';
$field->uiControl = FieldConfig::UI_CONTROL_TEXT;
$field->uiControlAttributes = array('size' => 100);
- $field->inlineHelp = 'Port the Redis server is running on. Value should be between 1 and 65535. Use 0 if you are using unix socket to connect to Redis server.';
+ $field->inlineHelp = Piwik::translate('QueuedTracking_RedisPortFieldHelp') . '';
- if ($self->isUsingSentinelBackend()) {
- $field->inlineHelp .= $self->getInlineHelpSentinelMultipleServers('ports');
+ if ($self->isUsingSentinelBackend() || $self->isUsingClusterBackend()) {
+ $field->inlineHelp .= '' . Piwik::translate('QueuedTracking_RedisHostFieldHelpExtendedSentinel') . '';
}
$field->validate = function ($value) use ($self) {
$self->checkMultipleServersOnlyConfiguredWhenSentinelIsEnabled($value);
- $ports = $self->convertCommaSeparatedValueToArray($value);
-
- foreach ($ports as $port) {
- if (!is_numeric($port)) {
- throw new \Exception('A port has to be a number');
- }
- $port = (int) $port;
-
- if ($port < 1 && !$this->isUsingUnixSocket()) {
- throw new \Exception('Port has to be at least 1');
- }
-
- if ($port >= 65535) {
- throw new \Exception('Port should be max 65535');
+ if ($self->isUsingSentinelBackend() || $self->isUsingClusterBackend()) {
+ $ports = explode(',', $value);
+ foreach ($ports as $port) {
+ (new NumberRange(0, 65535))->validate(trim($port));
}
+ } else {
+ (new NumberRange(0, 65535))->validate($value);
}
};
+
$field->transform = function ($value) use ($self) {
$ports = $self->convertCommaSeparatedValueToArray($value);
$ports = array_map('intval', $ports);
@@ -170,21 +203,13 @@ private function createRedisPortSetting()
private function createRedisTimeoutSetting()
{
$setting = $this->makeSetting('redisTimeout', $default = 0.0, FieldConfig::TYPE_FLOAT, function (FieldConfig $field) {
- $field->title = 'Redis timeout';
+ $field->title = Piwik::translate('QueuedTracking_RedisTimeoutFieldTitle');
$field->condition = 'backend=="redis"';
$field->uiControl = FieldConfig::UI_CONTROL_TEXT;
$field->uiControlAttributes = array('size' => 5);
- $field->inlineHelp = 'Redis connection timeout in seconds. "0.0" meaning unlimited. Can be a float eg "2.5" for a connection timeout of 2.5 seconds.';
- $field->validate = function ($value) {
-
- if (!is_numeric($value)) {
- throw new \Exception('Timeout should be numeric, eg "0.1"');
- }
-
- if (strlen($value) > 5) {
- throw new \Exception('Max 5 characters allowed');
- }
- };
+ $field->inlineHelp = Piwik::translate('QueuedTracking_RedisTimeoutFieldTitle') . '';
+ $field->validators[] = new NumberRange();
+ $field->validators[] = new CharacterLength(1, 5);
});
// we do not expose this one to the UI currently. That's on purpose
@@ -197,21 +222,12 @@ private function createNumberOfQueueWorkerSetting()
{
$numQueueWorkers = new NumWorkers('numQueueWorkers', $default = 1, FieldConfig::TYPE_INT, $this->pluginName);
$numQueueWorkers->setConfigureCallback(function (FieldConfig $field) {
- $field->title = 'Number of queue workers';
+ $field->title = Piwik::translate('QueuedTracking_NumberOfQueueWorkersFieldTitle');
$field->uiControl = FieldConfig::UI_CONTROL_TEXT;
$field->uiControlAttributes = array('size' => 5);
- $field->inlineHelp = 'Number of allowed maximum queue workers. Accepts a number between 1 and 16. Best practice is to set the number of CPUs you want to make available for queue processing. Be aware you need to make sure to start the workers manually. We recommend to not use 9-15 workers, rather use 8 or 16 as the queue might not be distributed evenly into different queues.';
- $field->validate = function ($value) {
-
- if (!is_numeric($value)) {
- throw new \Exception('Number of queue workers should be an integer, eg "6"');
- }
-
- $value = (int) $value;
- if ($value > 16 || $value < 1) {
- throw new \Exception('Only 1-16 workers allowed');
- }
- };
+ $field->inlineHelp = Piwik::translate('QueuedTracking_NumberOfQueueWorkersFieldHelpNew') . '';
+ $this->assignValueIsIntValidator($field);
+ $field->validators[] = new NumberRange(1, 4096);
});
$this->addSetting($numQueueWorkers);
@@ -222,36 +238,26 @@ private function createNumberOfQueueWorkerSetting()
private function createRedisPasswordSetting()
{
return $this->makeSetting('redisPassword', $default = '', FieldConfig::TYPE_STRING, function (FieldConfig $field) {
- $field->title = 'Redis password';
+ $field->title = Piwik::translate('QueuedTracking_RedisPasswordFieldTitle');
$field->condition = 'backend=="redis"';
$field->uiControl = FieldConfig::UI_CONTROL_PASSWORD;
$field->uiControlAttributes = array('size' => 128);
- $field->inlineHelp = 'Password set on the Redis server, if any. Redis can be instructed to require a password before allowing clients to execute commands.';
- $field->validate = function ($value) {
- if (is_string($value) && strlen($value) > 128) {
- throw new \Exception('Max 128 characters allowed');
- }
- };
+ $field->inlineHelp = Piwik::translate('QueuedTracking_RedisPasswordFieldHelp') . '';
+ $field->validators[] = new CharacterLength(null, 128);
});
}
private function createRedisDatabaseSetting()
{
return $this->makeSetting('redisDatabase', $default = 0, FieldConfig::TYPE_INT, function (FieldConfig $field) {
- $field->title = 'Redis database';
+ $field->title = Piwik::translate('QueuedTracking_RedisDatabaseFieldTitle');
$field->condition = 'backend=="redis"';
$field->uiControl = FieldConfig::UI_CONTROL_TEXT;
$field->uiControlAttributes = array('size' => 5);
- $field->inlineHelp = 'In case you are using Redis for caching make sure to use a different database.';
- $field->validate = function ($value) {
- if (!is_numeric($value) || false !== strpos($value, '.')) {
- throw new \Exception('The database has to be an integer');
- }
-
- if (strlen($value) > 5) {
- throw new \Exception('Max 5 digits allowed');
- }
- };
+ $field->inlineHelp = Piwik::translate('QueuedTracking_RedisDatabaseFieldHelp') . '';
+ $field->validators[] = new NumberRange();
+ $field->validators[] = new CharacterLength(1, 5);
+ $this->assignValueIsIntValidator($field);
});
}
@@ -260,9 +266,9 @@ private function createQueueEnabledSetting()
$self = $this;
return $this->makeSetting('queueEnabled', $default = false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) use ($self) {
- $field->title = 'Queue enabled';
+ $field->title = Piwik::translate('QueuedTracking_QueueEnabledFieldTitle');
$field->uiControl = FieldConfig::UI_CONTROL_CHECKBOX;
- $field->inlineHelp = 'If enabled, all tracking requests will be written into a queue instead of the directly into the database. Requires a Redis server and phpredis PHP extension if using Redis as a backend.';
+ $field->inlineHelp = Piwik::translate('QueuedTracking_QueueEnabledFieldHelp') . '';
$field->validate = function ($value) use ($self) {
$value = (bool) $value;
@@ -285,40 +291,26 @@ private function createQueueEnabledSetting()
private function createNumRequestsToProcessSetting()
{
return $this->makeSetting('numRequestsToProcess', $default = 25, FieldConfig::TYPE_INT, function (FieldConfig $field) {
- $field->title = 'Number of requests that are processed in one batch';
+ $field->title = Piwik::translate('QueuedTracking_NumRequestsToProcessFieldTitle');
$field->uiControl = FieldConfig::UI_CONTROL_TEXT;
$field->uiControlAttributes = array('size' => 3);
- $field->inlineHelp = 'Defines how many requests will be picked out of the queue and processed at once. Enter a number which is >= 1.';
- $field->validate = function ($value, $setting) {
-
- if (!is_numeric($value)) {
- throw new \Exception('Value should be a number');
- }
-
- if ((int) $value < 1) {
- throw new \Exception('Number should be 1 or higher');
- }
- };
+ $field->inlineHelp = Piwik::translate('QueuedTracking_NumRequestsToProcessFieldHelp') . '';
+ $field->validators[] = new NumberRange(1);
});
}
private function createProcessInTrackingRequestSetting()
{
return $this->makeSetting('processDuringTrackingRequest', $default = true, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
- $field->title = 'Process during tracking request';
+ $field->title = Piwik::translate('QueuedTracking_ProcessDuringRequestFieldTitle');
$field->uiControl = FieldConfig::UI_CONTROL_CHECKBOX;
- $field->inlineHelp = 'If enabled, we will process all requests within a queue during a normal tracking request once there are enough requests in the queue. This will not slow down the tracking request. If disabled, you have to setup a cronjob that executes the "./console queuedtracking:process" console command eg every minute to process the queue.';
+ $field->inlineHelp = Piwik::translate('QueuedTracking_ProcessDuringRequestFieldHelp', ['', '
']) . '';
});
}
- public function getInlineHelpSentinelMultipleServers($nameOfSetting)
- {
- return 'As you are using Redis Sentinel, you can define multiple ' . $nameOfSetting . ' comma separated. Make sure to specify as many hosts as you have specified ports. For example to configure two servers "127.0.0.1:26379" and "127.0.0.2:26879" specify "127.0.0.1,127.0.0.2" as host and "26379,26879" as ports.';
- }
-
public function checkMultipleServersOnlyConfiguredWhenSentinelIsEnabled($value)
{
- if ($this->isUsingSentinelBackend()) {
+ if ($this->isUsingSentinelBackend() || $this->isUsingClusterBackend()) {
return;
}
@@ -354,37 +346,33 @@ public function isMysqlBackend()
private function createBackendSetting()
{
return $this->makeSetting('backend', $default = 'redis', FieldConfig::TYPE_STRING, function (FieldConfig $field) {
- $field->title = 'Backend';
+ $field->title = Piwik::translate('QueuedTracking_BackendSettingFieldTitle');
$field->uiControl = FieldConfig::UI_CONTROL_SINGLE_SELECT;
$field->availableValues = array('redis' => 'Redis', 'mysql' => 'MySQL');
- $field->inlineHelp = 'Select the backend you want to use for this feature. If you do not have any experience with Redis or it is not available on your server, we recommend to use Mysql.';
+ $field->inlineHelp = Piwik::translate('QueuedTracking_BackendSettingFieldHelp') . '';
});
}
- private function createUseSentinelBackend()
+ private function createUseWhatRedisBackendType()
{
- return $this->makeSetting('useSentinelBackend', $default = false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
- $field->title = 'Enable Redis Sentinel';
- $field->uiControl = FieldConfig::UI_CONTROL_CHECKBOX;
- $field->uiControlAttributes = array('size' => 3);
+ return $this->makeSetting('useWhatRedisBackendType', $default = 1, FieldConfig::TYPE_INT, function (FieldConfig $field) {
+ $field->title = 'Redis type';
+ $field->uiControl = FieldConfig::UI_CONTROL_RADIO;
+ $field->availableValues = $this->getAvailableRedisBackendTypes();
$field->condition = 'backend=="redis"';
- $field->inlineHelp = 'If enabled, the Redis Sentinel feature will be used. Make sure to update host and port if needed. Once you have enabled and saved the change, you will be able to specify multiple hosts and ports comma separated.';
+ $field->inlineHelp = Piwik::translate('QueuedTracking_WhatRedisBackEndType') . '';
});
}
private function createSetSentinelMasterName()
{
return $this->makeSetting('sentinelMasterName', $default = 'mymaster', FieldConfig::TYPE_STRING, function (FieldConfig $field) {
- $field->title = 'Redis Sentinel Master name';
+ $field->title = Piwik::translate('QueuedTracking_MasterNameFieldTitle');
$field->condition = 'backend=="redis"';
$field->uiControl = FieldConfig::UI_CONTROL_TEXT;
$field->uiControlAttributes = array('size' => 200);
- $field->inlineHelp = 'The sentinel master name only needs to be configured if Sentinel is enabled.';
- $field->validate = function ($value) {
- if (!empty($value) && strlen($value) > 200) {
- throw new \Exception('Max 200 characters are allowed');
- }
- };
+ $field->inlineHelp = Piwik::translate('QueuedTracking_MasterNameFieldHelp') . '';
+ $field->validators[] = new CharacterLength(0, 200);
$field->transform = function ($value) {
if (empty($value)) {
return '';
@@ -394,6 +382,16 @@ private function createSetSentinelMasterName()
});
}
+ private function createUsePasswordForSentinelInstances()
+ {
+ return $this->makeSetting('usePasswordForSentinelInstances', $default = false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
+ $field->title = Piwik::translate('QueuedTracking_UsePasswordForSentinelsTitle');
+ $field->condition = 'backend=="redis"';
+ $field->uiControl = FieldConfig::UI_CONTROL_CHECKBOX;
+ $field->inlineHelp = Piwik::translate('QueuedTracking_UsePasswordForSentinelsHelp', ['']) . '';
+ });
+ }
+
public function checkMatchHostsAndPorts()
{
$hosts = $this->redisHost->getValue();
@@ -425,5 +423,4 @@ public function save()
}
}
}
-
}
diff --git a/Tasks.php b/Tasks.php
index 7c19432..a1438bd 100644
--- a/Tasks.php
+++ b/Tasks.php
@@ -1,4 +1,5 @@
isMysqlBackend() && $settings->queueEnabled->getValue()) {
-
$db = Db::get();
$prefix = Common::prefixTable(MySQL::QUEUED_TRACKING_TABLE_PREFIX);
$tables = $db->fetchCol("SHOW TABLES LIKE '" . $prefix . "%'");
@@ -104,5 +105,4 @@ public function optimizeQueueTable()
Db::optimizeTables($tables, $force);
}
}
-
-}
\ No newline at end of file
+}
diff --git a/Tracker/Handler.php b/Tracker/Handler.php
index 3b695e5..f90881d 100644
--- a/Tracker/Handler.php
+++ b/Tracker/Handler.php
@@ -1,4 +1,5 @@
1) {
@@ -26,5 +27,4 @@ public function sendResponseToBrowserDirectly()
ob_end_flush();
flush();
}
-
}
diff --git a/Updates/3.2.0.php b/Updates/3.2.0.php
index b3c2e9e..721ac9b 100644
--- a/Updates/3.2.0.php
+++ b/Updates/3.2.0.php
@@ -1,4 +1,5 @@
getValue() == 0) {
+ $tmp_useWhatRedisBackendType->setValue($old_useSentinelBackend->getValue() == true ? 2 : 1);
+ $tmp_useWhatRedisBackendType->save();
+ }
+ }
+}
diff --git a/docs/faq.md b/docs/faq.md
index 2b657cf..cae107e 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -12,26 +12,27 @@ for Matomo anyway.
__Where can I configure and enable the queue?__
-In your Piwik instance go to "Administration => General Settings". There is a config section for this plugin.
+In your Matomo instance go to "Administration => General Settings". There is a config section for this plugin.
__When will a queued tracking request be processed?__
First you should know that multiple tracking requests will be inserted into the database at once using
-[bulk tracking](http://developer.piwik.org/api-reference/tracking-api#bulk-tracking) as soon as a configurable number
+[bulk tracking](http://developer.matomo.org/api-reference/tracking-api#bulk-tracking) as soon as a configurable number
of requests is queued. By default we will check whether enough requests are queued during a regular tracking request
and start processing them right after sending a response to the browser to make sure a user won't have to wait until
the queue has finished to process all requests. Have a look at this graph to see how it works:
-
+
__I do not want to process queued requests within a tracking request, what shall I do?__
Don't worry, if this solution doesn't work out for you for some reason you can disable it and process all queued
-requests using the [Piwik console](http://developer.piwik.org/guides/piwik-on-the-command-line). Just follow these steps:
+requests using the [Matomo console](http://developer.matomo.org/guides/piwik-on-the-command-line). Just follow these steps:
-* Disable the setting "Process during tracking request" in the Piwik UI under "Settings => Plugin Settings"
+* Disable the setting "Process during tracking request" in the Matomo UI under "Settings => Plugin Settings"
* Setup a cronjob that executes the command `./console queuedtracking:process` for instance every minute
* That's it
+* Or, if you have __"non WINDOWS OS"__ you can use the [Supervisor](http://supervisord.org/) as a cron alternative.
The `queuedtracking:process` command will make sure to process all queued tracking requests whenever possible and the
command will exit as soon as there are not enough requests queued anymore. That's why you should setup a cronjob to start
@@ -41,7 +42,29 @@ queued requests at a time.
Example crontab entry that starts the processor every minute:
-`* * * * * cd /piwik && ./console queuedtracking:process >/dev/null 2>&1`
+`* * * * * cd /matomo && ./console queuedtracking:process >/dev/null 2>&1`
+
+Example Supervisor entry that will start 16 processors/workers with 10 loop cycle times and auto restart:
+
+```ini
+[program:matomo]
+directory=/path/to/your/matomo
+command=/path/to/your/php /path/to/your/matomo/console queuedtracking:process --queue-id=%(process_num)s -c 10 -s 2 -d 5
+process_name=queuedtracking-%(process_num)s
+
+#change the number according to how many worker(s) you have
+numprocs=16
+
+numprocs_start=0
+stopsignal=TERM
+autostart=true
+autorestart=true
+stopwaitsecs=120
+#priority=1000
+stdout_logfile=/dev/null
+stdout_logfile_maxbytes=0
+redirect_stderr=true
+```
__Can I keep track of the state of the queue?__
@@ -49,7 +72,7 @@ Yes, you can. Just execute the command `./console queuedtracking:monitor`. This
__Can I improve the speed of inserting requests from the Redis queue to the database?__
-Yes, you can by adding more workers. By default only one worker is activated at a time and only one worker processes tracking requests from Redis to the database. When inserting tracking requests into the database, at time of writing this, about 80% of the time is spent in PHP and the database might be rather bored. If you have multiple CPUs available on your server you can add more workers. You can do this by going in the Piwik Admin interface to "Plugin Settings". There will be a setting "Number of queue workers". Increase this number to the number of CPUs you want to dedeciate for processing requests. Best practice is to add more workers step by step. So first increase this number to 2 and check if the tracking request insertions is fast enough for you. If not and you have more CPUs available, increase the number again.
+Yes, you can by adding more workers. By default only one worker is activated at a time and only one worker processes tracking requests from Redis to the database. When inserting tracking requests into the database, at time of writing this, about 80% of the time is spent in PHP and the database might be rather bored. If you have multiple CPUs available on your server you can add more workers. You can do this by going in the Matomo Admin interface to "Plugin Settings". There will be a setting "Number of queue workers". Increase this number to the number of CPUs you want to dedeciate for processing requests. Best practice is to add more workers step by step. So first increase this number to 2 and check if the tracking request insertions is fast enough for you. If not and you have more CPUs available, increase the number again.
When using multiple workers it might be worth to lower the number of "Number of requests to process" to eg 15 in "Plugin Settings". By default 25 requests are inserted in one step by using transactions. This means different workers might have to wait for each other. By lowering that number each worker will block the DB for less time.
@@ -67,7 +90,9 @@ There should be only one Redis server to make sure the data will be replayed in
If you want to configure Redis HA (High Availability) it is possible to use Redis Sentinel see further down.
We currently write into the Redis default database by default but you can configure to use a different one.
-__Why do some tests fail on my local Piwik instance?__
+You can also use a "Redis Cluster" to distribute all tracking requests data across multiple Redis masters/shards, complete with the HA feature.
+
+__Why do some tests fail on my local Matomo instance?__
Make sure the requirements mentioned above are met and Redis needs to run on 127.0.0.1:6379 with no password for the
integration tests to work. It will use the database "15" and the tests may flush all data it contains. Make sure
diff --git a/lang/ca.json b/lang/ca.json
index 02c9ad2..2018800 100644
--- a/lang/ca.json
+++ b/lang/ca.json
@@ -1,6 +1,40 @@
{
"QueuedTracking": {
+ "AvailableRedisBackendTypeCluster": "Clúster",
+ "AvailableRedisBackendTypeSentinel": "Sentinella",
+ "AvailableRedisBackendTypeStandAlone": "Autònom",
+ "BackendSettingFieldHelp": "Seleccioneu el backend que voleu utilitzar per a aquesta funció. Si no teniu cap experiència amb Redis o no està disponible al vostre servidor, us recomanem que utilitzeu Mysql.",
+ "BackendSettingFieldTitle": "Backend",
+ "ExceptionValueIsNotInt": "El valor no és un nombre enter",
+ "MasterNameFieldHelp": "El nom del Sentinel Master només s'ha de configurar si Sentinel està habilitat.",
+ "MasterNameFieldTitle": "Nom de Redis Sentinel Master",
"MultipleServersOnlyConfigurableIfSentinelEnabled": "Només es poden configurar múltiples hostes o ports quan Redis Sentinel està activat. El connector README us indicarà com fer-ho.",
- "NumHostsNotMatchNumPorts": "El nombre d'hostes configurats no coincideix amb el nombre de ports configurats."
+ "NumHostsNotMatchNumPorts": "El nombre d'hostes configurats no coincideix amb el nombre de ports configurats.",
+ "NumRequestsToProcessFieldHelp": "Defineix quantes sol·licituds es recolliran de la cua i es processaran alhora. Introduïu un número que sigui >= 1.",
+ "NumRequestsToProcessFieldTitle": "Nombre de sol·licituds que es processen en un lot",
+ "NumberOfQueueWorkersFieldHelp": "Nombre màxim de treballadors de cua permesos. Accepta un número entre 1 i 16. La millor pràctica és establir el nombre de CPU que voleu que estiguin disponibles per al processament de la cua. Tingueu en compte que heu d'assegurar-vos d'iniciar els treballadors manualment. Us recomanem que no utilitzeu entre 9 i 15 treballadors, sinó que en utilitzeu 8 o 16, ja que és possible que la cua no es distribueixi uniformement en diferents cues.",
+ "NumberOfQueueWorkersFieldHelpNew": "Nombre màxim de treballadors de cua permesos. Accepta un nombre entre 1 i 4096. La millor pràctica és establir el nombre de CPU que voleu que estiguin disponibles per al processament de la cua. Tingueu en compte que heu d'assegurar-vos d'iniciar els treballadors manualment. Us recomanem que no utilitzeu entre 9 i 15 treballadors, sinó que en feu servir 8 o 16, ja que és possible que la cua no es distribueixi uniformement en diferents cues.",
+ "NumberOfQueueWorkersFieldTitle": "Nombre de treballadors de la cua",
+ "ProcessDuringRequestFieldHelp": "Si està activat, processarem totes les sol·licituds d'una cua durant una sol·licitud de seguiment normal quan hi hagi prou sol·licituds a la cua. Això no retardarà la sol·licitud de seguiment. Si està desactivat, heu de configurar un cronjob que executi l'ordre de la consola %1$s./console queuedtracking:process%2$s, per exemple, cada minut per processar la cua.",
+ "ProcessDuringRequestFieldTitle": "Procés durant la sol·licitud de seguiment",
+ "QueueEnabledFieldHelp": "Si està activat, totes les sol·licituds de seguiment s'escriuran en una cua en comptes de directament a la base de dades. Requereix un servidor Redis i una extensió PHP phpredis si s'utilitza Redis com a backend.",
+ "QueueEnabledFieldTitle": "S'ha activat la cua",
+ "RedisDatabaseFieldHelp": "En cas que utilitzeu Redis per a la memòria cau, assegureu-vos d'utilitzar una base de dades diferent.",
+ "RedisDatabaseFieldTitle": "Base de dades Redis",
+ "RedisHostFieldHelp": "Amfitrió remot o sòcol Unix del servidor Redis. Es permeten un màxim de 500 caràcters.",
+ "RedisHostFieldHelpExtended": "Si el vostre amfitrió requereix una connexió TLS, podeu anteposar el protocol TLS al vostre amfitrió com: tls://example-host.com. Si això no funciona, assegureu-vos que els certificats estiguin configurats correctament al vostre servidor Matomo.",
+ "RedisHostFieldHelpExtendedSentinel": "Quan utilitzeu Redis Sentinel, podeu utilitzar una llista separada per comes. Assegureu-vos d'especificar tants hosts com ports heu especificat. Per exemple, per configurar dos servidors \"127.0.0.1:26379\" i \"127.0.0.2:26879\" especifiqueu \"127.0.0.1,127.0.0.2\" com a host i \"26379,26879\" com a ports.",
+ "RedisHostFieldTitle": "Amfitrió Redis o sòcol Unix",
+ "RedisPasswordFieldHelp": "Contrasenya establerta al servidor Redis, si n'hi ha. Es pot indicar a Redis que requereixi una contrasenya abans de permetre que els clients executin ordres.",
+ "RedisPasswordFieldTitle": "Contrasenya de Redis",
+ "RedisPortFieldHelp": "Port on el servidor Redis s'està executant. El valor ha d'estar entre 1 i 65535. Utilitzeu 0 si utilitzeu un sòcol Unix per connectar-vos al servidor Redis.",
+ "RedisPortFieldTitle": "Port de Redis",
+ "RedisTimeoutFieldHelp": "Temps d'espera de connexió Redis en segons. \"0.0\" significa il·limitat. Pot ser un flotant, per exemple, \"2,5\" per a un temps d'espera de connexió de 2,5 segons.",
+ "RedisTimeoutFieldTitle": "Temps d'espera de Redis",
+ "UsePasswordForSentinelsHelp": "Només és rellevant si Sentinel està habilitat.%1$sSi està habilitat, la contrasenya de Redis també s'utilitzarà en autenticar-se amb instàncies de Sentinel per obtenir la informació de connexió mestra. En cas contrari, la contrasenya només s'utilitza per autenticar-se amb el mestre de Redis.",
+ "UsePasswordForSentinelsTitle": "Utilitza la contrasenya amb Redis Sentinels",
+ "UseSentinelFieldHelp": "Si està activada, s'utilitzarà la funció Redis Sentinel. Assegureu-vos d'actualitzar l'amfitrió i el port si cal. Un cop hàgiu habilitat i desat el canvi, podreu especificar diversos hosts i ports separats per comes.",
+ "UseSentinelFieldTitle": "Activa Redis Sentinel",
+ "WhatRedisBackEndType": "Seleccioneu quin tipus de redis voleu utilitzar. Assegureu-vos d'actualitzar l'amfitrió i el port si cal. Un cop hàgiu seleccionat i desat el canvi, podreu especificar diversos hosts i ports utilitzant llistes separades per comes només per al tipus \"Sentinel\" i \"Cluster\"."
}
}
diff --git a/lang/cs.json b/lang/cs.json
index 765e69b..bebb7c0 100644
--- a/lang/cs.json
+++ b/lang/cs.json
@@ -1,6 +1,7 @@
{
"QueuedTracking": {
- "NumHostsNotMatchNumPorts": "Počet nakonfigurovaných hostů neodpovídá počtu nakonfigurovaných portů.",
- "MultipleServersOnlyConfigurableIfSentinelEnabled": "Více hostů či portů lze nakonfigurovat pouze při povolení modulu Redis Sentinel. Více informací, jak Sentinel povolit, najdete v souboru readme tohoto modulu."
+ "ExceptionValueIsNotInt": "Hodnota není celé číslo",
+ "MultipleServersOnlyConfigurableIfSentinelEnabled": "Více hostů či portů lze nakonfigurovat pouze při povolení modulu Redis Sentinel. Více informací, jak Sentinel povolit, najdete v souboru readme tohoto modulu.",
+ "NumHostsNotMatchNumPorts": "Počet nakonfigurovaných hostů neodpovídá počtu nakonfigurovaných portů."
}
-}
\ No newline at end of file
+}
diff --git a/lang/de.json b/lang/de.json
index 922a9e4..d0f9d4d 100644
--- a/lang/de.json
+++ b/lang/de.json
@@ -1,6 +1,37 @@
{
"QueuedTracking": {
+ "AvailableRedisBackendTypeCluster": "Cluster",
+ "AvailableRedisBackendTypeSentinel": "Sentinel",
+ "AvailableRedisBackendTypeStandAlone": "Eigenständig",
+ "BackendSettingFieldHelp": "Wählen Sie das Backend aus, das Sie für dieses Feature verwenden möchten. Wenn Sie keine Erfahrung mit Redis haben oder es auf Ihrem Server nicht verfügbar ist, empfehlen wir die Verwendung von Mysql.",
+ "BackendSettingFieldTitle": "Backend",
+ "ExceptionValueIsNotInt": "Der Wert ist keine Ganzzahl",
+ "MasterNameFieldHelp": "Der Name des Sentinel-Masters muss nur konfiguriert werden, wenn Sentinel aktiviert ist.",
+ "MasterNameFieldTitle": "Name des Redis Sentinel Masters",
"MultipleServersOnlyConfigurableIfSentinelEnabled": "Mehrere Hosts oder Ports können erst konfiguriert werden, wenn Redis Sentinel aktiviert wurde. In der README des Plugins erfahren Sie, wie Sie dies tun können.",
- "NumHostsNotMatchNumPorts": "Die Anzahl der konfigurierten Hosts stimmt nicht mit der Anzahl der konfigurierten Ports überein."
+ "NumHostsNotMatchNumPorts": "Die Anzahl der konfigurierten Hosts stimmt nicht mit der Anzahl der konfigurierten Ports überein.",
+ "NumRequestsToProcessFieldHelp": "Definiert, wie viele Anfragen gleichzeitig aus der Warteschlange ausgewählt und bearbeitet werden. Geben Sie eine Zahl ein, die >= 1 ist.",
+ "NumRequestsToProcessFieldTitle": "Anzahl der Anfragen, die in einer Charge verarbeitet werden",
+ "NumberOfQueueWorkersFieldHelp": "Anzahl der maximal zulässigen Warteschlangenarbeiter. Akzeptiert eine Zahl zwischen 1 und 16. Die beste Vorgehensweise besteht darin, die Anzahl der CPUs festzulegen, die Sie für die Warteschlangenverarbeitung zur Verfügung stellen möchten. Beachten Sie, dass Sie sicherstellen müssen, die Arbeiter manuell zu starten. Wir empfehlen, nicht 9-15 Arbeiter zu verwenden, sondern eher 8 oder 16, da die Warteschlange möglicherweise nicht gleichmäßig auf verschiedene Warteschlangen verteilt wird.",
+ "NumberOfQueueWorkersFieldHelpNew": "Anzahl der maximal zulässigen Warteschlangenarbeiter. Akzeptiert eine Zahl zwischen 1 und 4096. Die beste Vorgehensweise besteht darin, die Anzahl der CPUs festzulegen, die Sie für die Warteschlangenverarbeitung zur Verfügung stellen möchten. Beachten Sie, dass Sie sicherstellen müssen, die Arbeiter manuell zu starten. Wir empfehlen, nicht 9-15 Arbeiter zu verwenden, sondern eher 8 oder 16, da die Warteschlange möglicherweise nicht gleichmäßig auf verschiedene Warteschlangen verteilt wird.",
+ "NumberOfQueueWorkersFieldTitle": "Anzahl der Warteschlangenarbeiter",
+ "ProcessDuringRequestFieldHelp": "Wenn aktiviert, werden wir alle Anfragen innerhalb einer Warteschlange während einer normalen Aufzeichnungsanfrage verarbeiten, sobald genügend Anfragen in der Warteschlange sind. Dies wird die Aufzeichnungsanfrage nicht verlangsamen. Wenn deaktiviert, müssen Sie einen Cronjob einrichten, der den %1$s./console queuedtracking:process%2$s Konsolenbefehl z.B. jede Minute ausführt, um die Warteschlange zu verarbeiten.",
+ "QueueEnabledFieldHelp": "Wenn aktiviert, werden alle Aufzeichnungsanfragen in eine Warteschlange geschrieben, anstatt direkt in die Datenbank. Erfordert einen Redis-Server und die phpredis PHP-Erweiterung, wenn Redis als Backend verwendet wird.",
+ "QueueEnabledFieldTitle": "Warteschlange aktiviert",
+ "RedisDatabaseFieldHelp": "Falls Sie Redis für das Caching verwenden, stellen Sie sicher, dass Sie eine andere Datenbank verwenden.",
+ "RedisDatabaseFieldTitle": "Redis Datenbank",
+ "RedisHostFieldHelp": "Remote-Host oder Unix-Socket des Redis-Servers. Maximal 500 Zeichen sind erlaubt.",
+ "RedisHostFieldHelpExtended": "Wenn Ihr Host eine TLS-Verbindung erfordert, können Sie das TLS-Protokoll Ihrem Host voranstellen, wie folgt: tls://beispiel-host.com. Wenn das nicht funktioniert, stellen Sie sicher, dass die Zertifikate auf Ihrem Matomo-Server korrekt konfiguriert sind.",
+ "RedisHostFieldHelpExtendedSentinel": "Da Sie Redis Sentinel verwenden, können Sie eine durch Kommas getrennte Liste verwenden. Stellen Sie sicher, dass Sie so viele Hosts angeben, wie Sie Ports angegeben haben. Um zum Beispiel zwei Server zu konfigurieren \"127.0.0.1:26379\" und \"127.0.0.2:26879\", geben Sie \"127.0.0.1,127.0.0.2\" als Host und \"26379,26879\" als Ports an.",
+ "RedisHostFieldTitle": "Redis Host oder Unix-Socket",
+ "RedisPasswordFieldHelp": "Passwort des Redis-Servers, falls vorhanden. Redis kann angewiesen werden, ein Passwort zu verlangen, bevor Clients Befehle ausführen dürfen.",
+ "RedisPasswordFieldTitle": "Redis Passwort",
+ "RedisPortFieldHelp": "Der Port, auf dem der Redis-Server läuft. Der Wert sollte zwischen 1 und 65535 liegen. Verwenden Sie 0, wenn Sie eine Unix-Socket-Verbindung zum Redis-Server verwenden.",
+ "RedisPortFieldTitle": "Redis-Port",
+ "RedisTimeoutFieldHelp": "Redis Verbindungs-Zeitlimit in Sekunden. \"0.0\" bedeutet unbegrenzt. Kann eine Fließkommazahl sein, z.B. \"2.5\" für ein Verbindungs-Zeitlimit von 2,5 Sekunden.",
+ "RedisTimeoutFieldTitle": "Redis Zeitlimit",
+ "UseSentinelFieldHelp": "Wenn aktiviert, wird das Redis Sentinel Feature verwendet. Stellen Sie sicher, dass Sie Host und Port bei Bedarf aktualisieren. Sobald Sie die Veränderung aktiviert und gespeichert haben, können Sie mehrere Hosts und Ports durch Kommas getrennt angeben.",
+ "UseSentinelFieldTitle": "Redis Sentinel aktivieren",
+ "WhatRedisBackEndType": "Wählen Sie aus, welchen Typ von Redis Sie verwenden möchten. Stellen Sie sicher, dass Sie Host und Port bei Bedarf aktualisieren. Sobald Sie die Veränderung ausgewählt und gespeichert haben, können Sie mehrere Hosts und Ports nur für den \"Sentinel\"- und \"Cluster\"-Typ mit kommagetrennten Listen angeben."
}
}
diff --git a/lang/el.json b/lang/el.json
index 2a10fb2..b77a94e 100644
--- a/lang/el.json
+++ b/lang/el.json
@@ -1,6 +1,40 @@
{
"QueuedTracking": {
+ "AvailableRedisBackendTypeCluster": "Cluster",
+ "AvailableRedisBackendTypeSentinel": "Sentinel",
+ "AvailableRedisBackendTypeStandAlone": "Stand-alone",
+ "BackendSettingFieldHelp": "Επιλέξτε το πίσω μέρος που θέλετε να χρησιμοποιείτε για αυτό το χαρακτηριστικό. Αν δεν έχετε εμπειρία με το Redis ή αν δεν είναι διαθέσιμο στο διακομιστή σας, προτείνουμε τη χρήση της Mysql.",
+ "BackendSettingFieldTitle": "Πίσω μέρος (backend)",
+ "ExceptionValueIsNotInt": "Η τιμή δεν είναι ακέραιος",
+ "MasterNameFieldHelp": "Αν το Sentinel είναι ενεργό χρειάζεται να παραμετροποιηθεί μόνο το όνομα του κυρίου Sentinel.",
+ "MasterNameFieldTitle": "Όνομα Κύριου Redis Sentinel",
"MultipleServersOnlyConfigurableIfSentinelEnabled": "Πολλαπλοί διακομιστές ή θύρες μπορούν να παραμετροποιηθούν όταν το Redis Sentinel είναι ενεργοποιημένο. Δείτε στο αρχείο README του πρόσθετου για να μάθετε πώς να το κάνετε.",
- "NumHostsNotMatchNumPorts": "Ο αριθμός διακομιστών για τους οποίους έγινε ρύθμιση δεν συμφωνεί με τον αριθμό των θυρών που παραμετροποιήθηκαν."
+ "NumHostsNotMatchNumPorts": "Ο αριθμός διακομιστών για τους οποίους έγινε ρύθμιση δεν συμφωνεί με τον αριθμό των θυρών που παραμετροποιήθηκαν.",
+ "NumRequestsToProcessFieldHelp": "Καθορίζει πόσες αιτήσεις θα επιλέγονται από την ουρά και θα επεξεργάζονται σε κάθε παρτίδα. Εισάγετε ένα αριθμό >=1.",
+ "NumRequestsToProcessFieldTitle": "Αριθμός αιτήσεων που θα επεξεργάζονται σε μια παρτίδα",
+ "NumberOfQueueWorkersFieldHelp": "Μέγιστος αριθμός επιτρεπόμενων εργατών ουράς. Δέχεται αριθμό μεταξύ 1 και 16. Καλύτερη πρακτική θεωρείται να βάλετε τον αριθμό των επεξεργαστών που θέλετε να έχετε διαθέσιμους για επεξεργασία ουράς. Βεβαιωθείτε ότι πρέπει να ξεκινάτε τους εργάτες χειροκίνητα. Προτείνουμε να μην χρησιμοποιείτε εργάτες μεταξύ 9 και 15, αντίθετα χρησιμοποιήστε 8 ή 16 καθώς η ουρά ενδέχεται να μην μοιράζεται ισόποσα σε διαφορετικές ουρές.",
+ "NumberOfQueueWorkersFieldHelpNew": "Ο αριθμός των μέγιστων επιτρεπόμενων εργατών ουράς. Δέχεται ένα αριθμό μεταξύ 1 και 4096. Η βέλτιστη πρακτική είναι ο ορισμός του αριθμού των επεξεργαστών που θέλετε να κάνετε διαθέσιμους για την επεξεργασία ουράς. Έχετε το νου σας ότι οι εργάτες θα πρέπει να ξεκινούν χειροκίνητα. Δεν προτείνουμε τη χρήση εργατών μεταξύ 9-15, αλλά καλύτερα να χρησιμοποιήσετε μεταξύ 8 και 16, καθώς η ουρά δύναται να μην μοιράζεται ισόποσα σε διαφορετικές ουρές.",
+ "NumberOfQueueWorkersFieldTitle": "Αριθμός εργατών ουράς",
+ "ProcessDuringRequestFieldHelp": "Αν είναι ενεργό, θα γίνεται επεξεργασία των αιτήσεων μέσα σε μια ουρά στη διάρκεια μιας κανονικής αίτησης ιχνηλάτησης από τη στιγμή που θα υπάρχουν αιτήσεις στην ουρά. Αυτό δε θα καθυστερήσει την αίτηση ιχνηλάτησης. Αν είναι ανενεργό, πρέπει να ορίσετε μια εργασία cronjob που θα εκτελεί την εντολή κονσόλας %1$s./console queuedtracking:process%2$s κάθε λεπτό για να γίνεται επεξεργασία της ουράς.",
+ "ProcessDuringRequestFieldTitle": "Επεξεργασία στην περίοδο αίτησης ιχνηλάτησης",
+ "QueueEnabledFieldHelp": "Αν είναι ενεργό, όλες οι αιτήσεις ιχνηλάτησης θα γράφονται σε ουρά αντί για κατευθείαν στη βάση δεδομένων. Αυτό απαιτεί ένα διακομιστή Redis με την επέκταση phpredis αν θα χρησιμοποιείται το Redis ως πίσω μέρος.",
+ "QueueEnabledFieldTitle": "Η ουρά ενεργοποιήθηκε",
+ "RedisDatabaseFieldHelp": "Στην περίπτωση που χρησιμοποιείτε Redis για προσωρινή μνήμη βεβαιωθείτε να χρησιμοποιήστε διαφορετική βάση δεδομένων.",
+ "RedisDatabaseFieldTitle": "Βάση δεδομένων Redis",
+ "RedisHostFieldHelp": "Απομακρυσμένος διακομιστής ή unix socket του διακομιστή Redis. Επιτρέπονται μέγιστο 500 χαρακτήρες.",
+ "RedisHostFieldHelpExtended": "Αν ο διακομιστής σας απαιτεί σύνδεση TLS, μπορείτε να βάλετε από μπροστά το TLS πρωτόκολλο στο διακομιστή σας όπως στο tls://example-host.com. Αν αυτό δε δουλέψει, βεβαιωθείτε ότι τα πιστοποιητικά έχουν εγκατασταθεί σωστά στον διακομιστή σας του Matomo.",
+ "RedisHostFieldHelpExtendedSentinel": "Αν χρησιμοποιείτε το Redis Sentinel, μπορείτε να χρησιμοποιήσετε μια λίστα χωρισμένη με κόμμα. Βεβαιωθείτε να ορίσετε τόσους διακομιστές όσους έχετε και στις αντίστοιχες θύρες. Για παράδειγμα, για να παραμετροποιήσετε δύο διακομιστές “127.0.0.1:26379” και “127.0.0.2:26879” καθορίστε το “127.0.0.1,127.0.0.2” ως διακομιστή και το “26379,26879” ως θύρες.",
+ "RedisHostFieldTitle": "Διακομιστής Redis ή unix socket",
+ "RedisPasswordFieldHelp": "Ορισμός συνθηματικού στο διακομιστή Redis, αν υπάρχει. Το Redis μπορεί να παραμετροποιηθεί να απαιτεί συνθηματικό προτού επιτρέψει τους πελάτες να εκτελούν εντολές.",
+ "RedisPasswordFieldTitle": "Συνθηματικό Redis",
+ "RedisPortFieldHelp": "Η θύρα στην οποία εκτελείται ο διακομιστής Redis. Η τιμή θα πρέπει να είναι μεταξύ του 1 και του 65535. Χρησιμοποιήστε το 0 αν χρησιμοποιείτε unix soxket για να συνδεθείτε στο διακομιστή Redis.",
+ "RedisPortFieldTitle": "Θύρα Redis",
+ "RedisTimeoutFieldHelp": "Ο χρόνος λήξης απόκρισης του Redis σε δευτερόλεπτα. Το \"0.0\" σημαίνει χωρίς όριο. Μπορεί να είναι δεκαδικός αριθμός, πχ \"2.5\" για χρόνο λήξης απόκρισης 2.5 δευτερόλεπτα.",
+ "RedisTimeoutFieldTitle": "Χρόνος λήξης απόκρισης του Redis",
+ "UsePasswordForSentinelsHelp": "Σχετικό μόνο αν το Sentinel είναι ενεργό. %1$sΑν είναι ενεργό, το συνθηματικό του Redis θα χρησιμοποιείται επίσης κατά την αυθεντικοποίηση με τα στιγμιότυπα του Sentinel για να γίνει λήψη των πληροφοριών κύριας σύνδεσης. Εναλλακτικά, το συνθηματικό χρησιμοποιείται μόνο κατά την αυθεντικοποίηση με τον κύριο Redis.",
+ "UsePasswordForSentinelsTitle": "Χρήση του συνθηματικού με το Redis Sentinels",
+ "UseSentinelFieldHelp": "Αν είναι ενεργό, θα χρησιμοποιηθεί το χαρακτηριστικό Redis Sentinel. Βεβαιωθείτε να ενημερώσετε το όνομα διακομιστή και τη θύρα αν απαιτηθεί. Από τη στιγμή που θα το ενεργοποιήσετε και αποθηκεύσετε την αλλαγή, θα μπορείτε να καθορίζετε πολλαπλούς διακομιστές και θύρες χωρισμένα με κόμμα.",
+ "UseSentinelFieldTitle": "Ενεργοποίηση του Redis Sentinel",
+ "WhatRedisBackEndType": "Επιλέξτε ποιο τύπο redis θα χρησιμοποιήσετε. Βεβαιωθείτε να ενημερώσετε το διακομιστή και θύρα αν χρειάζεται. Αφού έχετε κάνει και αποθηκεύσει την αλλαγή, θα μπορείτε να καθορίσετε πολλαπλούς διακομιστές και θύρες με λίστες και χρήση του κόμματος ως διαχωριστή μόνο για τους τύπους \"Sentinel\" και \"Cluster\"."
}
}
diff --git a/lang/en.json b/lang/en.json
index ff47cc1..1b2f7df 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -1,6 +1,40 @@
{
"QueuedTracking": {
+ "ExceptionValueIsNotInt": "The value is not an integer",
+ "RedisHostFieldTitle": "Redis host or unix socket",
+ "RedisHostFieldHelp": "Remote host or unix socket of the Redis server. Max 500 characters are allowed.",
+ "RedisHostFieldHelpExtended": "If your host requires a TLS connection, you can prepend the TLS protocol to your host like: tls://example-host.com. If that does not work, make sure that certificates are configured correctly on your Matomo server.",
+ "RedisHostFieldHelpExtendedSentinel": "As you are using Redis Sentinel, you can use a comma separated list. Make sure to specify as many hosts as you have specified ports. For example to configure two servers “127.0.0.1:26379” and “127.0.0.2:26879” specify “127.0.0.1,127.0.0.2” as host and “26379,26879” as ports.",
+ "RedisPortFieldTitle": "Redis port",
+ "RedisPortFieldHelp": "Port the Redis server is running on. Value should be between 1 and 65535. Use 0 if you are using unix socket to connect to Redis server.",
+ "RedisTimeoutFieldTitle": "Redis timeout",
+ "RedisTimeoutFieldHelp": "Redis connection timeout in seconds. “0.0” meaning unlimited. Can be a float eg “2.5” for a connection timeout of 2.5 seconds.",
+ "NumberOfQueueWorkersFieldTitle": "Number of queue workers",
+ "NumberOfQueueWorkersFieldHelp": "Number of allowed maximum queue workers. Accepts a number between 1 and 16. Best practice is to set the number of CPUs you want to make available for queue processing. Be aware you need to make sure to start the workers manually. We recommend to not use 9-15 workers, rather use 8 or 16 as the queue might not be distributed evenly into different queues.",
+ "NumberOfQueueWorkersFieldHelpNew": "Number of allowed maximum queue workers. Accepts a number between 1 and 4096. Best practice is to set the number of CPUs you want to make available for queue processing. Be aware you need to make sure to start the workers manually. We recommend to not use 9-15 workers, rather use 8 or 16 as the queue might not be distributed evenly into different queues.",
+ "WhatRedisBackEndType": "Select which type of redis to use. Make sure to update host and port if needed. Once you have selected and saved the change, you will be able to specify multiple hosts and ports using comma separated lists for \"Sentinel\" and \"Cluster\" type only.",
+ "AvailableRedisBackendTypeStandAlone": "Stand-alone",
+ "AvailableRedisBackendTypeSentinel": "Sentinel",
+ "AvailableRedisBackendTypeCluster": "Cluster",
+ "RedisPasswordFieldTitle": "Redis password",
+ "RedisPasswordFieldHelp": "Password set on the Redis server, if any. Redis can be instructed to require a password before allowing clients to execute commands.",
+ "RedisDatabaseFieldTitle": "Redis database",
+ "RedisDatabaseFieldHelp": "In case you are using Redis for caching make sure to use a different database.",
+ "QueueEnabledFieldTitle": "Queue enabled",
+ "QueueEnabledFieldHelp": "If enabled, all tracking requests will be written into a queue instead of the directly into the database. Requires a Redis server and phpredis PHP extension if using Redis as a backend.",
+ "NumRequestsToProcessFieldTitle": "Number of requests that are processed in one batch",
+ "NumRequestsToProcessFieldHelp": "Defines how many requests will be picked out of the queue and processed at once. Enter a number which is >= 1.",
+ "ProcessDuringRequestFieldTitle": "Process during tracking request",
+ "ProcessDuringRequestFieldHelp": "If enabled, we will process all requests within a queue during a normal tracking request once there are enough requests in the queue. This will not slow down the tracking request. If disabled, you have to setup a cronjob that executes the %1$s./console queuedtracking:process%2$s console command eg every minute to process the queue.",
+ "BackendSettingFieldTitle": "Backend",
+ "BackendSettingFieldHelp": "Select the backend you want to use for this feature. If you do not have any experience with Redis or it is not available on your server, we recommend using Mysql.",
+ "UseSentinelFieldTitle": "Enable Redis Sentinel",
+ "UseSentinelFieldHelp": "If enabled, the Redis Sentinel feature will be used. Make sure to update host and port if needed. Once you have enabled and saved the change, you will be able to specify multiple hosts and ports comma separated.",
+ "MasterNameFieldTitle": "Redis Sentinel Master name",
+ "MasterNameFieldHelp": "The sentinel master name only needs to be configured if Sentinel is enabled.",
"NumHostsNotMatchNumPorts": "The number of configured hosts doesn't match the number of configured ports.",
- "MultipleServersOnlyConfigurableIfSentinelEnabled": "Multiple hosts or ports can be only configured when Redis Sentinel is on. The plugin README will tell you how to do so."
+ "MultipleServersOnlyConfigurableIfSentinelEnabled": "Multiple hosts or ports can be only configured when Redis Sentinel is on. The plugin README will tell you how to do so.",
+ "UsePasswordForSentinelsTitle": "Use password with Redis Sentinels",
+ "UsePasswordForSentinelsHelp": "Only relevant if Sentinel is enabled.%1$sIf enabled, the Redis password will also be used when authenticating with Sentinel instances to obtain the master connection information. Otherwise, the password is only used to authenticate with the Redis master."
}
}
diff --git a/lang/fr.json b/lang/fr.json
index 5d7b78a..e54251c 100644
--- a/lang/fr.json
+++ b/lang/fr.json
@@ -1,6 +1,38 @@
{
"QueuedTracking": {
+ "AvailableRedisBackendTypeCluster": "Cluster",
+ "AvailableRedisBackendTypeSentinel": "Sentinel",
+ "AvailableRedisBackendTypeStandAlone": "Autonome",
+ "BackendSettingFieldHelp": "Sélectionnez le backend que vous souhaitez utiliser pour cette fonctionnalité. Si vous n’avez aucune expérience avec Redis ou si Redis n’est pas disponible sur votre serveur, nous vous recommandons d’utiliser Mysql.",
+ "BackendSettingFieldTitle": "Backend",
+ "ExceptionValueIsNotInt": "La valeur n'est pas un entier",
+ "MasterNameFieldHelp": "Le nom du maître Sentinel doit uniquement être configuré si Sentinel est activé.",
+ "MasterNameFieldTitle": "Nom du maître Redis Sentinel",
"MultipleServersOnlyConfigurableIfSentinelEnabled": "Plusieurs hôtes ou ports ne peuvent être configurés que lorsque Redis Sentinel est activé. Le plugin README vous dira comment faire.",
- "NumHostsNotMatchNumPorts": "Le nombre d'hôtes configurés est différent du nombre de ports configurés."
+ "NumHostsNotMatchNumPorts": "Le nombre d'hôtes configurés est différent du nombre de ports configurés.",
+ "NumRequestsToProcessFieldHelp": "Définit combien de requêtes seront extraites de la file d’attente et traitées en une seule fois. Saisissez un nombre supérieur ou égal à 1.",
+ "NumRequestsToProcessFieldTitle": "Nombre de requêtes traitées par lot",
+ "NumberOfQueueWorkersFieldHelp": "Nombre maximum de travailleurs de la file d’attente autorisés. Accepte une valeur comprise entre 1 et 16. La bonne pratique consiste à définir le nombre de CPU que vous souhaitez allouer au traitement de la file d’attente. Attention, vous devez démarrer manuellement les travailleurs. Nous recommandons de ne pas utiliser entre 9 et 15 travailleurs ; privilégiez plutôt 8 ou 16, car la répartition de la file d’attente pourrait ne pas être équilibrée entre les différentes files.",
+ "NumberOfQueueWorkersFieldHelpNew": "Nombre maximum de travailleurs de la file d’attente autorisés. Accepte une valeur comprise entre 1 et 4096. La bonne pratique consiste à définir le nombre de CPU que vous souhaitez allouer au traitement de la file d’attente. Attention, vous devez démarrer manuellement les travailleurs. Nous recommandons de ne pas utiliser entre 9 et 15 travailleurs ; privilégiez plutôt 8 ou 16, car la file d’attente pourrait ne pas être répartie de manière équilibrée entre les différentes files.",
+ "NumberOfQueueWorkersFieldTitle": "Nombre de travailleurs de la file d’attente",
+ "ProcessDuringRequestFieldHelp": "Si activé, toutes les requêtes de la file d’attente seront traitées pendant une requête de suivi normale, dès qu’il y aura suffisamment de requêtes dans la file. Cela ne ralentira pas la requête de suivi. Si désactivé, vous devrez configurer une tâche cron qui exécute la commande console %1$s./console queuedtracking:process%2$s, par exemple chaque minute, afin de traiter la file d’attente.",
+ "ProcessDuringRequestFieldTitle": "Traitement pendant la requête de suivi",
+ "QueueEnabledFieldHelp": "Si activé, toutes les requêtes de suivi seront enregistrées dans une file d’attente au lieu d’être directement écrites dans la base de données. Nécessite un serveur Redis et l’extension PHP phpredis si vous utilisez Redis comme backend.",
+ "QueueEnabledFieldTitle": "File d’attente activée",
+ "RedisDatabaseFieldHelp": "Si vous utilisez Redis pour la mise en cache, assurez-vous d’utiliser une base de données différente.",
+ "RedisDatabaseFieldTitle": "Base de données Redis",
+ "RedisHostFieldHelp": "Hôte distant ou socket unix du serveur Redis. Un maximum de 500 caractères est autorisé.",
+ "RedisHostFieldHelpExtended": "Si votre hébergeur nécessite une connexion TLS, vous pouvez ajouter le protocole TLS devant votre hôte, par exemple : tls://exemple-hote.com. Si cela ne fonctionne pas, assurez-vous que les certificats sont correctement configurés sur votre serveur Matomo.",
+ "RedisHostFieldHelpExtendedSentinel": "Puisque vous utilisez Redis Sentinel, vous pouvez utiliser une liste séparée par des virgules. Assurez-vous de spécifier autant d’hôtes que de ports. Par exemple, pour configurer deux serveurs \"127.0.0.1:26379\" et \"127.0.0.2:26879\", indiquez \"127.0.0.1,127.0.0.2\" comme hôtes et \"26379,26879\" comme ports.",
+ "RedisHostFieldTitle": "Hôte Redis ou socket unix",
+ "RedisPasswordFieldHelp": "Mot de passe défini sur le serveur Redis, le cas échéant. Redis peut être configuré pour exiger un mot de passe avant d’autoriser les clients à exécuter des commandes.",
+ "RedisPasswordFieldTitle": "Mot de passe Redis",
+ "RedisPortFieldHelp": "Port sur lequel le serveur Redis est en cours d’exécution. La valeur doit être comprise entre 1 et 65535. Utilisez 0 si vous utilisez un socket Unix pour vous connecter au serveur Redis.",
+ "RedisPortFieldTitle": "Port Redis",
+ "RedisTimeoutFieldHelp": "Délai d’expiration de la connexion Redis en secondes. \"0.0\" signifie illimité. Peut être un nombre à virgule flottante, par exemple \"2.5\" pour un délai de connexion de 2,5 secondes.",
+ "RedisTimeoutFieldTitle": "Timeout Redis",
+ "UseSentinelFieldHelp": "Si activé, la fonctionnalité Redis Sentinel sera utilisée. Assurez-vous de mettre à jour l’hôte et le port si nécessaire. Une fois l’option activée et la modification enregistrée, vous pourrez spécifier plusieurs hôtes et ports séparés par des virgules.",
+ "UseSentinelFieldTitle": "Activer Redis Sentinel",
+ "WhatRedisBackEndType": "Sélectionnez le type de Redis à utiliser. Assurez-vous de mettre à jour l’hôte et le port si nécessaire. Une fois la sélection effectuée et enregistrée, vous pourrez spécifier plusieurs hôtes et ports à l’aide de listes séparées par des virgules, uniquement pour les types \"Sentinel\" et \"Cluster\"."
}
}
diff --git a/lang/ga.json b/lang/ga.json
index 0967ef4..d59f0d5 100644
--- a/lang/ga.json
+++ b/lang/ga.json
@@ -1 +1,40 @@
-{}
+{
+ "QueuedTracking": {
+ "AvailableRedisBackendTypeCluster": "Braisle",
+ "AvailableRedisBackendTypeSentinel": "Fairtheoir",
+ "AvailableRedisBackendTypeStandAlone": "Neamhspleách",
+ "BackendSettingFieldHelp": "Roghnaigh an t-inneall is mian leat a úsáid don ghné seo. Mura bhfuil aon taithí agat le Redis nó mura bhfuil sé ar fáil ar do fhreastalaí, molaimid Mysql a úsáid.",
+ "BackendSettingFieldTitle": "Inneall",
+ "ExceptionValueIsNotInt": "Ní slánuimhir é an luach",
+ "MasterNameFieldHelp": "Ní gá an máistirainm fairtheora a chumrú ach amháin má tá Sentinel cumasaithe.",
+ "MasterNameFieldTitle": "Redis Sentinel ainm Máistir",
+ "MultipleServersOnlyConfigurableIfSentinelEnabled": "Ní féidir le hóstach iolrach nó poirt a chumrú ach amháin nuair atá Redis Sentinel ar siúl. Inseoidh an breiseán README duit conas é sin a dhéanamh.",
+ "NumHostsNotMatchNumPorts": "Ní hionann líon na n-óstach cumraithe agus líon na bport cumraithe.",
+ "NumRequestsToProcessFieldHelp": "Sainmhíníonn sé cé mhéad iarratas a phiocadh amach as an scuaine agus a phróiseáil ag an am céanna. Cuir isteach uimhir atá >= 1.",
+ "NumRequestsToProcessFieldTitle": "Líon na n-iarratas a phróiseáiltear in aon bhaisc amháin",
+ "NumberOfQueueWorkersFieldHelp": "Líon na n-oibrithe scuaine uasta a cheadaítear. Glacann sé le huimhir idir 1 agus 16. Is é an cleachtas is fearr ná líon na LAP a theastaíonn uait a chur ar fáil le haghaidh próiseála scuaine a shocrú. Bí ar an eolas go gcaithfidh tú a chinntiú na hoibrithe a thosú de láimh. Molaimid gan 9-15 oibrí a úsáid, ach 8 nó 16 a úsáid mar go mb’fhéidir nach mbeadh an scuaine roinnte go cothrom i scuainí éagsúla.",
+ "NumberOfQueueWorkersFieldHelpNew": "Líon na n-oibrithe scuaine uasta a cheadaítear. Glacann sé le huimhir idir 1 agus 4096. Is é an cleachtas is fearr ná líon na LAP a theastaíonn uait a chur ar fáil le haghaidh próiseála scuaine a shocrú. Bí ar an eolas go gcaithfidh tú a chinntiú na hoibrithe a thosú de láimh. Molaimid gan 9-15 oibrí a úsáid, ach 8 nó 16 a úsáid mar go mb’fhéidir nach mbeadh an scuaine roinnte go cothrom i scuainí éagsúla.",
+ "NumberOfQueueWorkersFieldTitle": "Líon na n-oibrithe scuaine",
+ "ProcessDuringRequestFieldHelp": "Má tá sé cumasaithe, próiseálfaimid gach iarratas laistigh de scuaine le linn gnáthiarratas rianaithe a luaithe a bheidh dóthain iarratas sa scuaine. Ní mhoilleoidh sé seo an t-iarratas rianaithe. Má tá tú díchumasaithe, caithfidh tú cronjob a shocrú a fheidhmíonn an %1$s./console queuedtracking:próiseáil %2$s ordú consóil m.sh. gach nóiméad chun an scuaine a phróiseáil.",
+ "ProcessDuringRequestFieldTitle": "Próiseas le linn iarratais rianaithe",
+ "QueueEnabledFieldHelp": "Má tá sé cumasaithe, scríobhfar gach iarratas rianaithe isteach i scuaine seachas iad go díreach isteach sa bhunachar sonraí. Teastaíonn freastalaí Redis agus síneadh PHP phpredis má tá Redis á úsáid mar inneall.",
+ "QueueEnabledFieldTitle": "Tá scuaine cumasaithe",
+ "RedisDatabaseFieldHelp": "I gcás go bhfuil tú ag baint úsáide as Redis le haghaidh taisce a dhéanamh cinnte a úsáid bunachar sonraí eile.",
+ "RedisDatabaseFieldTitle": "Bunachar sonraí Redis saor in aisce,",
+ "RedisHostFieldHelp": "Cianóstach nó soicéad unix den fhreastalaí Redis. Ceadaítear 500 carachtar ar a mhéad.",
+ "RedisHostFieldHelpExtended": "Má tá nasc TLS ag teastáil ó d’óstach, is féidir leat an prótacal TLS a ligean ar aghaidh chuig d’óstach mar: tls://example-host.com. Mura n-oibríonn sin, cinntigh go bhfuil na deimhnithe cumraithe i gceart ar do fhreastalaí Matomo.",
+ "RedisHostFieldHelpExtendedSentinel": "Toisc go bhfuil Redis Sentinel á úsáid agat, is féidir leat liosta scartha le camóg a úsáid. Déan cinnte an oiread óstach a shonrú agus a bhfuil calafoirt sonraithe agat. Mar shampla chun dhá fhreastalaí a chumrú “127.0.0.1:26379” agus “127.0.0.2:26879” sonraigh “127.0.0.1,127.0.0.2” mar óstach agus “26379,26879” mar phoirt.",
+ "RedisHostFieldTitle": "Redis ósta nó soicéad unix",
+ "RedisPasswordFieldHelp": "Pasfhocal socraithe ar an bhfreastalaí Redis, más ann dó. Is féidir treoir a thabhairt do Redis pasfhocal a éileamh sula gceadaítear do chliaint orduithe a fhorghníomhú.",
+ "RedisPasswordFieldTitle": "Redis pasfhocal",
+ "RedisPortFieldHelp": "Port an fhreastalaí Redis ar siúl. Ba chóir go mbeadh an luach idir 1 agus 65535. Bain úsáid as 0 má tá tú ag baint úsáide as soicéad unix chun ceangal le freastalaí Redis.",
+ "RedisPortFieldTitle": "Redis port",
+ "RedisTimeoutFieldHelp": "Redis am istigh ceangail i soicindí. Ciallaíonn “0.0” gan teorainn. Is féidir leis a bheith ina snámhán m.sh. “2.5” le haghaidh teorainn ama ceangail 2.5 soicind.",
+ "RedisTimeoutFieldTitle": "Teorainn ama Redis",
+ "UsePasswordForSentinelsHelp": "Ní bhaineann sé seo ach amháin má tá Sentinel cumasaithe.%1$sMá tá sé cumasaithe, úsáidfear an focal faire Redis freisin agus fíordheimhniú á dhéanamh le cásanna Sentinel chun an fhaisnéis nasc máistir a fháil. Seachas sin, ní úsáidtear an focal faire ach chun fíordheimhniú a dhéanamh leis an máistir Redis.",
+ "UsePasswordForSentinelsTitle": "Úsáid pasfhocal le Redis Sentinels",
+ "UseSentinelFieldHelp": "Má tá sé cumasaithe, úsáidfear an ghné Redis Sentinel. Déan cinnte an t-óstach agus an port a nuashonrú más gá. Nuair a bheidh an t-athrú cumasaithe agus sábháilte agat, beidh tú in ann óstach iolrach agus port scartha le camóga a shonrú.",
+ "UseSentinelFieldTitle": "Cumasaigh Redis Sentinel",
+ "WhatRedisBackEndType": "Roghnaigh cén cineál redis a úsáidfear. Déan cinnte an t-óstach agus an port a nuashonrú más gá. Nuair a bheidh an t-athrú roghnaithe agus sábháilte agat, beidh tú in ann óstaigh agus poirt iolracha a shonrú ag baint úsáide as liostaí scartha le camóg don chineál “Sentinel” agus “Cnuasach” amháin."
+ }
+}
diff --git a/lang/it.json b/lang/it.json
index dbd2bcd..188cedc 100644
--- a/lang/it.json
+++ b/lang/it.json
@@ -1,6 +1,10 @@
{
"QueuedTracking": {
+ "ExceptionValueIsNotInt": "Il valore non è un intero",
"MultipleServersOnlyConfigurableIfSentinelEnabled": "Host o porte multipli possono essere configurati solamente quando è abilitato Redis Sentinel. Il file readme del plugin ti dirà come farlo.",
- "NumHostsNotMatchNumPorts": "Il numero di host configurati con corrisponde al numero di porte configurate."
+ "NumHostsNotMatchNumPorts": "Il numero di host configurati con corrisponde al numero di porte configurate.",
+ "RedisHostFieldHelp": "Rimuovi host o socket unit del server Redis. Sono ammessi massimo 500 caratteri.",
+ "RedisHostFieldHelpExtended": "Se il tuo host richiede connessione TLS, puoi anteporre il protocollo TLS al tuo host, es: tls://example-host.com. Se non funziona, accertati che i certificati siano configurati correttamente nel tuo server Matomo.",
+ "RedisHostFieldTitle": "Host Redis o socket unix"
}
}
diff --git a/lang/nl.json b/lang/nl.json
index e01fa84..20b9273 100644
--- a/lang/nl.json
+++ b/lang/nl.json
@@ -1,6 +1,38 @@
{
"QueuedTracking": {
+ "AvailableRedisBackendTypeCluster": "Cluster",
+ "AvailableRedisBackendTypeSentinel": "Sentinel",
+ "AvailableRedisBackendTypeStandAlone": "Stand-alone",
+ "BackendSettingFieldHelp": "Selecteer de backend die je voor deze functie wilt gebruiken. Als je geen ervaring hebt met Redis of het is niet beschikbaar op uw server, raden wij u aan Mysql te gebruiken.",
+ "BackendSettingFieldTitle": "Backend",
+ "ExceptionValueIsNotInt": "De waarde is geen geheel getal",
+ "MasterNameFieldHelp": "De Sentinel-masternaam hoeft alleen te worden geconfigureerd als Sentinel is ingeschakeld.",
+ "MasterNameFieldTitle": "Redis Sentinel Master naam",
"MultipleServersOnlyConfigurableIfSentinelEnabled": "Meerdere hosts of poorten kunnen enkel geconfigureerd worden indien Redis Sentinel actief is. De plugin README beschrijft hoe u dit doet.",
- "NumHostsNotMatchNumPorts": "Het aantal geconfigureerde hosts komt niet overeen met het aantal geconfigureerde poorten."
+ "NumHostsNotMatchNumPorts": "Het aantal geconfigureerde hosts komt niet overeen met het aantal geconfigureerde poorten.",
+ "NumRequestsToProcessFieldHelp": "Definieert hoeveel aanvragen uit de wachtrij worden gehaald en in één keer worden verwerkt. Voer een getal in dat >= 1 is.",
+ "NumRequestsToProcessFieldTitle": "Aantal verzoeken dat in één batch wordt verwerkt",
+ "NumberOfQueueWorkersFieldHelp": "Toegestane maximum aantal wachtrij verwerkers. Accepteert een getal tussen 1 en 16. De beste praktijk is om het aantal CPU's in te stellen die je beschikbaar wilt maken voor wachtrijverwerking. Houd er rekening mee dat je ervoor moet zorgen dat je de verwerkers handmatig start. We raden aan om geen 9-15 verwerkers te gebruiken, maar liever 8 of 16, omdat de wachtrij mogelijk niet gelijkmatig over verschillende wachtrijen wordt verdeeld.",
+ "NumberOfQueueWorkersFieldHelpNew": "Aantal toegestane maximale wachtrij verwerkers. Accepteert een getal tussen 1 en 4096. De beste praktijk is om het aantal CPU's in te stellen die je beschikbaar wilt maken voor wachtrijverwerking. Houd er rekening mee dat je ervoor moet zorgen dat je de verwerkers handmatig start. We raden aan om geen 9-15 verwerkers te gebruiken, maar liever 8 of 16, omdat de wachtrij mogelijk niet gelijkmatig over verschillende wachtrijen wordt verdeeld.",
+ "NumberOfQueueWorkersFieldTitle": "Aantal wachtrij verwerkers",
+ "ProcessDuringRequestFieldHelp": "Indien ingeschakeld, verwerken we alle verzoeken binnen een wachtrij tijdens een normaal trackingverzoek zodra er voldoende verzoeken in de wachtrij staan. Dit zal het trackingverzoek niet vertragen. Indien uitgeschakeld, moet u een cronjob instellen die het console commando %1$s./console queuedtracking:process%2$s uitvoert, bijvoorbeeld om de wachtrij elke minuut te verwerken.",
+ "ProcessDuringRequestFieldTitle": "Verwerken tijdens trackingverzoek",
+ "QueueEnabledFieldHelp": "Indien ingeschakeld, worden alle trackingverzoeken in een wachtrij geschreven in plaats van rechtstreeks in de database. Vereist een Redis-server en een PHP-extensie van PHPredis indien je Redis als backend gebruikt.",
+ "QueueEnabledFieldTitle": "Wachtrij ingeschakeld",
+ "RedisDatabaseFieldHelp": "Indien je Redis gebruikt voor caching, zorg er dan voor dat je een andere database gebruikt.",
+ "RedisDatabaseFieldTitle": "Redis-database",
+ "RedisHostFieldHelp": "Externe host of Unix-socket van de Redis-server. Er zijn maximaal 500 tekens toegestaan.",
+ "RedisHostFieldHelpExtended": "Als uw host een TLS-verbinding vereist, kan je het TLS-protocol aan uw host toevoegen, zoals: tls://example-host.com. Als dat niet werkt, zorg er dan voor dat de certificaten correct zijn geconfigureerd op uw Matomo-server.",
+ "RedisHostFieldHelpExtendedSentinel": "Omdat je Redis Sentinel gebruikt, kun je een door komma's gescheiden lijst gebruiken. Zorg ervoor dat je evenveel hosts opgeeft als je poorten heeft opgegeven. Om bijvoorbeeld twee servers “127.0.0.1:26379” en “127.0.0.2:26879” te configureren, specificeer je “127.0.0.1,127.0.0.2” als host en “26379,26879” als poorten.",
+ "RedisHostFieldTitle": "Redis-host of Unix-socket",
+ "RedisPasswordFieldHelp": "Wachtwoord ingesteld op de Redis-server, indien aanwezig. Redis kan de opdracht krijgen om een wachtwoord te vereisen voordat clients opdrachten kunnen uitvoeren.",
+ "RedisPasswordFieldTitle": "Redis-wachtwoord",
+ "RedisPortFieldHelp": "Poort waarop de Redis-server draait. De waarde moet tussen 1 en 65535 liggen. Gebruik 0 als je een Unix-socket gebruikt om verbinding te maken met de Redis-server.",
+ "RedisPortFieldTitle": "Redis-poort",
+ "RedisTimeoutFieldHelp": "Time-out voor de Redis-verbinding in seconden. “0,0” betekent onbeperkt. Dit kan een decimale waarde zijn, bijvoorbeeld “2,5” voor een verbindingstime-out van 2,5 seconden.",
+ "RedisTimeoutFieldTitle": "Redis-time-out",
+ "UseSentinelFieldHelp": "Indien ingeschakeld, wordt de Redis Sentinel-functie gebruikt. Zorg ervoor dat je de host en poort indien nodig bijwerkt. Zodra je de wijziging ingeschakeld en opgeslagen hebt, kun je meerdere hosts en poorten met komma's gescheiden opgeven.",
+ "UseSentinelFieldTitle": "Schakel Redis Sentinel in",
+ "WhatRedisBackEndType": "Selecteer welk type Redis je wilt gebruiken. Zorg ervoor dat je de host en poort indien nodig bijwerkt. Zodra je de wijziging geselecteerd en opgeslagen hebt, kun je meerdere hosts en poorten opgeven met behulp van door komma's gescheiden lijsten voor alleen de typen \"Sentinel\" en \"Cluster\"."
}
}
diff --git a/lang/pt-br.json b/lang/pt-br.json
index 4d695f8..2233b61 100644
--- a/lang/pt-br.json
+++ b/lang/pt-br.json
@@ -1,6 +1,11 @@
{
"QueuedTracking": {
+ "ExceptionValueIsNotInt": "O valor não é um inteiro",
"MultipleServersOnlyConfigurableIfSentinelEnabled": "Vários hosts ou portas só podem ser configurados quando o Redis Sentinel está ativado. O plugin README lhe dirá como fazer isso.",
- "NumHostsNotMatchNumPorts": "O número de hosts configurados não coincide com o número de portas configuradas."
+ "NumHostsNotMatchNumPorts": "O número de hosts configurados não coincide com o número de portas configuradas.",
+ "RedisHostFieldHelp": "Host remoto ou socket unix do servidor Redis. São permitidos no máximo 500 caracteres.",
+ "RedisHostFieldHelpExtendedSentinel": "Como você está usando o Redis Sentinel, você pode usar uma lista separada por vírgulas. Certifique-se de especificar tantos hosts quanto portas especificadas. Por exemplo, para configurar dois servidores \"127.0.0.1:26379\" e \"127.0.0.2:26879\" especifique \"127.0.0.1,127.0.0.2\" como host e \"26379,26879\" como portas.",
+ "RedisHostFieldTitle": "Host Redis ou soquete unix",
+ "RedisPortFieldTitle": "Porto do Redis"
}
}
diff --git a/lang/pt.json b/lang/pt.json
index d706f0f..4876dfd 100644
--- a/lang/pt.json
+++ b/lang/pt.json
@@ -1,5 +1,6 @@
{
"QueuedTracking": {
+ "ExceptionValueIsNotInt": "O valor não é um inteiro",
"MultipleServersOnlyConfigurableIfSentinelEnabled": "Vários hosts ou portas só podem ser configurados quando o Redis Sentinel está ativado. O plugin README lhe dirá como fazer isso.",
"NumHostsNotMatchNumPorts": "O número de servidores configurados não coincide com o número de portas configuradas."
}
diff --git a/lang/sq.json b/lang/sq.json
index 23b4f9a..45347b4 100644
--- a/lang/sq.json
+++ b/lang/sq.json
@@ -1,6 +1,39 @@
{
"QueuedTracking": {
+ "AvailableRedisBackendTypeSentinel": "Sentinel",
+ "AvailableRedisBackendTypeStandAlone": "Më vete",
+ "BackendSettingFieldHelp": "Përzgjidhni mekanizmin e pasmë që doni të përdoret për këtë veçori. Nëse s’keni përvojë me Redis, ose s’është i pranishëm në shërbyesin tuaj, rekomandojmë përdorimin e Mysql-së.",
+ "BackendSettingFieldTitle": "Mekanizëm i pasmë",
+ "ExceptionValueIsNotInt": "Vlera s’është numër i plotë",
+ "MasterNameFieldHelp": "Emri për master sentinel lypset të formësohet vetëm nëse është aktivizuar Sentinel-i.",
+ "MasterNameFieldTitle": "Emër Master Sentinel Redis",
"MultipleServersOnlyConfigurableIfSentinelEnabled": "Disa strehë ose porta njëherësh mund të formësohen vetëm kur Redis Sentinel është i aktivizuar. README i shtojcës do t’ju mësojë si ta bëni.",
- "NumHostsNotMatchNumPorts": "Numri i strehëve të formësuara nuk përputhet me numrin e portave të formësuara."
+ "NumHostsNotMatchNumPorts": "Numri i strehëve të formësuara nuk përputhet me numrin e portave të formësuara.",
+ "NumRequestsToProcessFieldHelp": "Përcakton sa kërkesa do të merren prej radhës dhe përpunohen në një herë. Jepni një numër që është >= 1.",
+ "NumRequestsToProcessFieldTitle": "Numër kërkesash që përpunohen në një herë",
+ "NumberOfQueueWorkersFieldHelp": "Numri maksimum i lejuar për “queue workers”. Pranon një numër mes 1 dhe 16. Praktika më e mirë është të vini numrin e CPU-ve që doni të përdoren për përpunim radhësh. Kini parasysh se lypset të garantoni nisjen dorazi të workers-ve. Rekomandojmë të mos përdorni 9-15 “worker”s, përdorni më mirë 8 ose 16, ngaqë radha mund të mos shpërndahet në mënyrë të njëtrajtshme në radhë të ndryshme.",
+ "NumberOfQueueWorkersFieldHelpNew": "Numri maksimum i lejuar për “queue workers”. Pranon një numër mes 1 dhe 4096. Praktika më e mirë është të vini numrin e CPU-ve që doni të përdoren për përpunim radhësh. Kini parasysh se lypset të garantoni nisjen dorazi të workers-ve. Rekomandojmë të mos përdorni 9-15 “worker”s, përdorni më mirë 8 ose 16, ngaqë radha mund të mos shpërndahet në mënyrë të njëtrajtshme në radhë të ndryshme.",
+ "NumberOfQueueWorkersFieldTitle": "Numër për “queue workers”",
+ "ProcessDuringRequestFieldHelp": "Në u aktivizoftë, do të përpunojmë krejt kërkesat brenda një radhe gjatë një kërkese normale për ndjekje, pasi të ketë kërkesa të mjafta te radha. Kjo s’do të ngadalësojë kërkesën për ndjekje. Në u aktivizoftë, duhet të ujdisni një akt cron që ekzekuton urdhrin e konsolës %1$s./console queuedtracking:process%2$s p.sh., çdo minutë, që të përpunoni radhën.",
+ "ProcessDuringRequestFieldTitle": "Përpunoje gjatë ndjekjes së kërkesës",
+ "QueueEnabledFieldHelp": "Në u aktivizoftë, krejt kërkesat e gjurmimit do të shkruhen në një radhë, në vend se drejt e te baza e të dhënave. Lyp një shërbyes Redis dhe zgjerimin PHP phpredis, nëse përdoret Redis si mekanizëm i pasmë.",
+ "QueueEnabledFieldTitle": "Radhë e aktivizuar",
+ "RedisDatabaseFieldHelp": "Në rast se po përdorni Redis për ruajtje në fshehtinë, sigurohuni të përdorni një tjetër bazë të dhënash.",
+ "RedisDatabaseFieldTitle": "Bazë të dhënash Redis",
+ "RedisHostFieldHelp": "Strehë e largët, ose socket Unix e shërbyesit Redis. Lejohen deri në 500 shenja e shumta.",
+ "RedisHostFieldHelpExtended": "Nëse streha juaj lyp një lidhje TLS, mund t’i vini përpara strehës tuaj protokollin TLS, kështu: tls://example-host.com. Nëse kjo s’bën punë, sigurohuni se dëshmitë janë formësuar saktë te shërbyesi juaj Matomo.",
+ "RedisHostFieldHelpExtendedSentinel": "Meqë po përdorni Redis Sentinel, mund të përdorni një listë zërash ndarë me presje. Garantoni të specifikoni aq strehë sa keni porta të specifikuara. Për shembull, për të formësuar dy shërbyes “127.0.0.1:26379” dhe “127.0.0.2:26879”, jepni “127.0.0.1,127.0.0.2” si strehë dhe “26379,26879” si porta.",
+ "RedisHostFieldTitle": "Strehë Redis, ose socket Unix",
+ "RedisPasswordFieldHelp": "Fjalëkalim i caktuar te shërbyesi Redis, në pastë. Redis mund të udhëzohet të kërkojë një fjalëkalim, para se të lejojë klientë të ekzekutojnë urdhra.",
+ "RedisPasswordFieldTitle": "Fjalëkalim për Redis",
+ "RedisPortFieldHelp": "Porta në të cilën xhiron shërbyesi Redis. Vlera duhet të jetë mes 1 dhe 65535.Përdorni 0, nëse po përdorni një socket Unix për t’u lidhur me shërbyesin Redis.",
+ "RedisPortFieldTitle": "Portë Redis",
+ "RedisTimeoutFieldHelp": "Mbarim kohe lidhjeje Redis, në sekonda. “0.0” do të thotë e pakufizuar. Mund të jetë numër dhjetor, p.sh., “2.5” për një mbarim kohe prej 2.5 sekondash për lidhjen.",
+ "RedisTimeoutFieldTitle": "Mbarim kohe për Redis",
+ "UsePasswordForSentinelsHelp": "Ka vlerë vetëm nëse Sentinel është i aktivizuar.%1$sNë qoftë i aktivizuar, do të përdoret edhe fjalëkalimi Redis, kur bëhet mirëfilltësimi me instanca Sentinel, për të marrë hollësi mbi lidhjen kryesore. Përdnryshe, fjalëkalimi përdoret vetëm për mirëfilltësim me Redis master.",
+ "UsePasswordForSentinelsTitle": "Përdorni fjalëkalim me Redis Sentinels",
+ "UseSentinelFieldHelp": "Në u aktivizoftë, do të përdoret veçoria Redis Sentinel. Sigurohuni të përditësoni strehë dhe portë, në u dashtë. Pasi të keni aktivizuar dhe ruajtur ndryshimin, do të jeni në gjendje të specifikoni shumë strehë njëherësh dhe porta, ndarë me presje.",
+ "UseSentinelFieldTitle": "Aktivizo Redis Sentinel",
+ "WhatRedisBackEndType": "Përzgjidhni cili lloj Redis të përdoret. Mos harroni të përditësoni strehën dhe portën, në u dashtë. Pasi të keni përzgjedhur dhe ruajtur ndryshimet, do të jeni në gjendje të tregoni strehë dhe porta të shumta, duke përdorur lista elementësh të ndarë me presje, vetëm për llojin “Sentinel” dhe “Cluster”."
}
}
diff --git a/lang/sv.json b/lang/sv.json
index 382011b..08313a4 100644
--- a/lang/sv.json
+++ b/lang/sv.json
@@ -1,6 +1,32 @@
{
"QueuedTracking": {
+ "AvailableRedisBackendTypeCluster": "Cluster",
+ "AvailableRedisBackendTypeSentinel": "Sentinel",
+ "BackendSettingFieldHelp": "Välj den backend du vill använda för denna funktion. Om du inte har någon erfarenhet av Redis eller om det inte är tillgängligt på din server rekommenderar vi att du använder MySQL.",
+ "ExceptionValueIsNotInt": "Värdet är inte ett heltal",
"MultipleServersOnlyConfigurableIfSentinelEnabled": "Flera värdar eller portar kan bara konfigureras när Redis Sentinel är på. Insticksprogrammets README kommer att förklara hur du gör det.",
- "NumHostsNotMatchNumPorts": "Antalet konfigurerade värdar matchar inte antalet konfigurerade portar."
+ "NumHostsNotMatchNumPorts": "Antalet konfigurerade värdar matchar inte antalet konfigurerade portar.",
+ "NumRequestsToProcessFieldHelp": "Definierar hur många förfrågningar som väljs ut ur kön för att bearbetas i klump. Ange ett nummer större än 1.",
+ "NumRequestsToProcessFieldTitle": "Antal förfrågningar som bearbetas i en klump",
+ "ProcessDuringRequestFieldHelp": "Om aktiverad kommer alla förfrågningar i kön bearbetas under en normal spårningsförfrågan när det finns tillräckligt många förfrågningar i kön. Detta kommer inte att sakta ner spårningsförfrågan. Om inaktiverad måste du konfigurera ett cronjobb som kör konsolkommandot %1$s./console queuedtracking:process%2$s t.ex. varje minut för att bearbeta kön.",
+ "QueueEnabledFieldHelp": "Vid aktivering kommer alla spårningsförfrågningar att skrivas till en kö istället för direkt till databasen. Kräver en Redis-server och phpredis PHP-tillägg ifall Redis används som backend.",
+ "QueueEnabledFieldTitle": "Kö aktiverad",
+ "RedisDatabaseFieldHelp": "Om du använder Redis som cache behöver du använda en annan databas.",
+ "RedisDatabaseFieldTitle": "Redis-databas",
+ "RedisHostFieldHelp": "Värd eller unix-socket för Redis-server. Maximalt 500 tecken godtas.",
+ "RedisHostFieldHelpExtended": "Om din värd kräver en TLS-anslutning kan du lägga till TLS-protokollet före din värd så här: tls://exempel-värd.se. Om det inte fungerar, se till att certifikat är korrekt konfigurerade på din Matomo-server.",
+ "RedisHostFieldHelpExtendedSentinel": "Eftersom du använder Redis Sentinel kan du använda en kommaseparerad lista. Se till att ange lika många värdar som du har angivit portar. Till exempel, för att konfigurera två servrar \"127.0.0.1:26379\" och \"127.0.0.2:26879\", ange \"127.0.0.1,127.0.0.2\" som värd och \"26379,26879\" som portar.",
+ "RedisHostFieldTitle": "Redis-värd eller unix-socket",
+ "RedisPasswordFieldHelp": "Lösenordet sätts på Redis-servern, om något nu finns. Redis kan instrueras att kräva ett lösenord före den tillåter klienter att köra kommandon.",
+ "RedisPasswordFieldTitle": "Redis-lösenord",
+ "RedisPortFieldHelp": "Porten som Redis-servern körs på. Värdet ska vara mellan 1 och 65535. Använd 0 ifall du använder en unix-socket för att ansluta till Redis-servern.",
+ "RedisPortFieldTitle": "Redis-port",
+ "RedisTimeoutFieldHelp": "Redis anslutningstimeout i sekunder. \"0.0\" betyder obegränsad. Kan vara ett decimaltal, t.ex. \"2.5\" för en anslutningstimeout på 2,5 sekunder.",
+ "RedisTimeoutFieldTitle": "Redis-timeout",
+ "UsePasswordForSentinelsHelp": "Endast relevant om Sentinel är aktiverad.%1$sOm aktiverad kommer Redis-lösenordet även att användas vid autentisering med Sentinel-instanser för att hämta master-anslutningsinformationen. Annars används lösenordet endast för att autentisera med Redis master.",
+ "UsePasswordForSentinelsTitle": "Använd lösenord med Redis Sentinels",
+ "UseSentinelFieldHelp": "Om aktiverad kommer Redis Sentinel-funktion att användas. Se till att uppdatera värd och port vid behov. När du har aktiverat och sparat ändringen kommer du att kunna ange flera värdar och portar separerade med kommatecken.",
+ "UseSentinelFieldTitle": "Aktivera Redis Sentinel",
+ "WhatRedisBackEndType": "Välj vilken typ av redis att använda. Se till att uppdatera värd och port vid behov. När du har valt och sparat ändringen kan du ange flera värdar och portar med kommaseparerade listor endast för typerna \"Sentinel\" och \"Cluster\"."
}
}
diff --git a/lang/ta.json b/lang/ta.json
index 0967ef4..e689110 100644
--- a/lang/ta.json
+++ b/lang/ta.json
@@ -1 +1,38 @@
-{}
+{
+ "QueuedTracking": {
+ "AvailableRedisBackendTypeCluster": "கொத்து",
+ "AvailableRedisBackendTypeSentinel": "காவலாளி",
+ "AvailableRedisBackendTypeStandAlone": "தனியாக",
+ "BackendSettingFieldHelp": "இந்த அம்சத்திற்கு நீங்கள் பயன்படுத்த விரும்பும் பின்தளத்தில் தேர்ந்தெடுக்கவும். ரெடிசுடன் உங்களுக்கு எந்த அனுபவமும் இல்லை அல்லது அது உங்கள் சேவையகத்தில் கிடைக்கவில்லை என்றால், MySQL ஐப் பயன்படுத்த பரிந்துரைக்கிறோம்.",
+ "BackendSettingFieldTitle": "பின்தளத்தில்",
+ "ExceptionValueIsNotInt": "மதிப்பு ஒரு முழு எண் அல்ல",
+ "MasterNameFieldHelp": "சென்டினல் இயக்கப்பட்டிருந்தால் மட்டுமே சென்டினல் மாச்டர் பெயர் கட்டமைக்கப்பட வேண்டும்.",
+ "MasterNameFieldTitle": "ரெடிச் சென்டினல் மாச்டர் பெயர்",
+ "MultipleServersOnlyConfigurableIfSentinelEnabled": "ரெடிச் சென்டினல் இயக்கத்தில் இருக்கும்போது மட்டுமே பல ஓச்ட்கள் அல்லது துறைமுகங்கள் கட்டமைக்க முடியும். சொருகி ரீட்மே அதை எப்படி செய்வது என்று உங்களுக்குச் சொல்லும்.",
+ "NumHostsNotMatchNumPorts": "கட்டமைக்கப்பட்ட ஓச்ட்களின் எண்ணிக்கை உள்ளமைக்கப்பட்ட துறைமுகங்களின் எண்ணிக்கையுடன் பொருந்தவில்லை.",
+ "NumRequestsToProcessFieldHelp": "எத்தனை கோரிக்கைகள் வரிசையில் இருந்து எடுக்கப்பட்டு ஒரே நேரத்தில் செயலாக்கப்படும் என்பதை வரையறுக்கிறது. > = 1 என்ற எண்ணை உள்ளிடவும்.",
+ "NumRequestsToProcessFieldTitle": "ஒரு தொகுப்பில் செயலாக்கப்படும் கோரிக்கைகளின் எண்ணிக்கை",
+ "NumberOfQueueWorkersFieldHelp": "அனுமதிக்கப்பட்ட அதிகபட்ச வரிசை தொழிலாளர்களின் எண்ணிக்கை. 1 மற்றும் 16 க்கு இடையில் ஒரு எண்ணை ஏற்றுக்கொள்கிறது. வரிசை செயலாக்கத்திற்கு நீங்கள் கிடைக்க விரும்பும் சிபியு களின் எண்ணிக்கையை அமைப்பதே சிறந்த நடைமுறை. தொழிலாளர்களை கைமுறையாக தொடங்குவதை உறுதி செய்ய வேண்டும் என்பதை அறிந்து கொள்ளுங்கள். 9-15 தொழிலாளர்களைப் பயன்படுத்த வேண்டாம் என்று நாங்கள் பரிந்துரைக்கிறோம், மாறாக 8 அல்லது 16 ஐப் பயன்படுத்தவும், ஏனெனில் வரிசை வெவ்வேறு வரிசைகளில் சமமாக விநியோகிக்கப்படாது.",
+ "NumberOfQueueWorkersFieldHelpNew": "அனுமதிக்கப்பட்ட அதிகபட்ச வரிசை தொழிலாளர்களின் எண்ணிக்கை. 1 முதல் 4096 க்கு இடையில் ஒரு எண்ணை ஏற்றுக்கொள்கிறது. வரிசை செயலாக்கத்திற்கு நீங்கள் கிடைக்க விரும்பும் சிபியு களின் எண்ணிக்கையை அமைப்பதே சிறந்த நடைமுறை. தொழிலாளர்களை கைமுறையாக தொடங்குவதை உறுதி செய்ய வேண்டும் என்பதை அறிந்து கொள்ளுங்கள். 9-15 தொழிலாளர்களைப் பயன்படுத்த வேண்டாம் என்று நாங்கள் பரிந்துரைக்கிறோம், மாறாக 8 அல்லது 16 ஐப் பயன்படுத்தவும், ஏனெனில் வரிசை வெவ்வேறு வரிசைகளில் சமமாக விநியோகிக்கப்படாது.",
+ "NumberOfQueueWorkersFieldTitle": "வரிசை தொழிலாளர்களின் எண்ணிக்கை",
+ "ProcessDuringRequestFieldHelp": "இயக்கப்பட்டிருந்தால், வரிசையில் போதுமான கோரிக்கைகள் வந்தவுடன் சாதாரண கண்காணிப்பு கோரிக்கையின் போது அனைத்து கோரிக்கைகளையும் வரிசையில் செயலாக்குவோம். இது கண்காணிப்பு கோரிக்கையை குறைக்காது. முடக்கப்பட்டால், நீங்கள் %1$s./கன்சோல் கியூயட் டிராக்கிங்: செயல்முறை %2$s கன்சோல் கட்டளை எ.கா.",
+ "ProcessDuringRequestFieldTitle": "கண்காணிப்பு கோரிக்கையின் போது செயல்முறை",
+ "QueueEnabledFieldHelp": "இயக்கப்பட்டால், அனைத்து கண்காணிப்பு கோரிக்கைகளும் நேரடியாக தரவுத்தளத்திற்கு பதிலாக வரிசையில் எழுதப்படும். ரெடிசை பின்தளத்தில் பயன்படுத்தினால் ரெடிச் சேவையகம் மற்றும் PHPREDIS பிஎச்பி நீட்டிப்பு தேவைப்படுகிறது.",
+ "QueueEnabledFieldTitle": "வரிசை இயக்கப்பட்டது",
+ "RedisDatabaseFieldHelp": "கேச்சிங்கிற்கு நீங்கள் ரெடிசைப் பயன்படுத்துகிறீர்கள் என்றால், வேறு தரவுத்தளத்தைப் பயன்படுத்துவதை உறுதிசெய்க.",
+ "RedisDatabaseFieldTitle": "ரெடிச் தரவுத்தளம்",
+ "RedisHostFieldHelp": "ரெடிச் சேவையகத்தின் தொலை புரவலன் அல்லது யுனிக்ச் சாக்கெட். அதிகபட்சம் 500 எழுத்துக்கள் அனுமதிக்கப்படுகின்றன.",
+ "RedisHostFieldHelpExtended": "உங்கள் ஓச்டுக்கு டி.எல்.எச் இணைப்பு தேவைப்பட்டால், டி.எல்.எச் நெறிமுறையை உங்கள் ஓச்டுக்கு தயாரிக்கலாம்: டி.எல்.எச்: //example-host.com. அது வேலை செய்யவில்லை என்றால், உங்கள் மாடோமோ சேவையகத்தில் சான்றிதழ்கள் சரியாக கட்டமைக்கப்பட்டுள்ளதா என்பதை உறுதிப்படுத்திக் கொள்ளுங்கள்.",
+ "RedisHostFieldHelpExtendedSentinel": "நீங்கள் ரெடிச் சென்டினலைப் பயன்படுத்துவதால், நீங்கள் கமாவைப் பிரித்த பட்டியலைப் பயன்படுத்தலாம். நீங்கள் குறிப்பிட்ட துறைமுகங்களைக் கொண்ட பல ஓச்ட்களைக் குறிப்பிடுவதை உறுதிசெய்க. எடுத்துக்காட்டாக “127.0.0.1:26379” மற்றும் “127.0.0.2:26879” இரண்டு சேவையகங்களை ஓச்டாகவும் “26379,26879” ஆகவும் “127.0.0.1,127.0.0.0.0.0.2” என்று குறிப்பிடவும்.",
+ "RedisHostFieldTitle": "ரெடிச் புரவலன் அல்லது யுனிக்ச் சாக்கெட்",
+ "RedisPasswordFieldHelp": "கடவுச்சொல் ரெடிச் சேவையகத்தில் அமைக்கவும். வாடிக்கையாளர்களை கட்டளைகளை இயக்க அனுமதிப்பதற்கு முன் கடவுச்சொல் தேவை என்று ரெடிசுக்கு அறிவுறுத்தலாம்.",
+ "RedisPasswordFieldTitle": "ரெடிச் கடவுச்சொல்",
+ "RedisPortFieldHelp": "துறைமுகம் ரெடிச் சேவையகம் இயங்குகிறது. மதிப்பு 1 முதல் 65535 வரை இருக்க வேண்டும். ரெடிச் சேவையகத்துடன் இணைக்க நீங்கள் யூனிக்ச் சாக்கெட்டைப் பயன்படுத்தினால் 0 ஐப் பயன்படுத்தவும்.",
+ "RedisPortFieldTitle": "ரெடிச் துறைமுகம்",
+ "RedisTimeoutFieldHelp": "ரெடிச் இணைப்பு நேரம் நொடிகளில். “0.0” அதாவது வரம்பற்றது. 2.5 வினாடிகளின் இணைப்பு காலக்கெடுவுக்கு “2.5” ஒரு மிதவை எ.கா.",
+ "RedisTimeoutFieldTitle": "ரெடிச் நேரம் முடிந்தது",
+ "UseSentinelFieldHelp": "இயக்கப்பட்டால், ரெடிச் சென்டினல் நற்பொருத்தம் பயன்படுத்தப்படும். தேவைப்பட்டால் புரவலன் மற்றும் போர்ட்டைப் புதுப்பிப்பதை உறுதிசெய்க. மாற்றத்தை நீங்கள் இயக்கியதும் சேமித்ததும், பல ஓச்ட்கள் மற்றும் துறைமுகங்கள் கமாவைப் பிரிக்கலாம்.",
+ "UseSentinelFieldTitle": "ரெடிச் சென்டினலை இயக்கவும்",
+ "WhatRedisBackEndType": "எந்த வகை ரெடிசைப் பயன்படுத்த வேண்டும் என்பதைத் தேர்ந்தெடுக்கவும். தேவைப்பட்டால் புரவலன் மற்றும் போர்ட்டைப் புதுப்பிப்பதை உறுதிசெய்க. மாற்றத்தைத் தேர்ந்தெடுத்து சேமித்ததும், \"சென்டினல்\" மற்றும் \"கிளச்டர்\" வகைக்கு கமா பிரிக்கப்பட்ட பட்டியல்களைப் பயன்படுத்தி பல ஓச்ட்கள் மற்றும் துறைமுகங்களை நீங்கள் குறிப்பிட முடியும்."
+ }
+}
diff --git a/lang/tr.json b/lang/tr.json
index da662b5..e1b5a56 100644
--- a/lang/tr.json
+++ b/lang/tr.json
@@ -1,6 +1,40 @@
{
"QueuedTracking": {
+ "AvailableRedisBackendTypeCluster": "Küme",
+ "AvailableRedisBackendTypeSentinel": "Yedek",
+ "AvailableRedisBackendTypeStandAlone": "Bağımsız",
+ "BackendSettingFieldHelp": "Bu özellik için kullanmak istediğiniz arka ucu seçin. Redis ile herhangi bir deneyiminiz yoksa veya sunucunuzda kullanılamıyorsa, Mysql kullanmanızı öneririz.",
+ "BackendSettingFieldTitle": "Arka uç",
+ "ExceptionValueIsNotInt": "Değer bir tam sayı değil",
+ "MasterNameFieldHelp": "Sentinel Master adının yalnızca Sentinel açıksa yapılandırılması gerekir.",
+ "MasterNameFieldTitle": "Redis Sentinel Master adı",
"MultipleServersOnlyConfigurableIfSentinelEnabled": "Redis Sentinel eklentisi etkinleştirildiğinde birden çok sunucu ya da bağlantı noktası yapılandırılabilir. Gerekli bilgileri eklentinin README dosyasında bulabilirsiniz.",
- "NumHostsNotMatchNumPorts": "Yapılandırılmış sunucuların sayısı yapılandırılmış bağlantı noktaları ile eşleşmiyor."
+ "NumHostsNotMatchNumPorts": "Yapılandırılmış sunucuların sayısı yapılandırılmış bağlantı noktaları ile eşleşmiyor.",
+ "NumRequestsToProcessFieldHelp": "Bir kerede kuyruktan kaç isteğin alınacağını ve işleneceğini belirler. 1 değerine eşit veya büyük olan bir sayı yazın.",
+ "NumRequestsToProcessFieldTitle": "Bir kerede işlenecek istek sayısı",
+ "NumberOfQueueWorkersFieldHelp": "İzin verilen en fazla kuyruk işlemi sayısı. 1 ile 16 arasında bir sayı olabilir. En iyi uygulama, kuyruk işlenmesine ayırmak istediğiniz işlemci sayısını ayarlamaktır. İşlemleri elle başlattığınızdan emin olmanız gerektiğini unutmayın. Kuyruk farklı kuyruklara eşit olarak dağıtılamayabileceğinden 9-15 işlem kullanmamanızı, bunun yerine 8 veya 16 işlem kullanmanızı öneririz.",
+ "NumberOfQueueWorkersFieldHelpNew": "İzin verilen en fazla kuyruk işlemi sayısı. 1 ile 4096 arasında bir sayı olabilir. En iyi uygulama, kuyruk işlenmesine ayırmak istediğiniz işlemci sayısını ayarlamaktır. İşlemleri elle başlattığınızdan emin olmanız gerektiğini unutmayın. Kuyruk farklı kuyruklara eşit olarak dağıtılamayabileceğinden 9-15 işlem kullanmamanızı, bunun yerine 8 veya 16 işlem kullanmanızı öneririz.",
+ "NumberOfQueueWorkersFieldTitle": "Kuyruk işlemlerinin sayısı",
+ "ProcessDuringRequestFieldHelp": "Açıksa, kuyrukta yeterli istek olduğunda, normal bir izleme isteği sırasında kuyruktaki tüm istekler işlenir. Bu seçenek, izleme isteğini yavaşlatmaz. Kapalıysa, kuyruğu işlemek için örneğin 1 dakikada bir %1$s./console queuedtracking:process%2$s konsol komutunu yürüten bir zamanlanmış görev ayarlamanız gerekir.",
+ "ProcessDuringRequestFieldTitle": "İzleme isteği sırasında işlensin",
+ "QueueEnabledFieldHelp": "Açıksa, tüm izleme istekleri doğrudan veri tabanı yerine bir kuyruğa yazılır. Arka uç olarak Redis kullanılıyorsa bir Redis sunucusu ve phpredis PHP eklentisi gerekir.",
+ "QueueEnabledFieldTitle": "Kuyruk açık",
+ "RedisDatabaseFieldHelp": "Ön bellek için Redis kullanıyorsanız farklı bir veri tabanı kullandığınızdan emin olun.",
+ "RedisDatabaseFieldTitle": "Redis veri tabanı",
+ "RedisHostFieldHelp": "Uzak sunucu ya da Redis sunucusunun unix soketi. En fazla 500 karakter uzunluğunda olabilir.",
+ "RedisHostFieldHelpExtended": "Sunucunuz için bir TLS bağlantısı gerekiyorsa, TLS iletişim kuralını sunucunuza şu şekilde ekleyebilirsiniz: tls://ornek-sunucu.com. Bu işe yaramazsa, Matomo sunucunuzda sertifikaların doğru yapılandırıldığından emin olun.",
+ "RedisHostFieldHelpExtendedSentinel": "Redis Sentinel kullandığınız için virgülle ayrılmış bir liste kullanabilirsiniz. Belirttiğiniz bağlantı noktası sayısı kadar sunucu belirttiğinizden emin olun. Örneğin “127.0.0.1:26379” ve “127.0.0.2:26879” sunucularını yapılandırmak için sunucu olarak “127.0.0.1,127.0.0.2” ve bağlantı noktası olarak “26379,26879” belirtin.",
+ "RedisHostFieldTitle": "Redis sunucusu ya da unix soketi",
+ "RedisPasswordFieldHelp": "Varsa, Redis sunucusunda ayarlanmış parola. İstemcilerin komutları yürütmesine izin vermeden önce Redis sunucusu için bir parola gerektiği belirtilebilir.",
+ "RedisPasswordFieldTitle": "Redis parolası",
+ "RedisPortFieldHelp": "Redis sunucusunun çalıştığı bağlantı noktası. Değer 1 ile 65535 arasında olmalıdır. Redis sunucusuna bağlanmak için unix soketi kullanıyorsanız 0 kullanın.",
+ "RedisPortFieldTitle": "Redis bağlantı noktası",
+ "RedisTimeoutFieldHelp": "Saniye olarak Redis bağlantı zaman aşımı. “0.0” sınırsız anlamına gelir. Bir ondalık sayı olabilir, örneğin 2.5 saniyelik bir bağlantı zaman aşımı için “2.5”.",
+ "RedisTimeoutFieldTitle": "Redis zaman aşımı",
+ "UsePasswordForSentinelsHelp": "Yalnızca Sentinel etkinse geçerlidir.%1$sAçıldığında, ana bağlantı bilgilerini elde etmek için Sentinel kopyaları ile kimlik doğrulaması yaparken Redis parolası da kullanılır. Yoksa, parola yalnızca Redis master ile kimlik doğrulaması yapmak için kullanılır.",
+ "UsePasswordForSentinelsTitle": "Redis Sentinel ile parola kullanılsın",
+ "UseSentinelFieldHelp": "Açıksa, Redis Sentinel özelliği kullanılır. Gerekirse sunucu ve bağlantı noktasını güncellediğinizden emin olun. Açtıktan ve değişikliği kaydettikten sonra, virgülle ayrılmış birden fazla sunucu ve bağlantı noktası belirtebilirsiniz.",
+ "UseSentinelFieldTitle": "Redis Sentinel kullanılsın",
+ "WhatRedisBackEndType": "Kullanılacak Redis türünü seçin. Gerekirse sunucuyı ve bağlantı noktasını güncellemeyi unutmayın. Seçimi yaptıktan ve değişikliği kaydettikten sonra, yalnızca \"Yedek\" ve \"Küme\" türü için virgül ile ayrılmış listeler kullanarak birden fazla sunucu ve bağlantı noktası belirleyebilirsiniz."
}
}
diff --git a/lang/zh-cn.json b/lang/zh-cn.json
index b53ac22..59249e6 100644
--- a/lang/zh-cn.json
+++ b/lang/zh-cn.json
@@ -1,6 +1,7 @@
{
"QueuedTracking": {
- "NumHostsNotMatchNumPorts": "配置的主机数量与配置的端口数量不匹配。",
- "MultipleServersOnlyConfigurableIfSentinelEnabled": "仅在启用Redis Sentinel时才能配置多个主机或端口。 查看插件自述文件,以了解如何启用Sentinel。"
+ "ExceptionValueIsNotInt": "这个值不是整数",
+ "MultipleServersOnlyConfigurableIfSentinelEnabled": "仅在启用Redis Sentinel时才能配置多个主机或端口。 查看插件自述文件,以了解如何启用Sentinel。",
+ "NumHostsNotMatchNumPorts": "配置的主机数量与配置的端口数量不匹配。"
}
-}
\ No newline at end of file
+}
diff --git a/lang/zh-tw.json b/lang/zh-tw.json
index 8f595bf..ee72eb2 100644
--- a/lang/zh-tw.json
+++ b/lang/zh-tw.json
@@ -1,5 +1,6 @@
{
"QueuedTracking": {
+ "ExceptionValueIsNotInt": "該值不是整數",
"MultipleServersOnlyConfigurableIfSentinelEnabled": "只有在啟用 Redis Sentinel 時才能設定多個主機或端口。參閲外掛的 README 檔案來了解如何進行設定。",
"NumHostsNotMatchNumPorts": "設定的域名數量和端口數量不相符。"
}
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 0000000..67e4ce1
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,36 @@
+
+
+
+ Matomo Coding Standard for QueuedTracking plugin
+
+
+
+ .
+
+ tests/javascript/*
+ */vendor/*
+
+
+
+
+
+
+
+ tests/*
+
+
+
+
+ Updates/*
+
+
+
+
+ tests/*
+
+
+
+
+ tests/*
+
+
\ No newline at end of file
diff --git a/plugin.json b/plugin.json
index a9a09d8..1875b6b 100644
--- a/plugin.json
+++ b/plugin.json
@@ -1,6 +1,6 @@
{
"name": "QueuedTracking",
- "version": "5.0.3",
+ "version": "5.1.3",
"description": "Scale your large traffic Matomo service by queuing tracking requests in Redis or MySQL for better performance and reliability when experiencing peaks.",
"theme": false,
"keywords": ["tracker", "tracking", "queue", "redis"],
diff --git a/pull_request_template.md b/pull_request_template.md
new file mode 100644
index 0000000..e7d9cf5
--- /dev/null
+++ b/pull_request_template.md
@@ -0,0 +1,26 @@
+## Description
+
+
+## Issue No
+
+
+## Steps to Replicate the Issue
+1.
+2.
+3.
+
+
+
+## Checklist
+- [✔/✖] Tested locally or on demo2/demo3?
+- [✔/✖/NA] New test case added/updated?
+- [✔/✖/NA] Are all newly added texts included via translation?
+- [✔/✖/NA] Are text sanitized properly? (Eg use of v-text v/s v-html for vue)
+- [✔/✖/NA] Version bumped?
\ No newline at end of file
diff --git a/tests/Framework/Mock/ForcedException.php b/tests/Framework/Mock/ForcedException.php
index 889f097..fb31cf5 100644
--- a/tests/Framework/Mock/ForcedException.php
+++ b/tests/Framework/Mock/ForcedException.php
@@ -1,4 +1,5 @@
QueuedTracking = array('useSentinelBackend' => '1', 'sentinelMasterName' => $master);
+ Config::getInstance()->QueuedTracking = array('useWhatRedisBackendType' => '2', 'sentinelMasterName' => $master);
}
protected function disableRedisSentinel()
@@ -120,7 +121,6 @@ protected function buildRequestSetContainingError($numberOfRequestSets, $indexTh
} else {
$requests[] = new Request(array('idsite' => '1', 'index' => $i));
}
-
}
$set = new RequestSet();
@@ -128,6 +128,4 @@ protected function buildRequestSetContainingError($numberOfRequestSets, $indexTh
return $set;
}
-
-
}
diff --git a/tests/Integration/Queue/Backend/MysqlTest.php b/tests/Integration/Queue/Backend/MysqlTest.php
index 58dab6f..c9195b3 100644
--- a/tests/Integration/Queue/Backend/MysqlTest.php
+++ b/tests/Integration/Queue/Backend/MysqlTest.php
@@ -1,4 +1,5 @@
assertTrue($this->backend->hasAtLeastXRequestsQueued($this->emptyListKey, 1));
$this->assertFalse($this->backend->hasAtLeastXRequestsQueued($this->emptyListKey, 2));
- $this->backend->appendValuesToList($this->emptyListKey, range(1,11));
+ $this->backend->appendValuesToList($this->emptyListKey, range(1, 11));
$this->assertTrue($this->backend->hasAtLeastXRequestsQueued($this->emptyListKey, 10));
$this->assertTrue($this->backend->hasAtLeastXRequestsQueued($this->emptyListKey, 11));
$this->assertTrue($this->backend->hasAtLeastXRequestsQueued($this->emptyListKey, 12));
@@ -370,5 +371,4 @@ public function test_getKeysMatchingPattern_shouldReturnAnEmptyArrayIfNothingMat
$keys = $backend->getKeysMatchingPattern('*fere*');
$this->assertEquals(array(), $keys);
}
-
}
diff --git a/tests/Integration/Queue/Backend/RedisTest.php b/tests/Integration/Queue/Backend/RedisTest.php
index db0ba90..85cc2ca 100644
--- a/tests/Integration/Queue/Backend/RedisTest.php
+++ b/tests/Integration/Queue/Backend/RedisTest.php
@@ -1,4 +1,5 @@
assertTrue($this->redis->hasAtLeastXRequestsQueued($this->emptyListKey, 1));
$this->assertFalse($this->redis->hasAtLeastXRequestsQueued($this->emptyListKey, 2));
- $this->redis->appendValuesToList($this->emptyListKey, range(1,11));
+ $this->redis->appendValuesToList($this->emptyListKey, range(1, 11));
$this->assertTrue($this->redis->hasAtLeastXRequestsQueued($this->emptyListKey, 10));
$this->assertTrue($this->redis->hasAtLeastXRequestsQueued($this->emptyListKey, 11));
$this->assertTrue($this->redis->hasAtLeastXRequestsQueued($this->emptyListKey, 12));
@@ -329,5 +330,4 @@ public function test_getKeysMatchingPattern_shouldReturnAnEmptyArrayIfNothingMat
$keys = $backend->getKeysMatchingPattern('*fere*');
$this->assertEquals(array(), $keys);
}
-
}
diff --git a/tests/Integration/Queue/Backend/SentinelTest.php b/tests/Integration/Queue/Backend/SentinelTest.php
index eabe4fd..a7f3ca1 100644
--- a/tests/Integration/Queue/Backend/SentinelTest.php
+++ b/tests/Integration/Queue/Backend/SentinelTest.php
@@ -1,4 +1,5 @@
createRedisBackend());
@@ -63,13 +63,13 @@ public function test_makeBackend_shouldFailToCreateASentinelInstance_IfNotFullyC
$this->expectException(\Exception::class);
$this->expectExceptionMessage('You must configure a sentinel master name');
- Config::getInstance()->QueuedTracking = array('useSentinelBackend' => '1', 'sentinelMasterName' => '');
+ Config::getInstance()->QueuedTracking = array('useWhatRedisBackendType' => '2', 'sentinelMasterName' => '');
Factory::makeBackend();
}
public function test_makeBackend_shouldReturnASentinelInstanceIfConfigured()
{
- Config::getInstance()->QueuedTracking = array('useSentinelBackend' => '1', 'sentinelMasterName' => 'mymaster');
+ Config::getInstance()->QueuedTracking = array('useWhatRedisBackendType' => '2', 'sentinelMasterName' => 'mymaster');
$backend = Factory::makeBackend();
Config::getInstance()->QueuedTracking = array();
$this->assertTrue($backend instanceof Queue\Backend\Sentinel);
@@ -98,5 +98,4 @@ public function test_getSettings_shouldReturnASingleton()
$settings = Factory::getSettings();
$this->assertEquals(0.7, $settings->redisTimeout->getValue());
}
-
}
diff --git a/tests/Integration/Queue/LockTest.php b/tests/Integration/Queue/LockTest.php
index d0407e5..ef3cade 100644
--- a/tests/Integration/Queue/LockTest.php
+++ b/tests/Integration/Queue/LockTest.php
@@ -1,4 +1,5 @@
assertQueueIdForVisitorIdEquals($a, 'a');
$this->assertQueueIdForVisitorIdEquals($b, 'b');
$this->assertQueueIdForVisitorIdEquals($c, 'c');
- $this->assertQueueIdForVisitorIdEquals($a, 'abcdef');
- $this->assertQueueIdForVisitorIdEquals($b, 'bbcdef');
+ $this->assertQueueIdForVisitorIdEquals($d, 'abcdef');
+ $this->assertQueueIdForVisitorIdEquals($d, 'bbcdef');
$this->assertQueueIdForVisitorIdEquals($c, 'cbcdef');
}
@@ -267,11 +268,11 @@ public function test_addRequestSetToQueues_getNumberOfRequestSetsInAllQueues_sho
}
$this->assertSame(26, $this->manager->getNumberOfRequestSetsInAllQueues());
- $this->assertNumberOfRequestSetsInQueueEquals(5, $queueId = 0);
+ $this->assertNumberOfRequestSetsInQueueEquals(3, $queueId = 0);
$this->assertNumberOfRequestSetsInQueueEquals(9, $queueId = 1);
- $this->assertNumberOfRequestSetsInQueueEquals(1, $queueId = 2);
- $this->assertNumberOfRequestSetsInQueueEquals(11, $queueId = 3);
- $this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 4); // this queue is not available
+ $this->assertNumberOfRequestSetsInQueueEquals(7, $queueId = 2);
+ $this->assertNumberOfRequestSetsInQueueEquals(7, $queueId = 3);
+ $this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 4); // this queue is not available
}
public function test_addRequestSetToQueues_getNumberOfRequestSetsInAllQueues_shouldMoveAllInSameQueue_IfAllHaveSameUID()
@@ -287,12 +288,12 @@ public function test_addRequestSetToQueues_getNumberOfRequestSetsInAllQueues_sho
$this->assertSame(26, $this->manager->getNumberOfRequestSetsInAllQueues());
$this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 0);
- $this->assertNumberOfRequestSetsInQueueEquals(26, $queueId = 1);
- $this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 2);
+ $this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 1);
+ $this->assertNumberOfRequestSetsInQueueEquals(26, $queueId = 2);
$this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 3);
// verify all 26 written into queue
- $this->assertRequestSetsInQueueEquals($expectedRequestSets, 1);
+ $this->assertRequestSetsInQueueEquals($expectedRequestSets, 2);
}
public function test_addRequestSetToQueues_shouldMoveAllInSameQueue_IfAllHaveSameUidAndTheyAreInOneRequestSet()
@@ -303,12 +304,12 @@ public function test_addRequestSetToQueues_shouldMoveAllInSameQueue_IfAllHaveSam
$this->assertSame(1, $this->manager->getNumberOfRequestSetsInAllQueues());
$this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 0);
- $this->assertNumberOfRequestSetsInQueueEquals(1, $queueId = 1);
- $this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 2);
+ $this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 1);
+ $this->assertNumberOfRequestSetsInQueueEquals(1, $queueId = 2);
$this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 3);
// verify all 15 written into queue
- $this->assertRequestSetsInQueueEquals(array($requestSet), 1);
+ $this->assertRequestSetsInQueueEquals(array($requestSet), 2);
}
public function test_addRequestSetToQueues_shouldMoveIntoDifferentQueues_IfThereAreManyDifferentRequestsInOneSet()
@@ -328,21 +329,24 @@ public function test_addRequestSetToQueues_shouldMoveIntoDifferentQueues_IfThere
$this->manager->addRequestSetToQueues($req);
- $this->assertSame(3, $this->manager->getNumberOfRequestSetsInAllQueues()); // 3 different uid
+ $this->assertSame(4, $this->manager->getNumberOfRequestSetsInAllQueues()); // 4 different uid
- $this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 0);
+ $this->assertNumberOfRequestSetsInQueueEquals(1, $queueId = 0);
$this->assertNumberOfRequestSetsInQueueEquals(1, $queueId = 1);
$this->assertNumberOfRequestSetsInQueueEquals(1, $queueId = 2);
$this->assertNumberOfRequestSetsInQueueEquals(1, $queueId = 3);
$this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 4);
$req->setRequests(array($requests[1]));
+ $this->assertRequestSetsInQueueEquals([$req], 0);
+
+ $req->setRequests(array($requests[2], $requests[5]));
$this->assertRequestSetsInQueueEquals([$req], 1);
- $req->setRequests(array($requests[3]));
+ $req->setRequests(array($requests[0], $requests[4]));
$this->assertRequestSetsInQueueEquals([$req], 2);
- $req->setRequests(array($requests[0], $requests[2], $requests[4], $requests[5]));
+ $req->setRequests(array($requests[3]));
$this->assertRequestSetsInQueueEquals([$req], 3);
}
@@ -391,11 +395,11 @@ public function test_moveSomeQueuesIfNeeded_ShouldActuallyMoveQueues()
$this->manager->moveSomeQueuesIfNeeded($newNumWorkers, $oldNumWorkers);
- $this->assertNumberOfRequestSetsInQueueEquals(6, $queueId = 0);
+ $this->assertNumberOfRequestSetsInQueueEquals(1, $queueId = 0);
$this->assertNumberOfRequestSetsInQueueEquals(1, $queueId = 1);
$this->assertNumberOfRequestSetsInQueueEquals(1, $queueId = 2);
$this->assertNumberOfRequestSetsInQueueEquals(1, $queueId = 3);
- $this->assertNumberOfRequestSetsInQueueEquals(1, $queueId = 4);
+ $this->assertNumberOfRequestSetsInQueueEquals(6, $queueId = 4);
$this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 5);
$this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 6);
$this->assertNumberOfRequestSetsInQueueEquals(0, $queueId = 7);
@@ -451,5 +455,4 @@ private function addRequestSetToQueues($numRequestSets)
$this->manager->addRequestSetToQueues($this->buildRequestSetWithIdSite(1));
}
}
-
}
diff --git a/tests/Integration/Queue/Processor/HandlerTest.php b/tests/Integration/Queue/Processor/HandlerTest.php
index c207d92..953ba2c 100644
--- a/tests/Integration/Queue/Processor/HandlerTest.php
+++ b/tests/Integration/Queue/Processor/HandlerTest.php
@@ -1,4 +1,5 @@
transactionId;
@@ -46,13 +47,13 @@ public function setUp(): void
parent::setUp();
Fixture::createWebsite('2014-01-02 03:04:05');
-
+
$this->handler = $this->createHandler();
$this->tracker = new Tracker();
$this->handler->init($this->tracker);
}
-
+
public function tearDown(): void
{
$this->handler->rollBack($this->tracker);
@@ -273,12 +274,12 @@ public function test_process_ShouldRestoreTheEnvironmentOfARequest()
$cookieBackup = $_COOKIE;
$requestSet = $this->buildRequestSet(2);
- $requestSet->setEnvironment(array('server' => array('myserver' => 0), 'cookie' => array('testcookie'=> 7)));
+ $requestSet->setEnvironment(array('server' => array('myserver' => 0), 'cookie' => array('testcookie' => 7)));
$this->handler->process($this->tracker, $requestSet);
$this->assertEquals(array('myserver' => 0), $_SERVER);
- $this->assertEquals(array('testcookie'=> 7), $_COOKIE);
+ $this->assertEquals(array('testcookie' => 7), $_COOKIE);
$_SERVER = $serverBackup;
$_COOKIE = $cookieBackup;
@@ -288,5 +289,4 @@ private function createHandler()
{
return new TestHandler();
}
-
}
diff --git a/tests/Integration/Queue/ProcessorTest.php b/tests/Integration/Queue/ProcessorTest.php
index 40f5b9c..1661fdb 100644
--- a/tests/Integration/Queue/ProcessorTest.php
+++ b/tests/Integration/Queue/ProcessorTest.php
@@ -1,4 +1,5 @@
backend = $this->createMySQLBackend();
$this->lock = new Queue\Lock($this->backend);
@@ -181,7 +181,7 @@ public function test_processRequestSets_ShouldReturnAnEmptyArrayIfAllWereTracker
$requestSetsToRetry = $this->processor->processRequestSets($tracker, $queuedRequestSets);
$this->assertEquals(array(), $requestSetsToRetry);
- $this->assertSame(5+1+1+3, $tracker->getCountOfLoggedRequests());
+ $this->assertSame(5 + 1 + 1 + 3, $tracker->getCountOfLoggedRequests());
}
public function test_processRequestSets_ShouldReturnOnlyValidRequestSetsInCaseThereIsAFaultyOne()
@@ -282,7 +282,7 @@ public function test_process_ShouldRetryProcessingAllRequestsWithoutTheFailedOne
$tracker = $this->processor->process($this->createTracker());
- $this->assertSame(1+5+1+2+1+4, $tracker->getCountOfLoggedRequests());
+ $this->assertSame(1 + 5 + 1 + 2 + 1 + 4, $tracker->getCountOfLoggedRequests());
$this->assertNumberOfRequestSetsLeftInQueue(0);
}
@@ -361,7 +361,7 @@ public function test_process_shouldRestoreEnvironmentAfterTrackingRequests()
$this->queue->setNumberOfRequestsToProcessAtSameTime(1);
$requestSet = $this->buildRequestSet(5);
- $requestSet->setEnvironment(array('server' => array('test' => 1), 'cookie' => array('testcookie'=> 7)));
+ $requestSet->setEnvironment(array('server' => array('test' => 1), 'cookie' => array('testcookie' => 7)));
$this->queue->addRequestSetToQueues($requestSet);
$tracker = $this->process();
diff --git a/tests/Integration/QueueTest.php b/tests/Integration/QueueTest.php
index e476a09..8ce7a48 100644
--- a/tests/Integration/QueueTest.php
+++ b/tests/Integration/QueueTest.php
@@ -1,4 +1,5 @@
assertTrue($handler instanceof Handler);
}
-
}
diff --git a/tests/Integration/Settings/NumWorkersTest.php b/tests/Integration/Settings/NumWorkersTest.php
index 8a98e65..00f2c60 100644
--- a/tests/Integration/Settings/NumWorkersTest.php
+++ b/tests/Integration/Settings/NumWorkersTest.php
@@ -1,4 +1,5 @@
assertSame(0, $queues[2]->getNumberOfRequestSetsInQueue());
$this->assertSame(0, $queues[3]->getNumberOfRequestSetsInQueue());
}
-
}
diff --git a/tests/Integration/SettingsTest.php b/tests/Integration/SettingsTest.php
index 4d4ac94..09b5d38 100644
--- a/tests/Integration/SettingsTest.php
+++ b/tests/Integration/SettingsTest.php
@@ -1,4 +1,5 @@
settings = new SystemSettings();
}
@@ -39,7 +43,7 @@ public function tearDown(): void
public function test_redisHost_ShouldFail_IfMoreThan300CharctersGiven()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('Max 500 characters');
+ $this->expectExceptionMessage('should contain at most 500 characters');
$this->settings->redisHost->setValue(str_pad('3', 503, '4'));
}
@@ -47,23 +51,29 @@ public function test_redisHost_ShouldFail_IfMoreThan300CharctersGiven()
public function test_redisPort_ShouldFail_IfPortIsTooLow()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('Port has to be at least 1');
+ $this->expectExceptionMessage('The value needs to be at least 0');
- $this->settings->redisPort->setValue(0);
+ $this->settings->redisPort->setValue(-1);
}
public function test_redisPort_ShouldFail_IfPortIsTooHigh()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('Port should be max 65535');
+ $this->expectExceptionMessage('The value should be at most 65535');
$this->settings->redisPort->setValue(65536);
}
+ public function test_redisPort_ShouldNotFail_IfPortIsZero()
+ {
+ $this->settings->redisPort->setValue(0);
+ $this->assertEquals(0, $this->settings->redisPort->getValue());
+ }
+
public function test_redisTimeout_ShouldFail_IfTooLong()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('Max 5 characters');
+ $this->expectExceptionMessage('should contain at most 5 characters');
$this->settings->redisTimeout->setIsWritableByCurrentUser(true);
$this->settings->redisTimeout->setValue('333.43');
@@ -72,7 +82,7 @@ public function test_redisTimeout_ShouldFail_IfTooLong()
public function test_redisTimeout_ShouldFail_IfNotNumeric()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('should be numeric');
+ $this->expectExceptionMessage('The value is not a number');
$this->settings->redisTimeout->setIsWritableByCurrentUser(true);
$this->settings->redisTimeout->setValue('33d3.43');
@@ -81,7 +91,7 @@ public function test_redisTimeout_ShouldFail_IfNotNumeric()
public function test_sentinelMasterName_ShouldFail_IfTooManyCharacters()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('Max 200 characters are allowed');
+ $this->expectExceptionMessage('should contain at most 200 characters');
$this->settings->sentinelMasterName->setValue(str_pad('1', 201, '1'));
}
@@ -89,7 +99,7 @@ public function test_sentinelMasterName_ShouldFail_IfTooManyCharacters()
public function test_redisPassword_ShouldFail_IfMoreThan128CharctersGiven()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('Max 128 characters');
+ $this->expectExceptionMessage('should contain at most 128 characters');
$this->settings->redisPassword->setValue(str_pad('4', 130, '4'));
}
@@ -114,7 +124,7 @@ public function test_queueEnabled_ShouldNotFail_IfEnabledButWrongConnectionDetai
public function test_numRequestsToProcess_ShouldFail_IfTooLow()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('Number should be 1 or higher');
+ $this->expectExceptionMessage('The value needs to be at least 1');
$this->settings->numRequestsToProcess->setValue(0);
}
@@ -122,7 +132,7 @@ public function test_numRequestsToProcess_ShouldFail_IfTooLow()
public function test_numRequestsToProcess_ShouldFail_IfNotNumeric()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('Value should be a number');
+ $this->expectExceptionMessage('The value is not a number');
$this->settings->numRequestsToProcess->setValue('33d3.43');
}
@@ -130,7 +140,7 @@ public function test_numRequestsToProcess_ShouldFail_IfNotNumeric()
public function test_redisDatabase_ShouldFail_IfIsNumericButFloat()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('The database has to be an integer');
+ $this->expectExceptionMessage('The value is not an integer');
$this->settings->redisDatabase->setValue('5.34');
}
@@ -138,7 +148,7 @@ public function test_redisDatabase_ShouldFail_IfIsNumericButFloat()
public function test_redisDatabase_ShouldFail_IfNotNumeric()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('The database has to be an integer');
+ $this->expectExceptionMessage('The value is not a number');
$this->settings->redisDatabase->setValue('33d3.43');
}
@@ -146,7 +156,7 @@ public function test_redisDatabase_ShouldFail_IfNotNumeric()
public function test_redisDatabase_ShouldFail_IfTooLong()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('Max 5 digits allowed');
+ $this->expectExceptionMessage('should contain at most 5 characters');
$this->settings->redisDatabase->setValue('333333');
}
@@ -154,23 +164,31 @@ public function test_redisDatabase_ShouldFail_IfTooLong()
public function test_numQueueWorkers_ShouldFail_IfNotNumeric()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('should be an integer');
+ $this->expectExceptionMessage('The value is not a number');
$this->settings->numQueueWorkers->setValue('1f');
}
+ public function test_numQueueWorkers_ShouldFail_IfIsNumericButFloat()
+ {
+ $this->expectException(\Exception::class);
+ $this->expectExceptionMessage('The value is not an integer');
+
+ $this->settings->numQueueWorkers->setValue('1.2');
+ }
+
public function test_numQueueWorkers_ShouldFail_IfTooHigh()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('Only 1-16 workers allowed');
+ $this->expectExceptionMessage('The value should be at most 4096');
- $this->settings->numQueueWorkers->setValue('17');
+ $this->settings->numQueueWorkers->setValue('4097');
}
public function test_numQueueWorkers_ShouldFail_IfTooLow()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('Only 1-16 workers allowed');
+ $this->expectExceptionMessage('The value needs to be at least 1');
$this->settings->numQueueWorkers->setValue('0');
}
@@ -219,19 +237,33 @@ public function test_sentinelMasterName_ShouldTrimTheGivenValue_IfNotEmpty()
$this->assertSame('test', $this->settings->sentinelMasterName->getValue());
}
- public function test_useSentinelBackend()
+ public function test_useWhatRedisBackendType()
{
- $this->settings->useSentinelBackend->setValue('0');
- $this->assertFalse($this->settings->useSentinelBackend->getValue());
+ $this->settings->useWhatRedisBackendType->setValue(1);
+ $this->assertFalse($this->settings->isUsingSentinelBackend());
+
+ $this->settings->useWhatRedisBackendType->setValue(3);
+ $this->assertFalse($this->settings->isUsingSentinelBackend());
- $this->settings->useSentinelBackend->setValue('1');
- $this->assertTrue($this->settings->useSentinelBackend->getValue());
+ $this->settings->useWhatRedisBackendType->setValue(2);
+ $this->assertTrue($this->settings->isUsingSentinelBackend());
+ }
+
+ public function testIsUsingClusterBackend()
+ {
+ $this->settings->useWhatRedisBackendType->setValue(1);
+ $this->assertFalse($this->settings->isUsingClusterBackend());
+ $this->settings->useWhatRedisBackendType->setValue(2);
+ $this->assertFalse($this->settings->isUsingClusterBackend());
+
+ $this->settings->useWhatRedisBackendType->setValue(3);
+ $this->assertTrue($this->settings->isUsingClusterBackend());
}
public function test_redisPort_ShouldFailWhenMultipleValuesGiven_IfSentinelNotEnabled()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('QueuedTracking_MultipleServersOnlyConfigurableIfSentinelEnabled');
+ $this->expectExceptionMessage('Multiple hosts or ports can be only configured when Redis Sentinel is on.');
$this->settings->redisPort->setValue('45,56,788');
}
@@ -239,24 +271,24 @@ public function test_redisPort_ShouldFailWhenMultipleValuesGiven_IfSentinelNotEn
public function test_redisPort_ShouldNotFailAndConvertToIntWhenMultipleValuesGiven_IfSentinelIsEnabled()
{
$this->enableRedisSentinel();
- $this->settings->redisPort->setValue('55 , 44.34 ');
- $this->assertSame('55,44', $this->settings->redisPort->getValue());
+ $this->settings->redisPort->setValue('55 , 44.34, 0 ');
+ $this->assertSame('55,44,0', $this->settings->redisPort->getValue());
}
public function test_redisPort_ShouldValidateEachPortSeparately_WhenManySpecified()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('A port has to be a number');
+ $this->expectExceptionMessage('The value is not a number');
$this->enableRedisSentinel();
- $this->settings->redisPort->setValue('55 , 44.34, 4mk ');
+ $this->settings->redisPort->setValue('55, 0 , 44.34, 4mk ');
$this->assertSame('55,44', $this->settings->redisPort->getValue());
}
public function test_redisHost_ShouldFailWhenMultipleValuesGiven_IfSentinelNotEnabled()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('QueuedTracking_MultipleServersOnlyConfigurableIfSentinelEnabled');
+ $this->expectExceptionMessage('Multiple hosts or ports can be only configured when Redis Sentinel is on.');
$this->settings->redisHost->setValue('10.0.0.1,127.0.0.1');
}
@@ -273,9 +305,9 @@ public function test_queueEnabled_ShouldBeDisabledByDefault()
$this->assertFalse($this->settings->queueEnabled->getValue());
}
- public function test_useSentinelBackend_ShouldBeDisabledByDefault()
+ public function test_useWhatRedisBackendType_ShouldBe1Default()
{
- $this->assertFalse($this->settings->useSentinelBackend->getValue());
+ $this->assertSame(1, $this->settings->useWhatRedisBackendType->getValue());
}
public function test_sentinelMasterName_shouldHaveValueByDefault()
@@ -373,7 +405,7 @@ public function test_convertCommaSeparatedValueToArray($stringValue, $expectedAr
public function test_checkMultipleServersOnlyConfiguredWhenSentinelIsEnabled_shouldFailWhenMoreThanOneValue_IfSentinelNotEnabled($stringValue)
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('QueuedTracking_MultipleServersOnlyConfigurableIfSentinelEnabled');
+ $this->expectExceptionMessage('Multiple hosts or ports can be only configured when Redis Sentinel is on.');
$this->disableRedisSentinel();
@@ -402,7 +434,7 @@ public function getCommaSeparatedWithMultipleValues()
public function test_save_shouldFailIfPortAndHostMismatch()
{
$this->expectException(\Exception::class);
- $this->expectExceptionMessage('QueuedTracking_NumHostsNotMatchNumPorts');
+ $this->expectExceptionMessage('The number of configured hosts doesn\'t match the number of configured ports.');
$this->enableRedisSentinel();
$this->settings->redisPort->setValue('6379,6480,4393');
@@ -421,5 +453,4 @@ public function getCommaSeparatedValues()
array('foo,bar,baz', array('foo', 'bar', 'baz'))
);
}
-
}
diff --git a/tests/Integration/SystemCheckTest.php b/tests/Integration/SystemCheckTest.php
index 3a70236..001397d 100644
--- a/tests/Integration/SystemCheckTest.php
+++ b/tests/Integration/SystemCheckTest.php
@@ -1,4 +1,5 @@
usesFoundList[$pluginName]);
}
-}
\ No newline at end of file
+}
diff --git a/tests/System/TrackerTest.php b/tests/System/TrackerTest.php
index 9d3ee00..ffa8089 100644
--- a/tests/System/TrackerTest.php
+++ b/tests/System/TrackerTest.php
@@ -1,4 +1,5 @@
QueuedTracking = array();
$this->assertEquals(Configuration::$DEFAULT_NOTIFY_EMAILS, $this->configuration->getNotifyEmails());
}
-
-
}
diff --git a/tests/Unit/Queue/Processor/HandlerTest.php b/tests/Unit/Queue/Processor/HandlerTest.php
index b65a77e..01f6396 100644
--- a/tests/Unit/Queue/Processor/HandlerTest.php
+++ b/tests/Unit/Queue/Processor/HandlerTest.php
@@ -1,4 +1,5 @@
assertEquals($this->transactionId, $this->db->rollbackTransactionId);
$this->assertFalse($this->db->commitTransactionId);
}
-
}
diff --git a/tests/Unit/QueueTest.php b/tests/Unit/QueueTest.php
index 838ca12..110ff97 100644
--- a/tests/Unit/QueueTest.php
+++ b/tests/Unit/QueueTest.php
@@ -1,4 +1,5 @@