Ograniczony dostęp do widoku

Szukam najlepszego sposobu rozwiązania pewnego przypadku.

W aplikacji którą piszę muszę zaimplementować blokadę dostępu do jednego widoku. Blokada o tyle ma być nietypowa, że ma pozwalać na to aby tylko jeden użytkownik mógł w tym samym czasie oglądać ten widok (widok show dla konkretnego obiektu). Tak więc jeżeli któryś z użytkowników otworzy sobie podgląd tego obiektu to inny użytkownik podczas próby dostępu będzie musiał zobaczyć stosowny komunikat. Blokada ma być podtrzymywana do momentu aż użytkownik opuści ten widok (zamknie przeglądarkę, kartę w przeglądarce, twardy restart itp.).

Na chwilę obecną przychodzą mi do głowy dwa rozwiązania tego problemu.

  1. w widoku osadzam ajaxowy request (async) który co kilka sekund podbija blokadę obiektu w bazie danych. Po opuszczeniu widoku przestaną się wysyłać requesty i po kilku sec blokada ustąpi.
  2. jak ktoś otworzy widok wysłany zostanie request blokujący obiekt. W momencie opuszczenia widoku wysłany zostanie kolejny request przy pomocy metody w jquery onbeforeunload. Minusem tego rozwiązania będzie sytuacja w której nastąpi hardreset albo zawiesi się przeglądarka ponieważ nie odblokuje się wtedy dostęp do obiektu.

Macie jeszcze jakieś pomysły? Albo usprawnienia moich?

Kiedyś miałem podobne wymaganie, ale w aplikacji biurkowej. Stosowałem podobne rozwiązanie, jak proponujesz jako 1. Przed rozpoczęciem wyświetlania formularza sprawdzałem czy ustawiona jest kolumna z czasem blokady. Jeśli nie, formularz mógł być otwarty w trybie do edycji - w przeciwnym razie tylko do odczytu. W trybie edycji formularz, co minutę, aktualizował kolumnę blokady w edytowanym wierszu. Po zakończeniu edycji blokada była zdejmowana. Problem załamania systemu został rozwiązany w ten sposób, że warunkiem edycji był brak blokady lub blokada założona 70 sekund wcześniej (10 sekundowy margines).

Dodatkowo, poza czasem blokady, ustawiałem też identyfikator użytkownika, by było wiadomo kto blokuje dany rekord (co prawda rzadko, ale czasem może być przydatne).

Aplikacja działała od wielu lat i przynajmniej z tym mechanizmem nigdy nie było problemu.

Nie chcę się wymądrzać, gdyż nie znam specyfiki Twojej aplikacji, ani wymagań do niej, ale czy aby taka metoda nie jest formą powrotu do techniki blokowania pesymistycznego?
Ludzie zęby zjedli, by bazy danych blokować w trybie optymistycznym, po to właśnie by nie występowała sytuacja, że pani Zuzanna otwiera formularz edycji i idzie na tzw “szybką kawkę do pokoju obok”, a cała firma czeka i nikt nie może edytować tej pozycji, gdyż pani Zuzanna lock’a założyła na jego edycję.

Czyż nie jest lepszym rozwiązaniem pozwalać wszystkim wchodzić w tryb edycji, a ewentualnie dla akcji “zapisz” sprawdzić , czy aby dane nie zostały w tzw “międzyczasie” zmienione?

Powtarzam, że nie znam dokładnie wymogów Twojego programu, ale pachnie mi to trochę powrotem do …przeszłości.

@BSorbusMoże tutaj niestety wymaga tego specyfikacja.
Z aplikacji korzysta jednocześnie max kilka osób które siedzą obok siebie. Dwa razy dziennie muszę przeliterować listę obiektów i do każdego obiektu wykonać pewne czynności. Dzięki temu rozwiązaniu nie doprowadzimy do sytuacji że kilka osób pracuje nad tym samym obiektem.

Chyba że masz jakieś lepsze rozwiązanie tej sytuacji :smile: Wg. mnie blokowanie dostępu to jedyne odpowiednie rozwiązanie.

Pogadamy o tym, czy najlepsze, gdy pani pójdzie na lunch i …potrąci ją samochód. :slight_smile: :wink: :open_mouth:

U klienta firmie był kilka lat temu taki motyw:
Kilkanaście serwerów w sieci rozległej, rozproszonej po Polsce i kilkudziesięciu użytkowników.
Było to trochę w odległych czasach i użytkownicy “blokowali” tzw teczki, pobierając je na swoje laptopy, a po powrocie od klienta, wykonywali tzw “synchronizację teczek”.

Pani zablokowała kilkanaście pozycji i pojechała w teren.
Miała wypadek samochodowy i tzw “pesymistyczne zablokowanie” tych pozycji trwało klika dni, gdyż jej laptop uległ zniszczeniu, a nikt z firmy nie odważył się, by w bazie grzebać poleceniami SQL i w ten sposób usunąć blokady.

