https://visualhunt.com/photo/190380/

Heroku i zmiana bazy danych

Dzisiejszy wpis, choć dotyczy projektu na DSP2017, nie jest do końca związany z czystym kodowaniem. Będzie o platformie Heroku oraz konieczności zmiany bazy danych. Ale po kolei, co udało mi się zrobić przez ostatnie 2-3 dni.

Przede wszystkim wykonałem rozpoznanie w zakresie platformy Heroku, czyli chmury działającej w modelu PaaS (Platform as a Service). Jest to taka usługa, która udostępnia programiście wirtualne środowisko pracy, czyli zwalnia go z konieczności przygotowania całej infrastruktury, pozwalającej na wdrożenie jego aplikacji. Choć nigdy wcześniej nie miałem przyjemności pracować z taką platformą, stwierdziłem, że jest to właśnie to, czego szukam. Wybór Heroku padł już na samym początku, podczas opisywania założeń mojego projektu. Był on podyktowany głównie tym, że aplikacje napisane z wykorzystaniem Play Framework są wspierane akurat przez tą platformę. Pomyślałem, że to proste rozwiązanie, które nie zabierze mi czasu na pisanie kodu aplikacji, więc lepiej być nie może.

Ruby, Java, PHP, Python, Go, Scala, Clojure, Node.js
Ruby, Java, PHP, Python, Go, Scala, Clojure, Node.js

Co prawda nie mam porównania do innych usługodawców, ale Heroku daje wsparcie całkiem dużej ilości języków programowania. Co dla mnie istotne na etapie prototypowania, dostępny jest darmowy wariant usługi, oczywiście z mocnymi ograniczeniami. W planie darmowym największym obostrzeniem jest chyba uśpienie usługi po czasie 30 minut bezczynności oraz ograniczona do 450 liczba możliwych godzin pracy (?) (dyno hours) przypisanych do jednego konta (liczbę dyno hours możemy zwiększyć do 1000, jeśli zarejestrujemy kartę kredytową). Z pakietu Free może korzystać tylko jeden członek zespołu, jednak wszystko powyższe nie powinno być problemem w moim skromnym projekcie.

Różne pakiety Heroku
Różne pakiety Heroku

Z istotnych zalet Heroku pod względem wdrażania aplikacji opartych o Play Framework jest bardzo prosty proces instalacji na platformie (wykorzystujący system kontroli wersji GIT), dodatkowo opisany bardzo czytelną dokumentacją. Koniecznym okazało się zainstalowanie Command Line Interface (CLI), a następnie zalogowanie do usługi z wykorzystaniem swojego konta. W kolejnym kroku wykonałem polecenie heroku create rpihomecontroller, które utworzyło aplikację o wybranej przeze mnie nazwie oraz przypisało zdalne repozytorium.

maciek@z510:~/NetBeansProjects/HomeController$ git remote -v
heroku	https://git.heroku.com/rpihomecontroller.git (fetch)
heroku	https://git.heroku.com/rpihomecontroller.git (push)
origin	https://github.com/maciejstepniak/HomeController.git (fetch)
origin	https://github.com/maciejstepniak/HomeController.git (push)

Od tej pory każde wdrożenie to nic innego niż wykonanie operacji push do tego zdalnego repozytorium. W moim przypadku struktura katalogów na GitHub wygląda inaczej niż standardowo – aplikacja webowa Play jest w podkatalogu WebApp względem katalogu głównego repozytorium. W związku z tym standardowe polecenie wypychające gałąź master (git push heroku master) nie wdrażało poprawnie aplikacji. Problem został rozwiązany przez wykonanie poniższego polecenia.

git subtree push --prefix WebApp heroku master

Heroku udostępnia również bazę danych, również w planie darmowym (z ograniczeniem do 10 000 wierszy), jednak nie jest to MySQL, którego ślepo założyłem. Jest za to PostgreSQL, w którym miałem okazję eksperymentować na studiach. Nie jest źle, po prostu trzeba było zrobić migrację, co nie stanowiło dużego problemu na tym etapie projektu.

