W mojej aplikacji rails mam model Item, który ma wiele Versions. Mój kontroler ma akcję versions.

def versions
  @item = Item.find(params[:id])
  respond_to do |format|
    format.json { render json: @item.versions }
  end
end

Za każdym razem, gdy żądam wersji, niektóre elementy zwracają je pomyślnie, a inne nie. Ale kiedy wchodzę do konsoli, mogę bez problemu pobrać wersje wszystkich elementów.

Pomyślnie (zwraca tablicę wersji JSON):

Started GET "/api/versions/4.json?"
Processing by ItemsController#versions as JSON
Parameters: {"id"=>"4"}
Completed 200 OK in 106ms (Views: 0.1ms | ActiveRecord: 19.8ms)
app[web.1]: cache: [GET /api/versions/4.json?] miss
heroku[router]: GET x.x.com/api/versions/4.json? dyno=web.1 queue=0 wait=0ms service=113ms status=200 bytes=831

Niepowodzenie (zwraca dwie odpowiedzi, obie o statusie 200, brak danych JSON):

Started GET "/api/versions/1.json?"
Processing by ItemsController#versions as JSON
Parameters: {"id"=>"1"}
Completed 200 OK in 249ms (Views: 0.1ms | ActiveRecord: 162.9ms)
app[web.1]: cache: [GET /api/versions/1.json?] miss
heroku[router]: GET x.x.com/api/versions/1.json? dyno=web.1 queue=0 wait=0ms service=257ms status=200 bytes=3540

Jakiś pomysł, co może to spowodować? Nie wiem, jak logować SQL na Heroku, więc nie mam pomysłów.

0
nathan 28 sierpień 2012, 06:53

2 odpowiedzi

Najlepsza odpowiedź

To był właściwie błąd po stronie klienta. Na iOS obsługiwałem zwrócone dane w connection:didReceiveData:, który (przy zwracaniu dużych porcji danych) jest wielokrotnie wywoływany z częściowymi wynikami. Aby to naprawić, zamiast tego połączyłem wszystkie częściowe wyniki w tym wywołaniu zwrotnym i obsłużyłem dane w connectionDidFinishLoading:. Głupi błąd, niezwiązany z Heroku czy Railsami.

Dzięki za pomoc Craig.

0
nathan 28 sierpień 2012, 09:34

Ponowne rejestrowanie SQL: Włącz rejestrowanie instrukcji, wydając SQL SET log_statement='all'; po otwarciu każdego połączenia. Następnie sprawdź logi Heroku pod kątem Pg, aby zobaczyć, co się dzieje.

heroku logs --ps postgres

Widzieć:

Nie spowoduje to rejestrowania wyników zapytania, a jedynie tekst zapytania, parametry zapytania oraz błąd/powodzenie.

Aby obsłużyć rejestrowanie wyników, musisz to zrobić w swojej aplikacji; po prostu wypisz wiadomości na stderr, a Heroku doda je do dzienników aplikacji, dzięki czemu będziesz mógł je pobrać przez heroku logs.

Twój obecny kod i tak wygląda podejrzanie. Zapętlanie zestawu wyników i emitowanie json jest złe:

  • Nie jest wyraźnie jasne, że może istnieć tylko jeden wynik, a zatem emitować tylko jeden blok json; oraz
  • Jeśli nie ma wyników, nie jest emitowany żaden json

Zamiast tego zapisz wynik wyszukiwania — jeśli taki istnieje — w zmiennej. Następnie poprawnie obsłuż brakujące wyniki: w RESTful API prawdopodobnie zgłosiłbyś stan HTTP 404 Not Found; w interfejsie API bardziej w stylu RPC zwróciłbyś pusty dokument JSON lub dokument JSON z pewnego rodzaju flagą „nie znaleziono” i raportował stan HTTP 200 OK.

2
Craig Ringer 28 sierpień 2012, 07:33