Browse Source

Downsizing: remove Redis

imwald
Nuša Pukšič 9 months ago
parent
commit
c4207be173
  1. 4
      .env.dist
  2. 1
      Dockerfile
  3. 1
      composer.json
  4. 9
      config/packages/cache.yaml
  5. 14
      config/services.yaml
  6. 6
      docker/cron/Dockerfile
  7. 10
      src/Controller/ArticleController.php
  8. 6
      src/Controller/AuthorController.php
  9. 6
      src/Controller/EventController.php
  10. 8
      src/Security/UserDTOProvider.php
  11. 70
      src/Service/RedisCacheService.php
  12. 4
      src/Twig/Components/Header.php
  13. 19
      src/Twig/Components/Molecules/CategoryLink.php
  14. 6
      src/Twig/Components/Molecules/UserFromNpub.php
  15. 4
      src/Twig/Components/Organisms/FeaturedList.php
  16. 10
      src/Util/CommonMark/Converter.php
  17. 7
      src/Util/CommonMark/NostrSchemeExtension/NostrMentionParser.php
  18. 6
      src/Util/CommonMark/NostrSchemeExtension/NostrRawNpubParser.php
  19. 8
      src/Util/CommonMark/NostrSchemeExtension/NostrSchemeExtension.php

4
.env.dist

@ -43,10 +43,6 @@ MERCURE_PUBLIC_URL=https://${SERVER_NAME}/.well-known/mercure @@ -43,10 +43,6 @@ MERCURE_PUBLIC_URL=https://${SERVER_NAME}/.well-known/mercure
# The secret used to sign the JWTs
MERCURE_JWT_SECRET="!NotSoSecretMercureHubJWTSecretKey!"
###< symfony/mercure-bundle ###
###> redis ###
REDIS_HOST=localhost
REDIS_PASSWORD=r_password
###< redis ###
###> LNBits ###
LNBITS_URL=https://legend.lnbits.com
LNBITS_API_KEY=<your-lnbits-admin-key>

1
Dockerfile

@ -36,7 +36,6 @@ RUN set -eux; \ @@ -36,7 +36,6 @@ RUN set -eux; \
zip \
gmp \
gd \
redis \
;
# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser

1
composer.json

@ -10,7 +10,6 @@ @@ -10,7 +10,6 @@
"ext-ctype": "*",
"ext-iconv": "*",
"ext-openssl": "*",
"ext-redis": "*",
"doctrine/dbal": "^4.2",
"doctrine/doctrine-bundle": "^2.13",
"doctrine/doctrine-migrations-bundle": "^3.3",

9
config/packages/cache.yaml

@ -3,13 +3,8 @@ framework: @@ -3,13 +3,8 @@ framework:
# Unique name of your app: used to compute stable namespaces for cache keys.
prefix_seed: newsroom/app
# The "app" cache stores to the filesystem by default.
# The data in this cache should persist between deploys.
# Other options include:
# Redis
app: cache.adapter.redis
default_redis_provider: Redis
# Use filesystem cache
app: cache.adapter.filesystem
# Namespaced pools use the above "app" backend by default
pools:

14
config/services.yaml

@ -27,17 +27,3 @@ services: @@ -27,17 +27,3 @@ services:
Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler:
arguments:
- '%env(DATABASE_URL)%'
# Redis (still used for cache, just not sessions)
Symfony\Component\Cache\Adapter\RedisAdapter:
arguments:
- '@Redis'
Redis:
# you can also use \RedisArray, \RedisCluster, \Relay\Relay or \Predis\Client classes
class: Redis
calls:
- connect:
- '%env(REDIS_HOST)%'
- auth:
- '%env(REDIS_PASSWORD)%'

6
docker/cron/Dockerfile

@ -8,12 +8,6 @@ RUN apt-get update && apt-get install -y \ @@ -8,12 +8,6 @@ RUN apt-get update && apt-get install -y \
libpq-dev \
libonig-dev
# Install Redis PHP extension
RUN pecl install redis \
&& docker-php-ext-enable redis
RUN docker-php-ext-install pdo pdo_pgsql
# Set working directory
WORKDIR /var/www/html

10
src/Controller/ArticleController.php

