# Specyfikacja behawioralna (??)
## Symbole
*m* - maksymalny rozmiar koła (teoretyczna maksmymalna ilość Managerów)
*r* - ilość następników którzy przechowują kopię danych zadanego Managera
*S* - maksymalna liczba Sesji - *30.000*? (czy taka liczba sesji w ciągu 8 godzin oznacza że możemy mieć tyle sesji jednocześnie?)
*M* - maksymalna liczba Managerów - *100*
*n* - numer Managera w kole - Manager o numerze *n* może nie istnieć
*T* - maksymalne obciążenia Node-u z Maszyną Stanową, powyżej którego nie tworzymy już na nim nowych Sesji
## Zdarzenia, jeśli założymy pełny mesh (każdy Manager ma pełną informację o innych Managerach)
#### Klient wysyła zapytanie o nową sesję do Managera
Mamy Managera *x*, który dostaje ID Sesji *y*.
Wyliczamy *n = hash(y) % m*
Wyszukujemy Managera *x'*, którego ma wartość *n* lub jest pierwszym o wartości większej od *n*
Robimy co następuje:
**a.1** jeśli *x'* jest dostępny:
wysyłamy zapytanie o nową sesję
zwracamy rezultat - adres IP node'a lub błąd
**a.2** jeśli *x'* jest niedostępny:
wysyłamy zapytanie do któregoś z jego sąsiadów - odpowiednio duży parametr *r* gwarantuje nam że któryś z nich będzie dostępny
**a.2.1** jeśli sesja *y* już istnieje:
zwracamy rezultat - adres IP node'a
**a.2.2** jeśli sesja *y* jest w trakcie tworzenia:
zwracamy rezultat - adres IP node'a
**a.2.3** jeśli sesja *y* jeszcze nie istnieje:
wysyłamy zapytanie o nową sesję do pierwszego aktywnego następnika
zwracamy rezultat - adres IP node'a lub błąd
Całość sprowadza się do tego, że sesja zostanie utworzona tam gdzie ma być lub w pierwszym dostępnym następniku.
Jeśli w którymkolwiek wypadku nie dostaniemy odpowiedzi, odświeżamy informację o dostępnych Managerach i powtarzamy proces.
#### Manager wysyła zapytanie o nową sesję do innego Managera
Mamy Managera x, który dostaje ID Sesji *y*.
Robimy co następuje:
spośród dostępnych Node-ów wybieramy ten najbardziej obciążony, ale wciąż poniżej zadanego progu *T*
jeśli żaden nie spełnia kryterium, provisionujemy nowy Node
informujemy *r* następników (tylko te dostępne) że utworzymy Sesję *y* pod wybranym adresem
gdy wszystkie potwierdzą odbiór informacji (lub będziemy mieli timeout), to wysyłamy żądanie utworzenia Sesji do Node-a
**a.1** jeśli mamy błąd:
wysyłamy do *r* następników informację że nie udało się utworzyć sesji
zwracamy błąd
**a.1** jeśli się udało:
wysyłamy do *r* następników informację że udało się utworzyć sesję
zwracamy adres IP
#### Klient wysyła żądanie zamknięcia sesji do Managera
Mamy Managera *x*, który dostaje ID Sesji *y*.
Wyliczamy *n = hash(y) % m*
Wyszukujemy Managera *x'*, którego ma wartość *n* lub jest pierwszym o wartości większej od *n*
Robimy co następuje:
**a.1** jeśli *x'* jest dostępny:
wysyłamy żądanie o zamknięcie sesji
**a.1.1** dostaniemy OK:
zwracamy OK
**a.1.2** dostaniemy błąd lub nie dostaniemy odpowiedzi:
zwracamy błąd
**a.2** jeśli *x'* nie jest dostępny:
zwracamy błąd
#### Manager wysyła żądanie zamknięcia sesji do innego Managera
Mamy Managera *x*, który dostaje ID Sesji *y*, znajdującej się na Maszynie Stanowej *ms*.
Robimy co następuje:
**a.1** jeśli Sesja *y* należy do nas (została oryginalnie utworzona przez Managera *x*):
wysyłamy żądanie do *ms*
**a.1.1** jeśli *ms* zwróci OK:
zwracamy OK
**a.1.2** jeśli *ms* zwróci błąd lub jest niedostępna:
zwracamy błąd
**a.2** jeśli Sesja *y* nie należy do nas (została oryginalnie utworzona przez Managera *x'*):
przekazujemy to żądanie do *x'*
**a.2.1** jeśli *x'* zwróci OK:
zwracamy OK
**a.2.2** jeśli *x'* nie jest dostępny lub zwróci błąd:
zwracamy błąd
Jeśli Manager *x* ma numer odpowiadający *n*, ale nie jest twórcą Sesji, to możliwy jest maksymalnie jeden skok, ponieważ ma on informację o stwórcy i ta nie może się zmienić
#### W sieci pojawia się nowy Manager *m* (nie ma znaczenia czy po awarii czy jako nowy narybek)
Co musi się stać?
- *m* dostaje od swojego następnika wszystkie sesje, które mają być jego
- *m* dostaje kopię danych z *r* poprzedników
- wszystkie przeniesione sesje muszą zostać usunięte z *r-tego* następnika następnika *m* xD (czyli jeśli np. mamy *r=3*, to jeśli utworzyliśmy nowego Managera, który dostał 5 Sesji, to te 5 Sesji musi zostać usunięte z Managera odległego o 4 miejsca od niego)
- wszyscy muszą dowiedzieć się o *m* - poznać jego wartość *n* oraz adres IP
- *m* musi się dowiedzieć o wszystkich - poznać ich wartość *n* oraz adres IP
Założenia:
- **uproszczenie**: w systemie może jednocześnie być dodawany / przywracany jeden Manager; nie możemy dodać nowego, dopóki cały proces się nie skończy (wszystkie klucze poprzenoszone, wszyscy poinformowani, itd.)
- każdy manager ma zarezerwowany numer *n* - nawet, jeśli padnie, ten numer zostanie dalej przypisany do niego, bo zakładamy, że każdy manager w końcu zostanie przywrócony do życia
- skąd wiemy że ktoś padł? Mamy naszego Consula (usługę Service Discovery), do którego wszyscy zgłaszają się co kilka sekund - jeśli ktoś wypadnie z zabawy, Consul odpali określony skrypt, który wyśle do każdego Managera informację, że niedostępny Manager zniknął; następnie wyślemy request o odtworzeniu tego Managera na nowym komputerze;
- gdy Manager jest już odpalony, to jeszcze nie jest w sieci - aby go do niej dodać, wysyłamy do niego request z 2 parametrami - jego *n* oraz adres jego następnika; od następnika dostanie on wszystkie inne adresy, do których wyśle informację o swoim istnieniu. co jeśli któryś wtedy nie jest dostępny? nie ma problemu, po prostu po powrocie jego następnik wszystko mu powie :) nie potrzebujemy więc dodatkowego mechanizmu stabilizacji (mile widziane udowodnienie mi że się mylę)
- w trakcie przenoszenia kluczy, jeśli pojawi się zapytanie o nową sesję, to możemy sprawdzić czy jest ona w następniku (jeszcze nie przeniesiona), jeśli jej nie ma to tworzymy normalnie; jak to zrobić - patrz następny punkt
- co jeśli coś się zepsuje w trakcie przenoszenia? po to mamy *r* kopii, ale zakładam że Chord (lub inny algorytm) opisuje nam dokładnie jak się obchodzić w takiej sytuacji
Wnioski:
- mam wrażenie (z tego co opisałem), że podczas tworzenia/przywracania Managera cały system będzie działał poprawnie - pozostaje nam sprawdzić ile takie tworzenie zajmuje czasu i czy nie pominąłem w rozważaniach jakiegoś kroku, który może się zepsuć