3

ここに問題があります。ユーザーが表示したいデータがあります。クエリは、私が思うに高速になるように最適化し、インデックスを作成しました。1 秒か 2 秒削るかもしれませんが、データの量を考えると、できることはあまりありません。

いずれにせよ、クエリは 1 日または 2 日のデータに制限されている場合でも問題なく実行されますが、ユーザーは 1 週間または 2 週間のデータに対して実行しています。したがって、2 ~ 3 週間分のデータのクエリには約 40 秒かかり、Heroku のタイムアウトは 30 秒で、これは機能しません。したがって、解決策が必要です。

こことGoogleで検索すると、WebhookまたはAjaxが解決策として機能するというコメントが表示されます。ただし、実際の具体的な例を見つけることができませんでした。また、「時計をリセットする」何らかの応答を送信できると誰かが言っているコメントも見ました。しかし、再び興味をそそるように聞こえましたが、例を見つけることができませんでした.

ユーザーは不満を抱いているため、迅速でシンプルなソリューションが必要です。よろしくお願いします。

4

1 に答える 1

1

同様の問題に直面しました。Sinatra アプリには基本的に「一括ダウンロード」ページがあり、クライアント アプリはこれを呼び出して、ブラウザーのローカル webSQL データベースにデータをインポートします。

ダウンロード ページ (「GET /download」と呼びます) は、CouchDB データベースにクエリを実行して、指定されたビュー内のすべてのドキュメントを取得します。プロセスのこの部分 (クエリと同様) に長い時間がかかります。

Sinatra のストリーミング API を使用して、この問題を回避することができました。前述のように、Heroku の時計は、30 秒が経過する前に応答で少なくとも 1 つの by を送信することで「リセット」できます。これにより、クロックがさらに 55 秒間リセットされます (さらに送信するバイトごとにクロックが再度リセットされます)。これにより、データを送信している間、接続を無期限に開いたままにすることができます。

シナトラでは、これを置き換えることができました:

get '/download' do
  body = db.view 'data/all'
end

..次のようなもので:

get '/download' do
  # stream is a Sinatra helper that effectively does 'chunked transfer encoding'
  stream do |out|
    # Long query starts here
    db.view 'data/all' do |row|
      # As each row comes back from the db, stream it to the front-end
      out << row
    end
  end
end

「最初のバイトまでの時間」(つまり、dbクエリが最初の行を返すのにかかる時間は30秒の制限をはるかに下回っているため、これは私にとってはうまく機能します。

唯一の欠点は、以前はすべての結果をデータベースから Sinatra アプリに戻してから、結果全体の MD5 合計を計算して etag ヘッダーとして使用していたことです。クライアント アプリはこれを使用して、条件付きの HTTP get を実行できます (つまり、再度ダウンロードしようとしてデータが変更されていない場合は、302 Not Modified を送信できます)。さらに、受信したデータの独自のチェックサムと比較できます (転送中に破損/変更されていないことを確認するため)。

応答でデータのストリーミングを開始すると、HTTP ヘッダーとして送信するコンテンツの MD5 合計を計算できなくなります (まだすべてのデータを取得していないためです。本文の送信を開始しました)。

これをある種のページ分割された複数の AJAX 呼び出し、ソリューションに変更することを考えています。Zenphが上で提案したように。または、ある種のワーカー プロセス (Resque、DelayedJob など) を使用してクエリをオフロードします。しかし、データを取得する準備ができたときにクライアントに通知する方法がわかりません。

お役に立てれば。

于 2013-03-11T13:21:06.693 に答える