1

私は2つのアクションを持つコントローラーを持っています。1 つは非常に長い計算を実行し、いくつかのステップでセッション コンテナーにステータスを格納します。

public function longAction()
{

    $session = new Container('SessionContainer');
    $session->finished = 0;
    $session->status   = "A";

    // do something long

    $session->status = "B";

    // do more long jobs

    $session->status = "C";

    // ...

}

2 番目のコントローラー:

public function shortAction()
{

    $session = new Container('SessionContainer');

    return new JsonModel(
        array(
            'status' => $session->status
        )
    );

}

これらは両方とも AJAX 経由で呼び出されますが、ブラウザーのタブを使用するだけで同じ動作を示すことができます。私は最初に /module/long を呼び出します。タスクを完了する間、/module/short (JSON をエコーするだけだと思っていました) を呼び出すと、/module/long が停止します。

これを持ち出すと、一部の ZFer は、これが競合状態に対する有効な保護であると感じました。しかし、後者を本当に気にしないこのユースケースを持つ唯一の人ではないはずです。

キュー、データベース、またはメモリ キャッシュに向かうのを避けるための安価なトリックはありますか? 軽量化を図っています。

4

1 に答える 1

0

これは予期される動作です。これが理由です:

セッションは、セッション ID を保存する Cookie を使用して識別されます。これにより、ブラウザは次のリクエストで同じセッションを取得できます。

長いプロセスがセッションを使用しているため、プロセス全体の実行が完了するまでsession_write_close()は呼び出されません。つまり、長いプロセスの実行中にセッションがまだ開いていることを意味します。

別のブラウザー タブに接続すると、ブラウザーは、まだ開いていて長いプロセスを実行している同じセッション (同じ Cookie を使用) を取得しようとします。

別のブラウザーを使用してリンクを開くと、ページが正常に読み込まれ、session_write_close()が呼び出されるのを待つ必要がないことがわかります。これは、別のセッションを開いているためです (ただし、必要なテキストは表示されません)別セッション)

セッションを手動で書き込んで閉じる (session_write_close()) こともできますが、それはおそらく最良の方法ではありません。

これについては、Gearman のようなものを検討する価値があります。余分な作業はそれほど多くなく、特にこの種の非同期ジョブ処理用に設計されています。データベースにステータスを書き込むこともできますが、それでも理想的ではありません。

于 2013-01-28T13:25:44.597 に答える