Prawdę mówiąc, na późniejszym etapie również nie byłoby większych problemów z bazą danych. Po stronie aplikacji webowej mam zamiar korzystać z warstwy danych, mapowania ORM oraz unikać natywnych zapytań, co bardzo dobrze uniezależnia mnie od wyboru silnika. Z kolei w oprogramowaniu na Raspberry Pi (Python) wykorzystałem również mapowanie za pomocą SQLAlchemy. Tutaj konieczne były na prawdę minimalne zmiany, a konkretnie zainstalowanie modułu py-postgresql oraz utworzenie nowej klasy z danymi połączeniowymi (PostgresConnectionData) wykorzystywanymi w skryptach db_declarative.py oraz db_insert.py. Oczywiście konieczne było również zainstalowanie samego PostgreSQL lokalnie do testów oraz utworzenie bazy danych homecontroller i użytkownika o takiej samej nazwie. Niestety pgAdmin III, będący graficzną nakładką na silnik bazodanowy, nie jest dla mnie tak wygodny jak MySQL Workbench, w związku z czym wolę pracować w terminalu.

Zamieszczam krótką ściągawkę składni, która przydała mi się podczas obsługi PostgreSQL.

Zalogowanie użytkownika postgres do konsoli bazy danych homecontroller:

sudo -u postgres psql homecontroller

Czyszczenie ekranu:

homecontroller=# \! clear

Wyświetlenie listy istniejących tabel:

homecontroller=# \dt
                   List of relations
 Schema |         Name         | Type  |     Owner      
--------+----------------------+-------+----------------
 public | element_output_state | table | homecontroller
 public | measurement          | table | homecontroller
 public | play_evolutions      | table | homecontroller
 public | room                 | table | homecontroller
 public | sensor               | table | homecontroller
 public | sensor_type          | table | homecontroller

W tym miejscu warto wspomnieć, że tabela play_evolutions jest miejscem, gdzie przechowywane są zmiany struktury tabel, spowodowane zmianą modelu po stronie Play Framework.

Sprawdzenie struktury wybranej tabeli:

homecontroller=# \d+ sensor
                                                       Table "public.sensor"
   Column    |          Type          |                      Modifiers                      | Storage  | Stats target | Description 
-------------+------------------------+-----------------------------------------------------+----------+--------------+-------------
 id          | integer                | not null default nextval('sensor_id_seq'::regclass) | plain    |              | 
 type_id     | integer                |                                                     | plain    |              | 
 room_id     | integer                |                                                     | plain    |              | 
 position_x  | integer                |                                                     | plain    |              | 
 position_y  | integer                |                                                     | plain    |              | 
 description | character varying(255) |                                                     | extended |              | 
Indexes:
    "pk_sensor" PRIMARY KEY, btree (id)
    "ix_sensor_room_id" btree (room_id)
    "ix_sensor_type_id" btree (type_id)
Foreign-key constraints:
    "fk_sensor_room_id" FOREIGN KEY (room_id) REFERENCES room(id) ON UPDATE RESTRICT ON DELETE RESTRICT
    "fk_sensor_type_id" FOREIGN KEY (type_id) REFERENCES sensor_type(id) ON UPDATE RESTRICT ON DELETE RESTRICT

Wyjście z konsoli do terminalu systemu:

homecontroller=# \q

Dzisiejszy wpis może nie był górnych lotów, ale już w następnym pojawi się trochę więcej kodowania. Będzie o dostępie do bazy danych z aplikacji Play, z wykorzystaniem Ebean ORM. Serdecznie zapraszam!

Literatura obowiązkowa:

Getting Started on Heroku
PostgreSQL 9.5.6 Documentation

2 thoughts to “Heroku i zmiana bazy danych”

  1. Oprócz py-postgresql można jeszcze wykorzystywać py-odbc. Do prostych zapytań powinno wystarczyć, a jest niezależny od silnika bazodanowego. Wydaje mi się, ze jedyna różnicą był ConnectionString.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *