Pytanie Sinatra ze zmienną stałą


Moja aplikacja Sinatra musi przeanalizować ~ 60 MB pliku XML. Ten plik prawie nigdy się nie zmienia: w nocnym zadaniu cron jest nadpisywany innym.

Czy istnieją jakieś sztuczki lub sposoby przechowywania sparsowanego pliku w pamięci, jako zmiennej, tak, że mogę odczytywać z niego na przychodzących żądaniach, ale nie muszę analizować go w kółko dla każdego przychodzącego żądania?

Jakiś Pseudokod w celu zilustrowania mojego problemu.

get '/projects/:id'
  return @nokigiri_object.search("//projects/project[@id=#{params[:id]}]/name/text()")
end

post '/projects/update'
  if params[:token] == "s3cr3t"
    @nokogiri_object = reparse_the_xml_file
  end
end

Muszę wiedzieć, jak stworzyć taki obiekt, aby działał po uruchomieniu Sinatry. Czy to w ogóle możliwe? A może potrzebuję jakiegoś miejsca na dane?


13
2018-06-22 17:05


pochodzenie




Odpowiedzi:


Możesz spróbować:

configure do
  @@nokogiri_object = parse_xml
end

Następnie @@nokogiri_object będą dostępne w Twoich metodach prośby. Jest to raczej zmienna klasy niż zmienna instancji, ale powinna robić to, co chcesz.


9
2018-06-22 17:33



Czy @@ var będzie dostępny w sesjach i na żądanie? Powiedz, że użytkownik Anna pobiera / foo, @@ var jest utworzony, a następnie, gdy Barry odwiedza / foo, @@ var jest wciąż ustawiony? - berkes
@berkes tak, jest tylko jeden @@var współdzielone między wszystkimi żądaniami - matt
@berkes: posiadanie zmiennej o wartości 60 mb nie jest zbyt wydajne. Ten baran powinien być lepiej wykorzystany. Myślę, że rozwiązanie użycia pliku do przechowywania przeanalizowanego pliku jest znacznie lepsze. Można nawet użyć bazy danych Mini redis do przechowywania ostatniego pliku, lub do użycia zmiennej globalnej. Ale przechowuj w pamięci tylko datę, a nie rzeczywisty plik. Jeśli jest dłuższy niż jeden dzień, zaktualizuj przeanalizowany plik. Jeśli jest niższy, po prostu przeczytaj przeanalizowany plik. To jest najbardziej efektywny sposób, jaki mogę wymyślić. - Nerian
@@ Nerian: masz rację. I w pierwszym refaktoryzacji rozważę albo redis albo mongodb. Na razie potrzebuję głównie uzyskać dowód koncepcji, sprawdzając, czy mogę przeanalizować plik / pliki (jest ich o wiele więcej) w oparciu o parametry. Ale dzięki za ostrzeżenie i napiwek! - berkes
Właśnie próbowałem tego, zmienna jest ustawiana za każdym razem ponownie :( - Dominik Goltermann


Proponowane rozwiązanie daje ostrzeżenie

warning: dostęp do klasy class z poziomu tween

Możesz użyć metody klasy, aby uzyskać dostęp do zmiennej klasy, a ostrzeżenie zniknie

require 'sinatra'

class Cache
  @@count = 0

  def self.init()
    @@count = 0
  end

  def self.increment()
    @@count = @@count + 1
  end

  def self.count()
    return @@count
  end
end

configure do
  Cache::init()
end

get '/' do
  if Cache::count() == 0
    Cache::increment()
    "First time"
  else
    Cache::increment()
    "Another time #{Cache::count()}"
  end
end

8
2018-01-29 22:31





Dwie opcje:

  • Zapisz sparsowany plik do nowego pliku i zawsze czytaj ten.

Możesz zapisać w pliku - serializować - skrót z dwoma kluczami: "ostatnia modyfikacja" i "dane".

Wartość "ostatniej modyfikacji" jest datą i sprawdzasz każde żądanie, jeśli ten dzień jest dzisiaj. Jeśli nie jest to dzisiaj, to nowy plik jest pobierany, analizowany i zapisywany z dzisiejszą datą.

Wartość "danych" to przeanalizowany plik.

W ten sposób parsujesz tylko raz, coś w rodzaju pamięci podręcznej.

  • Zapisz sparsowany plik do bazy danych NoSQL, na przykład redis.

0
2018-06-22 17:12



Myślałem o redis, memcached lub nawet mongoDB. Nadal jestem w wyścigu, ale wolałbym, żeby to było naprawdę - naprawdę proste, kiedy to możliwe :) - berkes