W prywatnym projekcie, nad którym pracuje, do wyszukiwania kursów będę korzystać narzędzia Elasticsearch. Ponieważ potrzebuje lepiej poznać to narzędzie, postanowiłem udokumentować kilka kroków z mojej podróży, aby dzielić się wiedzą, a jednocześnie liczę, że przyda się to także innym.
Zamierzam korzystać z instalacji opartej o Docker i poniży wpis jest właśnie taką uproszczoną instrukcją jak tego dokonać.
Docker
Używam Docker, aby to uruchomić Elasticsearch, z racji tego ze Docker desktop rozpoczął zarabianie pieniędzy na swoim narzędziu, a ja, póki co nie chce im płacić i przesiadłem się na rancher desktop, darmowa wersje dockera. Którą można zainstalować przez windowsowa wersje choco, a mianowicie winget, taką oto komendą:
Błąd: error during connect: this error may indicate that the docker daemon is not running: Get “http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/containers/json”: open //./pipe/docker_engine: The system cannot find the file specified.
Rozwiązuje się wcześniejszym uruchomieniem serwisu rancher desktop, wybieram opcje bez kubernetes oraz hostowanie domyślne `dockerd`
Teraz się skup, bo będzie ważne, po pierwszym uruchomieniu Elasticsearch wyświetlone zostaną ważne informacje:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Elasticsearch security features have been automatically configured! Authentication is enabled and cluster connections are encrypted.
Password for the elastic user (reset with `bin/elasticsearch-reset-password -u elastic`): xHfUR+xSz7-yhFJ1uXie
HTTP CA certificate SHA-256 fingerprint:
a8c9d16a2c7317da8f115ad6d2e02a843b7fbcbc6a7160e80ce464b9b313654d
Configure Kibana to use this cluster:
• Run Kibana and click the configuration link in the terminal when Kibana starts.
• Copy the following enrollment token and paste it into Kibana in your browser (valid for the next 30 minutes):
eyJ2ZXIiOiI4LjEyLjIiLCJhZHIiOlsiMTcyLjE3LjAuMjo5MjAwIl0sImZnciI6ImE4YzlkMTZhMmM3MzE3ZGE4ZjExNWFkNmQyZTAyYTg0M2I3ZmJjYmM2YTcxNjBlODBjZTQ2NGI5YjMxMzY1NGQiLCJrZXkiOiJISFg4Q280QmhUaWFaVHZKVW1Wejpnam9VVF9aVlFjZXAzeDRsV3BrS1R3In0=
Configure other nodes to join this cluster:
• Copy the following enrollment token and start new Elasticsearch nodes with `bin/elasticsearch –enrollment-token <token>` (valid for the next 30 minutes):
eyJ2ZXIiOiI4LjEyLjIiLCJhZHIiOlsiMTcyLjE3LjAuMjo5MjAwIl0sImZnciI6ImE4YzlkMTZhMmM3MzE3ZGE4ZjExNWFkNmQyZTAyYTg0M2I3ZmJjYmM2YTcxNjBlODBjZTQ2NGI5YjMxMzY1NGQiLCJrZXkiOiJIWFg4Q280QmhUaWFaVHZKVW1WejpOZ25XNXJ3OVJOR3E5NEZrcG1DZGV3In0=
If you’re running in Docker, copy the enrollment token and run:
`docker run -e “ENROLLMENT_TOKEN=<token>” docker.elastic.co/elasticsearch/elasticsearch:8.12.2`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Jeśli z jakiegoś powodu zgubisz lub będziesz chciał zmienić hasło dla użytkownika, na spokojnie robisz to tak:
Pracując z Entity Framework możemy doceniać jego moc oraz zapomnieć o tym, jaką potężną magią on operuje. Np. skąd ten diabeł wie, co się zmieniło, a kiedy muszę mu o tym przypomnieć.
Mam prostą regułę w głowie, jeśli wyciągam dane z kontekstu i zaraz od razu wrzucam je tam z powrotem, nie ustawiam do tego flag, nie wtrącam się, nie robię hokus-pokus i zakładam, że wszystko będzie dobrze.
Jeśli wyciągam dane na dłużej, wtedy podpowiadam EF, żeby nie śledził zmian, bo to trochę zajmie, zanim te dane wrócą do bazy danych i szkoda zachodu.
Dane można zapisać / zaktualizować na kilka sposobów:
Na raz:
Pobierz
Zmodyfikuj
Zapisz
Na dwa
Utwórz
Przypnij
Zapisz
Na trzy:
Nie zaglądam, jeśli działa u Ciebie to dawaj dawaj na produkcje
Wygląda że proste? To sprawdzam, co i jak zadziała
W obu przypadkach mam taki oto kod:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Nie oszukujmy się, bunkrów nie ma, kontekst oraz jakiś POCO na potrzeby przykładów.
Uno
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Ten przykład działa, pobieram, modyfikuje, zapisuje. EF robi magię i potrafi sam wykryć zmianę w encji – nie wymaga wywołania `update` aby znaleźć i nanieść zmiany na obiekcie. PFM! Wymagany jest natomiast strzał do bazy aby pobrać początkowy obiekt do modyfikacji. Na plus – nie tracę informacji, który nie modyfikuje. Wrócę do tego niżej.
Duo(s)
Teraz się zacznie, co się stanie, gdy wyciągnę dane bez śledzenia i zapiszę zamiany:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Pudło! Nic, EF cichutko “zapisał” zmienione encje, ale mój odcięty obiekt nie był na tej liście, w związku z tym – nic się nie wydarzyło. Może tylko odrobina smutku. Ale sam tego chciałem, przecież mówiłem – bez śledzenia!
Spróbuje inaczej, stworze nowy obiekt, przypnę go do kontekstu i wtedy zapisze:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Hus! (Dzięki panie Łukaszu) – nie działa! Ale czemu? Przecież obiekt jest w kontekście!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Ach, obiekt został dodany, ale jest oznaczony jako unchanged! Ok-sprawdzam:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Czyli co, nawet jeśli mam nowy obiekt i przypiąłem go do kontekstu nadal nie jest śledzony? Nie koniecznie, obiekt został przypięty i jest śledzony, ale zmiany nie nastąpiły po włączeniu śledzenia. Natomiast taki kod:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Robi już robotę, zwróć uwagę, że zmiany następują po przypięci i włączeniu śledzenia zmian
Zamiast takiego cyrkolenia się, można iść na skróty i wywołać po prostu Update:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Który ustawia status obiektu na modified i zapisuje zmiany.
Turbo mega uwaga:
Oba przypadku zerują wartość dla ReleaseDate który dostanie domyślną 01.01.0001 00:00:00 wartość-trzeba tego pilnować. W przypadku gdy wcześniej ładujemy obiekt z DB a potem go modyfikujemy, ReleaseDate jest ustawiony i nie nadpisany zerową wartością.
Pewnie można by poszukać i podpowiedzieć, które właściwości zostały zmienione, ale to wymagałoby znajomości voodoo.
Dodam tylko dla optymalizacji, że gdy wyciągamy obiekt z EF, który nie będzie zmieniany, np. tylko żeby wyciągnąć i wyświetlić, warto użyć opcji ` AsNoTracking, aby podpowiedzieć EF zaprzestania śledzenia obiektów, bo zniknąć one z naszego kontekstu.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Nie lubię logowania — brudzi mi w kodzie; narzekam, gdy podczas ratowania produkcji brak logów — jak żyć?!
Jestem leniwy, nie lubię pamiętać o tym i tamtym — lubię, gdy rzeczy dzieją się same i nie muszę sobie zawracać tym głowy. Ale bez przesady! Logi to najgorsze i najlepsze co może spotkać programistów — z jednej strony logi zaśmiecają kod, z drugiej strony dają podgląd na to, co użytkownicy wymyślili na produkcji.
AOP
Logowanie przy pomocy AOP oczyszcza kod w przypadku typowego i klasycznego podejścia do logów, ok — może to zrobić. Często szukam w logach tego, co zostało uruchomione i z jakim parametrem, aby zrozumieć, co poszło nie tak. Nie lubię ^C^V takiego kodu na początku każdej metody. Niestety nie znalazłem dobrego rozwiązania AOP (czytaj darmowego) a interfejs IIntercept z jakiegoś powodu nie chce zostać uruchomiony (ale jest tworzony — kiedyś to zrozumiem); z tego powodu przy pomocy internetów znalazłem DispatchProxy które świetnie robi swoją robotę.
DispatchProxy
Otóż chciałbym mieć możliwość logowania tego, co i jak się wywołuje z możliwością włączenia / wyłączenia detali (poziomy logowania w moim przypadku, lub inna forma konfiguracji). Chce móc przeczytać logi i dowiedzieć się co się wywołuje i z jakim parametrami, dla każdej metody, dodatkowo bez potrzeby modyfikacji kodu, gdy dana metoda się zmieni.
Można to zrobić przy pomocy DispatchProxy które przechwyci wywołanie metody i umożliwi wykonanie dowolnego kodu; przed; po czy też podczas błędu.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Otóż taka klasa opina ładnie swoją docelową klasę T , a następnie podczas tworzenia zwraca takie proxy, udając klasę typu podstawowego. Tutaj uwaga: konstruktor musi być pusty, a ewentualne przekazanie parametrów i ich przypisanie następuje w metody fabrykującej (wewnątrz if)
Gdy użytkownik takiej klasy wywołuje metodę docelową, na proxy wcześniej zostanie zawołane Invoke gdzie można czynić cuda.
Ja na przykład na poziomie `Information` loguje nazwę wywoływanej metody, a na poziomie Debug dorzucam także nazwy i wartości przekazanych argumentów.
Rejestracja
Piękne jest to, że DispatchProxy nie wymaga zewnętrznych bibliotek i działa na czysto z .net. Zależność do klasy rejestruje w taki sposób:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Tutaj przykład konsumpcji oraz wykorzystania przykładowego serwisu
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Serwis jest nudny do bólu i prawie o nim zapomniałem:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
W tak przygotowanym kodzie, zależności rejestrowane z pomocą logera powinny samodzielnie wrzucać informację o tym, co i jak się wykonało. Oczywiście można dodać sobie flagi do optymalizacji tego, czy przed, czy po co w sytuacjach wyjątkowych ma się logować i na jakim poziomie. Warto także pomyśleć o tym, jak takie logi ze sobą łączyć za pomocy correlationId – ale to pozostawiam już waszej wyobraźni.
Tylko w ruscie, jak się skompilowało to można na proda wrzucać
Integrować się chce
No ale ale, chce napisać, że marzy mi się taka sytuacja, że mogę sobie odpalić i szybko przetestować cały kod (prawie cały) od wejścia do zapisu. Większość rzeczy, z którymi pracuje, albo zaczyna się na http, albo kończy się na http, a ja nie chce nigdzie strzelać, chce to zaślepić i mieć pod kontrolą — jak?!
To nie pierwszy raz, kiedy marudzę, nie pierwszy raz, kiedy na Twitterze i nie pierwszy raz o tym, że komentarze na temat spacji, wcięć, klamerek i całej serii białych znaków to czyste ?
Ile jeszcze? Otóż dorosłem ? i chce coś z tym zrobić. Można na różne sposoby, ja wybrałem .editorconfig– bo jest wspierany z pudełka przez większość edytorów
Oczywiście moje życie mówi sprawdzam! i jest trochę inaczej, ale ostatecznie można to ogarnąć.