@ -6,7 +6,7 @@ use App\Entity\Article; @@ -6,7 +6,7 @@ use App\Entity\Article;
use App\Enum\KindsEnum;
use App\Form\EditorType;
use App\Service\NostrClient;
use App\Service\RedisCacheService;
use App\Service\CacheService;
use App\Util\CommonMark\Converter;
use Doctrine\ORM\EntityManagerInterface;
use League\CommonMark\Exception\CommonMarkException;
@ -62,7 +62,7 @@ class ArticleController extends AbstractController @@ -62,7 +62,7 @@ class ArticleController extends AbstractController
public function article(
$slug,
EntityManagerInterface $entityManager,
RedisCacheService $redisCacheService,
CacheService $cacheService,
CacheItemPoolInterface $articlesCache,
Converter $converter
): Response
@ -101,7 +101,7 @@ class ArticleController extends AbstractController @@ -101,7 +101,7 @@ class ArticleController extends AbstractController
$key = new Key();
$npub = $key->convertPublicKeyToBech32($article->getPubkey());
$author = $redisCacheService->getMetadata($npub);
$author = $cacheService->getMetadata($npub);
return $this->render('pages/article.html.twig', [
@ -120,7 +120,7 @@ class ArticleController extends AbstractController @@ -120,7 +120,7 @@ class ArticleController extends AbstractController
public function articlePreviewEvent(
Request $request,
NostrClient $nostrClient,
RedisCacheService $redisCacheService,
CacheService $cacheService,
CacheItemPoolInterface $articlesCache
): Response {
$data = $request->getContent();
@ -136,7 +136,7 @@ class ArticleController extends AbstractController @@ -136,7 +136,7 @@ class ArticleController extends AbstractController
$hint = json_decode($descriptor->decoded);
$key = new Key();
$npub = $key->convertPublicKeyToBech32($hint->pubkey);
$metadata = $redisCacheService->getMetadata($npub);
$metadata = $cacheService->getMetadata($npub);
$metadata->npub = $npub;
$metadata->pubkey = $hint->pubkey;
$metadata->type = 'nprofile';

6
src/Controller/AuthorController.php

@ -6,7 +6,7 @@ namespace App\Controller; @@ -6,7 +6,7 @@ namespace App\Controller;
use App\Repository\ArticleRepository;
use App\Service\NostrClient;
use App\Service\RedisCacheService;
use App\Service\CacheService;
use Exception;
use swentel\nostr\Key\Key;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@ -19,12 +19,12 @@ class AuthorController extends AbstractController @@ -19,12 +19,12 @@ class AuthorController extends AbstractController
* @throws Exception
*/
#[Route('/p/{npub}', name: 'author-profile', requirements: ['npub' => '^npub1.*'])]
public function index($npub, NostrClient $nostrClient, RedisCacheService $redisCacheService, ArticleRepository $articleRepository): Response
public function index($npub, NostrClient $nostrClient, CacheService $cacheService, ArticleRepository $articleRepository): Response
{
$keys = new Key();
$pubkey = $keys->convertToHex($npub);
$author = $redisCacheService->getMetadata($npub);
$author = $cacheService->getMetadata($npub);
// Retrieve long-form content for the author
try {
$list = $nostrClient->getLongFormContentForPubkey($npub);

6
src/Controller/EventController.php

@ -6,7 +6,7 @@ namespace App\Controller; @@ -6,7 +6,7 @@ namespace App\Controller;
use App\Service\NostrClient;
use App\Service\NostrLinkParser;
use App\Service\RedisCacheService;
use App\Service\CacheService;
use Exception;
use nostriphant\NIP19\Bech32;
use nostriphant\NIP19\Data;
@ -23,7 +23,7 @@ class EventController extends AbstractController @@ -23,7 +23,7 @@ class EventController extends AbstractController
* @throws Exception
*/
#[Route('/e/{nevent}', name: 'nevent', requirements: ['nevent' => '^nevent1.*'])]
public function index($nevent, NostrClient $nostrClient, RedisCacheService $redisCacheService, NostrLinkParser $nostrLinkParser, LoggerInterface $logger): Response
public function index($nevent, NostrClient $nostrClient, CacheService $cacheService, NostrLinkParser $nostrLinkParser, LoggerInterface $logger): Response
{
$logger->info('Accessing event page', ['nevent' => $nevent]);
@ -89,7 +89,7 @@ class EventController extends AbstractController @@ -89,7 +89,7 @@ class EventController extends AbstractController
if (isset($event->pubkey)) {
$key = new Key();
$npub = $key->convertPublicKeyToBech32($event->pubkey);
$authorMetadata = $redisCacheService->getMetadata($npub);
$authorMetadata = $cacheService->getMetadata($npub);
}
// Render template with the event data and extracted Nostr links

8
src/Security/UserDTOProvider.php

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
namespace App\Security;
use App\Entity\User;
use App\Service\RedisCacheService;
use App\Service\CacheService;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
@ -19,7 +19,7 @@ readonly class UserDTOProvider implements UserProviderInterface @@ -19,7 +19,7 @@ readonly class UserDTOProvider implements UserProviderInterface
{
public function __construct(
private EntityManagerInterface $entityManager,
private RedisCacheService $redisCacheService,
private CacheService $cacheService,
private LoggerInterface $logger
)
{
@ -40,7 +40,7 @@ readonly class UserDTOProvider implements UserProviderInterface @@ -40,7 +40,7 @@ readonly class UserDTOProvider implements UserProviderInterface
$this->logger->info('Refresh user.', ['user' => $user->getUserIdentifier()]);
$freshUser = $this->entityManager->getRepository(User::class)
->findOneBy(['npub' => $user->getUserIdentifier()]);
$metadata = $this->redisCacheService->getMetadata($user->getUserIdentifier());
$metadata = $this->cacheService->getMetadata($user->getUserIdentifier());
$freshUser->setMetadata($metadata);
return $freshUser;
}
@ -75,7 +75,7 @@ readonly class UserDTOProvider implements UserProviderInterface @@ -75,7 +75,7 @@ readonly class UserDTOProvider implements UserProviderInterface
$this->entityManager->flush();
}
$metadata = $this->redisCacheService->getMetadata($identifier);
$metadata = $this->cacheService->getMetadata($identifier);
$user->setMetadata($metadata);
$this->logger->debug('User metadata set.', ['metadata' => json_encode($user->getMetadata())]);

70
src/Service/RedisCacheService.php

@ -1,70 +0,0 @@ @@ -1,70 +0,0 @@
<?php
namespace App\Service;
use Psr\Cache\InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
readonly class RedisCacheService
{
public function __construct(
private NostrClient $nostrClient,
private CacheInterface $redisCache,
private LoggerInterface $logger
)
{
}
/**
* @param string $npub
* @return \stdClass
*/
public function getMetadata(string $npub): \stdClass
{
$cacheKey = '0_' . $npub;
try {
return $this->redisCache->get($cacheKey, function (ItemInterface $item) use ($npub) {
$item->expiresAfter(3600); // 1 hour, adjust as needed
try {
$meta = $this->nostrClient->getNpubMetadata($npub);
} catch (\Exception $e) {
$this->logger->error('Error getting user data.', ['exception' => $e]);
$meta = new \stdClass();
$content = new \stdClass();
$meta->name = substr($npub, 0, 8) . '…' . substr($npub, -4);
$meta->content = json_encode($content);
}
$this->logger->info('Metadata:', ['meta' => json_encode($meta)]);
return json_decode($meta->content);
});
} catch (InvalidArgumentException $e) {
$this->logger->error('Error getting user data.', ['exception' => $e]);
$content = new \stdClass();
$content->name = substr($npub, 0, 8) . '…' . substr($npub, -4);
return $content;
}
}
public function getRelays($npub)
{
$cacheKey = '10002_' . $npub;
try {
return $this->redisCache->get($cacheKey, function (ItemInterface $item) use ($npub) {
$item->expiresAfter(3600); // 1 hour, adjust as needed
try {
$relays = $this->nostrClient->getNpubRelays($npub);
} catch (\Exception $e) {
$this->logger->error('Error getting user relays.', ['exception' => $e]);
}
return $relays ?? [];
});
} catch (InvalidArgumentException $e) {
$this->logger->error('Error getting user relays.', ['exception' => $e]);
return [];
}
}
}

4
src/Twig/Components/Header.php

@ -16,9 +16,9 @@ class Header @@ -16,9 +16,9 @@ class Header
/**
* @throws InvalidArgumentException
*/
public function __construct(private readonly CacheInterface $redisCache)
public function __construct(private readonly CacheInterface $cache)
{
$mag = $this->redisCache->get('magazine-newsroom-magazine-by-newsroom', function (){
$mag = $this->cache->get('magazine-newsroom-magazine-by-newsroom', function (){
return null;
});

19
src/Twig/Components/Molecules/CategoryLink.php

@ -11,17 +11,16 @@ final class CategoryLink @@ -11,17 +11,16 @@ final class CategoryLink
public string $title;
public string $slug;
public function __construct(private CacheInterface $redisCache)
public function __construct(private CacheInterface $cache)
{
}
public function mount($coordinate): void
public function mount($category): void
{
if (key_exists(1, $coordinate)) {
$parts = explode(':', $coordinate[1]);
$this->slug = $parts[2];
$cat = $this->redisCache->get('magazine-' . $parts[2], function (){
return null;
$parts = explode(':', $category[1]);
try {
$cat = $this->cache->get('magazine-' . $parts[2], function (){
throw new \Exception('Not found');
});
$tags = $cat->getTags();
@ -31,10 +30,8 @@ final class CategoryLink @@ -31,10 +30,8 @@ final class CategoryLink
});
$this->title = $title[array_key_first($title)][1];
} else {
dump($coordinate);die();
} catch (\Exception $e) {
// Handle cache miss
}
}
}

6
src/Twig/Components/Molecules/UserFromNpub.php

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
namespace App\Twig\Components\Molecules;
use App\Service\RedisCacheService;
use App\Service\CacheService;
use swentel\nostr\Key\Key;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
@ -13,7 +13,7 @@ final class UserFromNpub @@ -13,7 +13,7 @@ final class UserFromNpub
public string $npub;
public $user = null;
public function __construct(private readonly RedisCacheService $redisCacheService)
public function __construct(private readonly CacheService $cacheService)
{
}
@ -27,6 +27,6 @@ final class UserFromNpub @@ -27,6 +27,6 @@ final class UserFromNpub
} else {
$this->npub = $ident;
}
$this->user = $this->redisCacheService->getMetadata($this->npub);
$this->user = $this->cacheService->getMetadata($this->npub);
}
}

4
src/Twig/Components/Organisms/FeaturedList.php

@ -16,7 +16,7 @@ final class FeaturedList @@ -16,7 +16,7 @@ final class FeaturedList
public array $list = [];
public function __construct(
private readonly CacheInterface $redisCache,
private readonly CacheInterface $cache,
private readonly ArticleRepository $articleRepository)
{
}
@ -29,7 +29,7 @@ final class FeaturedList @@ -29,7 +29,7 @@ final class FeaturedList
{
$parts = explode(':', $category[1]);
/** @var Event $catIndex */
$catIndex = $this->redisCache->get('magazine-' . $parts[2], function (){
$catIndex = $this->cache->get('magazine-' . $parts[2], function (){
throw new \Exception('Not found');
});

10
src/Util/CommonMark/Converter.php

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
namespace App\Util\CommonMark;
use App\Service\RedisCacheService;
use App\Service\CacheService;
use App\Util\CommonMark\ImagesExtension\RawImageLinkExtension;
use App\Util\CommonMark\NostrSchemeExtension\NostrSchemeExtension;
use League\CommonMark\Environment\Environment;
@ -25,8 +25,10 @@ use League\CommonMark\Renderer\HtmlDecorator; @@ -25,8 +25,10 @@ use League\CommonMark\Renderer\HtmlDecorator;
readonly class Converter
{
public function __construct(
private RedisCacheService $redisCacheService
){}
private CacheService $cacheService
)
{
}
/**
* @throws CommonMarkException
@ -64,7 +66,7 @@ readonly class Converter @@ -64,7 +66,7 @@ readonly class Converter
$environment->addExtension(new TableExtension());
$environment->addExtension(new StrikethroughExtension());
// create a custom extension, that handles nostr mentions
$environment->addExtension(new NostrSchemeExtension($this->redisCacheService));
$environment->addExtension(new NostrSchemeExtension($this->cacheService));
$environment->addExtension(new SmartPunctExtension());
$environment->addExtension(new EmbedExtension());
$environment->addRenderer(Embed::class, new HtmlDecorator(new EmbedRenderer(), 'div', ['class' => 'embedded-content']));

7
src/Util/CommonMark/NostrSchemeExtension/NostrMentionParser.php

@ -2,11 +2,10 @@ @@ -2,11 +2,10 @@
namespace App\Util\CommonMark\NostrSchemeExtension;
use App\Service\RedisCacheService;
use App\Service\CacheService;
use League\CommonMark\Parser\Inline\InlineParserInterface;
use League\CommonMark\Parser\Inline\InlineParserMatch;
use League\CommonMark\Parser\InlineParserContext;
use swentel\nostr\Key\Key;
/**
* Class NostrMentionParser
@ -17,7 +16,7 @@ use swentel\nostr\Key\Key; @@ -17,7 +16,7 @@ use swentel\nostr\Key\Key;
readonly class NostrMentionParser implements InlineParserInterface
{
public function __construct(
private RedisCacheService $redisCacheService
private CacheService $cacheService
){}
public function getMatchDefinition(): InlineParserMatch
@ -40,7 +39,7 @@ readonly class NostrMentionParser implements InlineParserInterface @@ -40,7 +39,7 @@ readonly class NostrMentionParser implements InlineParserInterface
$npubLink = substr($fullMatch, strpos($fullMatch, 'npub1'), -1); // e.g., "npubXXXX"
if (empty($label)) {
$metadata = $this->redisCacheService->getMetadata($npubLink);
$metadata = $this->cacheService->getMetadata($npubLink);
$label = $metadata->display_name ?? $metadata->name;
}

6
src/Util/CommonMark/NostrSchemeExtension/NostrRawNpubParser.php

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
namespace App\Util\CommonMark\NostrSchemeExtension;
use App\Service\RedisCacheService;
use App\Service\CacheService;
use League\CommonMark\Parser\Inline\InlineParserInterface;
use League\CommonMark\Parser\Inline\InlineParserMatch;
use League\CommonMark\Parser\InlineParserContext;
@ -14,7 +14,7 @@ use League\CommonMark\Parser\InlineParserContext; @@ -14,7 +14,7 @@ use League\CommonMark\Parser\InlineParserContext;
readonly class NostrRawNpubParser implements InlineParserInterface
{
public function __construct(private RedisCacheService $redisCacheService)
public function __construct(private CacheService $cacheService)
{
}
@ -28,7 +28,7 @@ readonly class NostrRawNpubParser implements InlineParserInterface @@ -28,7 +28,7 @@ readonly class NostrRawNpubParser implements InlineParserInterface
$cursor = $inlineContext->getCursor();
// Get the match and extract relevant parts
$fullMatch = $inlineContext->getFullMatch();
$meta = $this->redisCacheService->getMetadata($fullMatch);
$meta = $this->cacheService->getMetadata($fullMatch);
// Create a new inline node for the custom link
$inlineContext->getContainer()->appendChild(new NostrMentionLink($meta->name, $fullMatch));

8
src/Util/CommonMark/NostrSchemeExtension/NostrSchemeExtension.php

@ -2,23 +2,23 @@ @@ -2,23 +2,23 @@
namespace App\Util\CommonMark\NostrSchemeExtension;
use App\Service\RedisCacheService;
use App\Service\CacheService;
use League\CommonMark\Environment\EnvironmentBuilderInterface;
use League\CommonMark\Extension\ExtensionInterface;
class NostrSchemeExtension implements ExtensionInterface
{
public function __construct(private readonly RedisCacheService $redisCacheService)
public function __construct(private readonly CacheService $cacheService)
{
}
public function register(EnvironmentBuilderInterface $environment): void
{
$environment
->addInlineParser(new NostrMentionParser($this->redisCacheService), 200)
->addInlineParser(new NostrMentionParser($this->cacheService), 200)
->addInlineParser(new NostrSchemeParser(), 199)
->addInlineParser(new NostrRawNpubParser($this->redisCacheService), 198)
->addInlineParser(new NostrRawNpubParser($this->cacheService), 198)
->addRenderer(NostrSchemeData::class, new NostrEventRenderer(), 2)
->addRenderer(NostrMentionLink::class, new NostrMentionRenderer(), 1)

Loading…
Cancel
Save