アニソンイントロクイズ練習サイト

繰り返しランダム再生コード

1.下記のコードをコピーして、サイト(https://app.tockey.net/panelquiz/intro/2000/index.html)を開く。
※アニソンイントロクイズ前に公開するので、いつもは使用できません。

2.F12キーを押下して、開発者ツールを開く。

3.最下段に「コンソール」があるので、最終行に張り付けてEnter。

(() => {
  const sleep = (ms) => new Promise(r => setTimeout(r, ms));

  function getAudio() {
    return document.querySelector('audio#player, audio');
  }

  function findCandidates() {
    const rows = Array.from(document.querySelectorAll('tr'));
    const list = [];
    for (const r of rows) {
      const txt = (r.innerText || "").trim();
      if (!txt) continue;

      const parts = txt.split(/\s+/);
      const last = parts[parts.length - 1];
      if (last !== "1" && last !== "2") continue;

      // クリック対象の推定(button/a/role=button → なければtd先頭)
      const click =
        r.querySelector("button, a, [role='button']") ||
        r.querySelector("td") ||
        r;

      list.push({ row: r, click });
    }
    return list;
  }

  async function waitAudioEnd(maxWaitMs = 360000) {
    const start = Date.now();
    while (true) {
      const a = getAudio();
      if (a && Number.isFinite(a.duration) && a.duration > 0) {
        // ended or near end
        if (a.ended || a.currentTime >= a.duration - 0.05) return true;
      }
      if (Date.now() - start > maxWaitMs) return false;
      await sleep(250);
    }
  }

  let candidates = findCandidates();
  if (!candidates.length) {
    console.warn("レベル1/2候補が見つかりませんでした");
    return;
  }

  let lastIndex = -1;
  let stopFlag = false;
  window.__STOP_RANDOM_XE__ = () => { stopFlag = true; };

  (async () => {
    console.log("開始。止めるには __STOP_RANDOM_XE__() を実行");
    while (!stopFlag) {
      // DOMが変わる場合だけ再取得(軽く)
      const fresh = findCandidates();
      if (fresh.length) candidates = fresh;

      let idx = Math.floor(Math.random() * candidates.length);
      if (candidates.length > 1 && idx === lastIndex) idx = (idx + 1) % candidates.length;
      lastIndex = idx;

      const { row, click } = candidates[idx];
      const title = (row.innerText || "").split("/")[0].replace("再生", "").trim();
      console.log("クリック:", title);

      // 再生クリック
      click.scrollIntoView({ block: "center" });
      click.click();

      // 曲が終わるまで待機
      const ok = await waitAudioEnd();
      if (!ok) console.warn("タイムアウト。次へ");
      await sleep(200); // 次曲までの短いクッション
    }
    console.log("停止しました");
  })();
})();

アプリ開発のサーバーサイド、いったん保留か。

■検討

 まず、制約事項としてさくらVPSの最小プランを選択しました。
 なので、その環境で動作する必要がありますので、軽量であることが条件となります。
 実際に何度もOSの再インストールをして試してみましたが、そもそも各種ライブラリなどがきちんとインストールできないとかありましてね。。。
 とりあえず、脆弱性の面でPHPなどは避けておきたいので、自分の中ではRubyかPythonかなと見当をつけていました。

■Ruby On Rails

 何度もOS再インストールを繰り返しながら何とかインストールができそう!ってところまで行きましたが、結局はメモリが足りずに断念しました。

 結構時間もかかっていたのに残念です。
 潤沢に資金があればプランをスケールアップして採用するのもアリでしたね。

■Python

 Rubyの次点として考えておりましたが、Rubyがダメそうとなって本格的に検討しました。
 Pythonで軽量なWEBアプリケーションが作成できるのかなと思っていましたが、FastAPIというものがあるらしく、それを使おうと思います。
 さくらVPSにはPython向けセットアップスクリプトがあったんですけど、全然インストールされてないんですよね。。。
 サーバーサイドは諦めて、アプリにデータを含めてリリースする方が早くリリースできそうなんですよねー。

HTTPステータスに502を返却している

主題のとおり、HTTPステータスに502を返却していたので、原因を調査して対策した話。

【原因調査】

まずはネットで502ってどんな時に出てくるの?ってのを調べました。
色々見て回ったところ「負荷がかかっている」みたいなのを見て、確かに日中帯に出現していて夜間帯は全然出ていない、というところで納得しました。

が、
実は負荷ではなく、別な原因がありました。

【原因判明】

原因はTomcatのコネクションプールサイズの最大数と最小数が異なるためです。
Tomcatのコネクションプールは、使用していないコネクションを自動で開放(切断)します。
なので、使用していないコネクションを開放するタイミングでリクエストが来た時はそのまま開放しちゃうので502が発生してしまうということみたいですね。

ちなみに同様の事象なのかはApacheのエラーログを見れば分かると思います。
下記のようなエラーが出ていると思うので。

proxy: error reading status line from remote server...


ちょっと気になったのは、色々サイトを見て回ったけど、何故か「Apacheにコネクションプールを使用しない設定にしましょう」(proxy-initial-not-pooledの有効化)って対策が出てくるんですよね。

【対策】

便利な機能をOFFにしましょうというのは納得できなかったのでもっと調査した結果、コネクションプールの最大数と最小数を同数にしました。

原因が不要なコネクションを閉じてしまうというなら、常にコネクションを一定量に保つようにしておきましょうということですね。

自力で思いついた訳ではないんですけど、ここに書いた方が記憶に残りそうだし、同じことでつまずいている人がいた場合に他の対策方法を提示できるかもしれないので。(^^)

※バックエンド側に設定する方法があると思いますが、それはバージョンやフレームワークとかミドルウェアで変わってくると思うので記載はしません。

本番環境と検証環境を区別させたい

目的・意図

検証環境を利用していて、誤って本番環境にアクセスしてしまわないかは心配ですよね。
誤って本番環境にアクセスしてゴミデータを登録したりとか、ありそうですよね。

提案

Chromeの設定でサイトごとに画像を表示させない設定ができるので、その設定を試してみてはいかがでしょうか?

右上の3点リーダーから「設定」
→左のメニューから「プライバシーとセキュリティ」
→「サイトの設定」
→「画像」
→「画像の表示を許可しないサイト」に対象のURLを追加。

最近では、画像を全く使っていないというようなサイトは少ないと思いますので、
「画像が表示されない→本番環境だ」となるのではないでしょうか。

昔、担当したことのあるシステムでは検証環境だけ背景色が変わっていたりしていましたが、
これならコードをいじらなくて良いので、お手軽かなと思います。