A może by tak robić API na .NET Core z wykorzystaniem CQRS? Albo, jak robić mikroserwisy w podejściu DDD

No właśnie, taki popularny wzorzec architektoniczny a nikt nie chce go używać. Co prawda używają, ale na potrzeby tego wpisu załóżmy że nie 😉

Nie będę tutaj definiował, czym jest CQRS bo za mnie już to zrobił Pan Martin Fowler (https://martinfowler.com/bliki/CQRS.html), powiem tylko krótko – CQRS jest oparty o ideologię rozgraniczenia odpowiedzialności na odczyt i zapis, gdzie Queries mogą tylko odczytywać dane a zapisywać dane mogą tylko Commands. W swojej niezbyt długiej karierze widziałem kilka podejść do implementacji tego wzorca w projektach różnej wielkości, ale większość z tych projektów i tak korzystała z zdefiniowanych w Controller’ach akcjach, które wołały albo sam Query/Command albo jakiś Handler. IMO, w takim podejściu niepotrzebnie zwiększamy poziom abstrakcji w projekcie i w 99.9(9)% przypadków przytoczone wyżej Controller’y służą tylko jako przelotka do warstwy niżej.

Czytaj dalej

Bazy danych skazane na rozproszenie

W czasach dzisiejszych, gdy biznesy często są globalne a działalność operacyjna większości przedsiębiorstw opiera się na systemy informatyczne, pojawiają się problemy z dostępnością danych czy serwisu ogółem. Zcentralizowane systemy jak najbardziej zdają egzaminy w większości przypadków, da się bez problemu używać z systemu uruchomionego w Europie będąc fizycznie w Australii czy na Hawajach, ale doświadczenie klientów z takimi systemami może być oceniane średnio – głównie za sprawą niskiej wydajności sieci. Choć o tzw latency rzędu maks 2s-3s można było kiedyś tylko pomarzyć – pamiętam jeszcze czasy dial-up i te długie minuty buforyzowania filmiku na youtube, – ale w dziś takie czasy odpowiedzi już są uznawane za mauvais ton.

Inżynierowie systemów informatycznych borykają się z problemamy wydajnościowymi chyba od udostępnienia pierwszych publicznych serwisów, czy to bankowych systemów transakcyjnych czy zwykłej strony internetowej. Często dla rzadko zmieniających się danych stosuje się cache, czy to na CDN, czy w web serwerze czy jakiś Redis lub podobny. Takie cache są ok, aż do momentu jak dane zaczną się zmieniać tak często że koszt aktualizacji cache jest większy od round-tripa do instancji bazy.

Czytaj dalej

Dokumentacja i skutki ślepej wiary w nią

21 kwietnia 2021 roku, 00:40, minęła właśnie chyba druga godzina jak ja probuję zmusić funkcję lambda do wykonania się przez notyfikację topica SNSa. Niby trywialne zadanie i dokumentacja Serverlessa ma opisany ten use case:

functions:
  dispatcher:
    handler: dispatcher.dispatch
    events:
      - sns:
          arn: !Ref SuperTopic
          topicName: MyCustomTopic

resources:
  Resources:
    SuperTopic:
      Type: AWS::SNS::Topic
      Properties:
        TopicName: MyCustomTopic

Ale, niestety to nie dzialą. Metodą prób i błędów doszedłem do wniosku, że owszem ten events - sns działa, ale tylko jeśli zdefiniujemy tam nowy topic SNS. Jak wskazujemy jeszcze nieistniejący topic, to Serverless wypluwa do CloudFormation następujące instrukcje:

Czytaj dalej

Dzięki za pamięć

Strach pomyśleć, że w czasach powszechnych Garbage Collectorów czy to w .NET-cie czy innej Javie, są jeszcze programiści którzy ręcznie zarządzają pamięcią 😱. Ale nawet, mając pod ręką wspaniałego pomocnika, jakim jest GC, nie warto zapominać, jak CLR zarządza pamięcią i warto wiedzieć kilka tricków jak można optymalizować działanie programu w tej czy innej sytuacji.

Czytaj dalej

Kiedy wybieram AWS DynamoDB, zaczynam liczyć bajty

Tak jest. Maksymalny rozmiar wpisu w tabeli DynamoDB wynosi 400KB, jak wskazuje oficjalna dokumentacja. Natomiast, oficjalna dokumentacja nie wspomina o metodzie wyliczania rozmiaru wpisu.

Otóż, na końcowy rozmiar wpisu w tabeli DynamoDB składa się: rozmiar nazwy atrybutu zakodowane w utf-8 (w większości przypadków będzie to 1 bajt per symbol) oraz rozmiar wartości atrybutu. Rozmiar wartości atrybutu zależy od typu danych wykorzystanych, np. jeśli jest to zwykły string to rozmiarem wartości będzie wartość zakodowana w UTF-8 (od 1 do 4 bajtów na symbol). Jeśli natomiast będzie to Map (objekt w plain JSON), to trzeba doliczyć jeszcze 3 bajty (const) oraz po 1 bajcie na każdą parę klucz-wartość, no i rozmar samych par klucz-wartość też trzeba policzyć – w wyniku tego, nawet pusta mapa będzie miała co najmniej 3 bajty.

400KB to jest wystarczajćo dla mniejszych dokumentów, natomiast kiedy dokumenty przechowywane w DynamoDB są generowane na podstawie danych wprowadzonych przez użytkowników, to trzeba liczyć się z tym, że prędziej czy później dostaniemy błąd

An error occurred (ValidationException) when calling the PutItem operation: Item size has exceeded the maximum allowed size
Czytaj dalej

Kryptografia symetryczna i asymetryczna

Coraz częściej słychać w świecie o wymagalności szyfrowania danych, czy to danych osobistych użytkowników systemów informatycznych, czy to bezpiecznego przesyłania informacji pomiędzy systemami informatycznymi. Dlatego w tej skromnej publikacji chciałbym omówić jakie są główne różnice kryptografii symetrycznej i asymetrycznej oraz jak można używać obu do implementacji najbezpieczniejszej komunikacji.

Zacznijmy od podstaw, a dokładnie – jak działają algorytmu kryptografii symetrycznej i asymetrycznej.

Czytaj dalej

Optymalizacja implementacji `Insert or Update` zapytań na bazie danych

Proszę Państwa, czasem jest potrzeba zrobić coś a’la Insert or Update. Zadanie jest dość trywialne, ale nie zawsze optymalne zarówno pod względem czasu implementacji jak i czasu wykonania – pierwsze co wpada do głowy, to implementacja czterech kroków:

  1. Wyciągnij wpisy z tabeli które spełniają wymagania
  2. Sprawdź czy wynik poprzedniego zapytania jest pusty
  3. Jeśli odpowiedź jest pozytywna – wykonaj UPDATE
  4. W przeciwnym razie wykonaj INSERT

W takich sytuacjach bardzo się przydaje zgłębienie wiedzy w narzędziach i zapytaniach wychodzących poza zakres ANSI SQL np. Transact-SQL (MS Sql Server) lub PL/pgSQL (Postgres). Oba te wyżej wspomniane języki mają cudowne narzędzie umożliwiające wykonanie całej roboty InsertOrUpdate za jednym zapytaniem – tzw UPSERT.

Nazwa pochodzi od połączenia dwóch słów – UPDATE oraz INSERT. Założenie takiej kwerendy jest proste – spróbuj wstawić nowy rekord do tabeli, i w przypadku pojawienia się błędu o duplikacje, zrób update.

Czytaj dalej

Uruchomienie JIRA Software w Dockerze

Jako że jestem wielbicielem kontenerków, pamiętam jeszcze dzieciakiem miałem styczność z kontenerami na moim starym Siemens A55 albo Siemens A60 – nie pamiętam już ?; postanowiłem sobie przenieść swą instancję JIRA Software z dedykowanego EC2 hosta do dockera.

Zacznijmy od tego że potrzebujemy Oracle JRE do uruchomienia tego wspaniałego oprogramowania, a jak wiadomo Oracle lubi utrudniać życie innym przez wprowadzenie zakazu dystrubucji JRE – chodzi o to że nie można zrobić skrypt który automatycznie pobierze i zainstaluje JRE w kontenerze, ale można bez problemu wejść na stronę Oracle i ściągnąć JDK nie naruszając licencji. Chodzą plotki, że JIRA już wpiera OpenJDK – ale oficjalnie od wersji 7.13, natomiast ja posiadam licencję na wersję ciut starszą – 7.12, niestety ?

Czytaj dalej

Indeksowanie kolumny typu NVARCHAR(MAX)

Bardzo rzadko piszę tutaj, jest to spowodowane tym że jestem leniwym, ale dziś zwalczyłem leń i przekazuję do użytku publicznego prostą receptę na indeksowanie kolumny typu NVARCHAR(MAX).

Ostatnio zderzyłem się z wydajnością jednej z procedur składowanej (ang. stored procedure), a mianowicie – łączenie tabeli z inną tabelą po kolumnie tupy NVARCHAR(MAX) daje bardzo słabą wydajność prz >1k rekordów w tabeli. Teraz każdy może powiedzieć – no panie, wiadomo że trzeba założyć indeksy ? Czytaj dalej