Oczywiście, skoro jest Was kilka osób, które dodatkowo siedzą obok siebie, to taki problem pewnie nigdy nie wystąpi, ale sama zasada “blokuję aż do odwołania” jest chyba “nieteges”.

Czy nie lepiej stosować:

  • “Inny użytkownik aktualnie edytuje tę pozycję. Czy też chcesz otworzyć ją w trybie edycji? [tak][Nie]”
    i później:
  • “Od czasu pobrania danych zostały one zmienione przez innego użytkownika.
    Naciśnij 1, by pobrać aktualne dane
    Naciśnij 2, by mimo wszystko zapisać.”

?

…Ale to tylko takie moje luźne uwagi. :smile:

Może.
Naszą rolą jest czasami wybić z głowy klienta, chory pomysł.

(nie mówię, że tak jest w tym przypadku, gdyż nie znam dokładnie ani specyfiki tego systemu, ani cyklu pracy użytkowników)

Przy okresowym odświeżaniu blokady taką sytuację da się wyeliminować.

Rozwiązanie konfliktów przy blokadach optymistycznych nie musi być wcale takie trywialne (szczególnie jeśli rekord zawiera rekordy podrzędne).

Oczywiście, zgadzam się z Tobą, że wcale to nie są banalne sprawy.

Odnoszę się jedynie do zasady “blokowania aż do odwołania”.

A ten “okres”, to jak się definiuje?
Po 1 minucie już można odblokować?
Nie?
Dopiero po 2-ch?
… to są śliskie sprawy takie “czasowe” zwalnianie blokad, szczególnie gdy ktoś telefon od żonki dostanie…albo nagłą sraczkę i musi zawiesić swoją pracę. :wink:

Tak, jak opisałem wyżej. Przykład z działającego systemu: odświeżanie blokady co 60s. Odblokowanie po 70. W środowisku sieci lokalnej tak dobrane wartości sprawdzały się bez problemu. Przy czym blokady miały swój osobny wątek, by utrzymać ten 60 sekundowy okres.

@Jacku

Nie mam zamiaru kwestionować tego, że to działało/działa i działać (jakoś) będzie nadal!

Sugeruję tylko, że takie rozwiązanie jest obarczone “grzechem pierworodnym”.

Mój ojciec jeździł kiedyś Syrenką i też przeważnie dojeżdżał cały do celu.
To, że z założenia działały tam nieprawidłowo hamulce, bo tłok pracował pod skosem, a nie równolegle do cylindra, to inna bajka :wink:
On wiedział o tym “grzechu pierworodnym” naszej myśli motoryzacyjnej i regularnie, raz w roku zmieniał uszczelki, ale nigdy nie mówił, że Sireno R-105 ma lepsze hamulce niż mercedes :slight_smile: :wink:

Z tym, że ja nie widzę tego grzechu pierworodnego. Blokady pesymistyczne są równoprawną metodą rozwiązywania problemu równoczesnego aktualizowania danych. Owszem mają swoje wady i wymagają przemyślanej implementacji, ale nie oznacza to, że nie powinno się ich stosować. Tym bardziej, że często użytkownicy optują za takim modelem współpracy z systemem, jako bardziej zrozumiałym.

To rozwiązanie było by ok ale w jego przypadku i tak musimy blokować dostęp lub dać dostęp tylko w trybie readonly.

Tu na szczęście sprawa sprawa jest w miarę prosta :smile:

Czyli najlepiej będzie chyba właśnie blokować dostęp na zasadzie jakiegoś timera. Zabezpieczyć to dając jakiś timeout jeżeli user przez dłuższy czas jest nieaktywny przed sytuacją “pójście na kawę”.
No i dać też możliwość podglądu obiektu w trybie ReadOnly.

Do realizacji tego to chyba jedynym wyjściem jest wysyłanie requestów ajaxowych które będą podbijały czas blokady w bazie danych, przy okazji zapisywały również kto blokuje dostęp. Jak user wyjdzie z podglądu, blokada się zwolni po kilku minutach/sekundach. Zablokowanie przed sytuacją z kawą można by zrobić na zasadzie takiej że jak user przez np 5 min jest bezczynny to go wywalamy z tego widoku :slight_smile:

Pół żartem, pół serio - ten problem mogą rozwiązać sobie użytkownicy we własnym zakresie, jeśli wyświetlisz im, kto właśnie edytuje dany rekord.

A w firmie już wprowadzono normy akordowe wprowadzania danych na czas, bo inaczej blokadka się zwolni i nie zdążysz zapisać danych?

Ciekawe, kiedy obetną normę z 60s do 50s…? :slight_smile: :wink:

OK.
Panowie, podkreślam, że nie znam wszystkich założeń tego systemu, to raz.
Dwa, to zostałem przekonany do
…hamulców z syrenki… :wink: :slight_smile:

:smiley: :smiley: :smiley:

