protected function incrementCounter($actionName, $blockType, $entityId, $config)
    {
        // Begin an exclusive transaction
        $this->storage->transaction($actionName, $blockType, RateLimitStorageInterface::TRANSACTION_BEGIN);
        
        $limit = $this->getLimitFor($actionName, $blockType, $entityId);

        $time = time();

        $resetCounter =
            // Counter reset after specified timeout since the last action
            ($time > $limit["ts"] + $config["counterTimeout"]) ||

            // Counter reset after blockout delay timeout
            ($limit["cnt"] >= $config["count"] && $time > $limit["ts"] + $config["blockDuration"]);

        if ($resetCounter) {
            $limit["cnt"] = 0;
        }

        $limitBeforeIncrement = $limit;

        // The limit will be reached with this increment
        if ($limit["cnt"] === $config["count"] - 1) {
            $this->logRateLimitReached($actionName, $blockType, $entityId, $config);
        }

        ++$limit["cnt"];
        $limit["ts"] = $time;

        // Update the limit if the entity is not blocked
        if ($limit["cnt"] <= $config["count"]) {
            $this->storage->updateLimitFor($actionName, $blockType, $entityId, $limit);
            if (rand(0, 100) <= $this->config["cleanupProbability"]) {
                $this->storage->cleanup($actionName, $blockType, $config);
            }
            $this->storage->save($actionName, $blockType);
        }
        
        // Close the transaction
        $this->storage->transaction($actionName, $blockType, RateLimitStorageInterface::TRANSACTION_END);
        
        // Returns the limit array before the increment
        return $limitBeforeIncrement;
    }