Pół żartem, pół serio, czy nie jest to rozwiązanie polegające na informowaniu użytkownika o możliwych do podjęcia działaniach (edytuj pomimo tego, że ktoś wszedł już w ten tryb), zamiast uniemożliwiać mu to i zmuszać do grupowego przeszukiwania toalet, bo ktoś tam siedzi dłużej niż 5 min, a zostawił zablokowaną pozycję?

Reasumując:
Ja osobiście, zamiast budować rozwiązanie osobnego wątku ze zwalnianiem blokad po określonym czasie i “wyrzucaniem użytkownika z trybu edycji”, wolałbym poświęcić czas na zbudowanie rozwiązania informującego użytkowników, które pozycje “są na warsztacie” i pozwolić im na samodzielne podejmowanie decyzji, czy pomimo tej informacji chcą ją edytować.

A co do komplikacji w interfejsie, to zastanawiam się, czy czas poświęcony na rozwiązanie tego, nie byłby równoważny na tworzeniu modułu osobnego wątku zakładającego/przedłużającego/sprawdzającego blokady i obsługi tych informacji po stronie aplikacji klienta.

Podkreślam kolejny raz, że nie znam dokładnie wymagań stawianych systemowi i nie kwestionuję, że w małej sieci, dla małej liczby użytkowników, to się nawet sprawdza Wasze rozwiązanie…

Ale jaką normę? Jeśli użytkownik po 60 s nadal edytuje rekord, blokada jest zakładana na kolejne 60s. Jeśli zrezygnuje z edycji, blokada jest zdejmowana natychmiast. Jeśli załamie się jego system, po 70 sekundach rekord jest odblokowywany automatycznie.

W tym przypadku musisz użytkownikowi wyjaśnić, jak ma sobie rozwiązać konflikty, które w takiej sytuacji niechybnie wystąpią. Do tego dochodzą komplikacje w interfejsie, co nie zawsze musi być opłacalne, jeśli z systemu korzysta kilkanaście osób, a realne sytuacje konfliktowe występują raz na jakiś czas.

Na koniec ważne zastrzeżenie: zakładam, że wątek dotyczy właśnie takiego małego systemu, z kilkunastoma użytkownikami.

A może w tym czasie odebrać ważny telefon lub iść do szefa, czy jednak po rozmowie z żonką, zapisaniu na kartce listy zakupów, godziny odbioru dziecka z przedszkola… lub powrocie od szefa zobaczy okno:
“Sorry Stary, ale minęło Twoje 60 sekund na edycję tej pozycji.
Zmiany nie zostały zapisane, więc zacznij od nowa”?

Edit:
Czy użytkownik może “nie rezygnować z edycji” i wyjść na zakupy?
System chyba nie będzie w stanie “crash” i nikt inny nie będzie mógł w tym czasie nic z taką pozycją zrobić do czasu…aż panna Zuzanna powróci i zapisze lub “zrezygnuje z edycji”?

Tutaj na szczęście nie będzie potrzeby wprowadzania jakiś wielu zmian. Możemy sobie założyć że owym obiektem będzie jakieś “zgłoszenie” a pracownik nad nim pracuje ~ 15min na koniec pracy z nim po prostu je zamyka bądź dodaje jakiś komentarz. Może epiej to zobrazuje problem :slight_smile:

Więc jeżeli system kogoś wywali to nic on nie straci. Co najwyżej może ktoś za niego odwali robotę bo ktoś inny zajmie się tym.

Rozumiem, że nie “robimy zagadnienia”, gdy w 14-ej minucie musi wyjść do szefa i te 14 minut jego pracy pójdzie się walić.
Od kiedy to zacznie być problemem?
Po 19-tu zmarnowanych minutach ? 29? 59?

Sorry, ale nie tak to działa. To co proponuję to blokada do czasu, gdy użytkownik nie zakończy edycji lub system po stronie klienta załamie się z jakiegoś powodu. Wada rozwiązania jest taka, że po wyjściu na dłużej oraz pozostawieniu formularza w stanie edycji rekord pozostanie zablokowany. Dlatego pisałem wyżej, że ten problem często można pozostawić samym użytkownikom do rozwiązania, jako kwestia organizacyjna.

Jak w większości dyskusji inżynierskich, istotne są warunki w jakich pracuje system oraz koszty realizacji. Dla małej grupy użytkowników, nierzadko pracujących w tej samej lokalizacji blokada pesymistyczna to sensowne rozwiązanie.

Fakt, dopisałem to później.

:smiley: :smiley: :smiley:
“Kocówa” w pokoju socjalnym? :wink:

  • jeżeli system wymaga takiej właśnie “obsługi organizacyjnej” dla niesfornych użytkowników, to właśnie takie rozwiązanie techniczne jest obarczone “grzechem pierworodnym”

Nie, to jest inżynieria, a więc działanie w ramach wymagań oraz dostępnego budżetu.