私は、ダウンタイムなしの展開を実装しようとしているチームで働いています。これを実現するために、青/緑の展開戦略を使用することを計画しています。私がこの調査で実現していることの1つは、データベースの変更を行うことがいかに複雑になるかです。列の名前を変更するような単純な操作では、完了するまで 完全なリリースサイクル を要します。
変更を完全に公開するには、複数のリリースサイクルがかかるため、人為的エラーが発生する可能性が高くなります。リンクされた記事では、2つのリリースではコードの変更が必要であり、3つのリリースではデータベースの移行が必要であることを示しています。
現在、何かを忘れないようにしたい場合は、問題管理システムでチケットを作成できます。これにより、混乱が生じ、管理者が後のスプリントまたはバックログに移動する可能性があります。または、TODOコメントを作成することもできます。これはおそらく完全に忘れられます。
私が探しているのは、TODOコメントに期限が設定される可能性がある方法です。この継続期限が切れている場合、継続的インテグレーションシステム(現在未定)がビルドを拒否します。
たとえば、列の名前を変更する場合、最初の移行を作成し、次に2つのTODOコメントを作成して、残りの2つの移行が確実に作成されるようにします。
// TODO by v55: Create migration to move constraints to new column, remove references to old column in app
// TODO by v56: Create migration to drop old column
これは実装するのはかなり簡単に思えますが、ホイールを再発明したくないので、このようなものがすでに存在しているかどうか疑問に思っています。
ここでXY問題に苦しんでいるように感じます。ローリングデプロイメントとブルー/グリーンデプロイメントがベストプラクティスであると考えると、データベースの更新の痛みを軽減するための解決策が見つからないのは奇妙に思えます。私が全体を間違って調べていると思われる場合は、コメントで知らせてください!とは言っても、データベースの例はほんの一例であり、期限付きのTODOコメントは他の状況でも役立つと思うので、この特定の状況にすべて近づいているとしても、本当に答えたいと思います。実際の質問も。ありがとう!
編集:私はこれが役立つかもしれない別の状況を考えました。機能の切り替えを使用して、準備ができたときにアプリの一部をオンにする場合は、それらをクリーンアップするように注意する必要があります。そうしないと、最終的に Toggle Debt になる場合があります。期限のあるコメントは、これを覚えるのに良い方法です。
この質問は、実際には1つの2つの質問です。
アクションアイテムを追跡するすべての方法の中で、これは最悪です。 TODOのコメントは、アクティブな作業中や、メンテナーへの提案の手段として「ここに将来改善される可能性があるものがあります」とよいでしょう。しかし、作業を完了するためにTODOコメントに依存していると、失敗する運命にあります。
それについて何をすべきか
TODOコメントは基本的に技術的負債であるため、他の技術的負債と同様に処理する必要があります。時間があれば、すぐに対処するか、バックログに入れて追跡および優先順位付けを行います。
一般的に言って、これは完全に意見が分かれており、議論の余地があります。TODOコメントはコードのにおいと考えることができます。 TODOコメントでバージョン管理にチェックインされている場合は、自問する必要があります。実際に今すぐフォローしますか?そうでなければ、それは大丈夫です。自分に正直になり、それをバックログに入れてください。
このバックログをどのように管理するかは、ビジネスプロセス、企業の政治、そしておそらくいくつかの個人的な自律性にかかっています。ただし、それが確実に行われるようにするには、追跡および優先順位付けされたバックログが必要です。
はい、データベースの変更は、ゼロダウンタイムポリシーでトリッキーです。痛みを軽減するためのいくつかのトリック:
デプロイ後のプロセス
同じリリースの一部として実行されるデプロイ後のプロセスを作成します。しかし、あなたはそれを働かせたいです。私が取り組んだ最後のシステムでは、4フェーズの展開を設計しました。
そのアイデアは、可能な限り、データベースの変更のできるだけ多くをpreappに入れるというものでした。
Postappは、互換性のないスキーマ変更を行う必要がある異常な場合のために予約されていました。これらの場合、preappは新しいアプリケーションコードに互換性を持たせるために十分な変更を加え(互換性のために一時的なビューを作成する場合があります)、postappはそのような一時的なアーティファクトをクリーンアップします。
メンテナンスウィンドウフェーズは、ダウンタイムを本当に必要とする変更、またはライブ展開のリスクやコストに見合わない変更のために予約されていました。たとえば、大量のデータを変更するスクリプトは、テーブル全体をロックする必要がある場合があります。
頻繁に展開
新しいリリースを頻繁に展開する場合、2つまたは3つのリリース間で変更を実行するのは簡単です。リリースサイクルが長いと、データベース変更のコストが増大します。
TODOは使用しないでください。プロジェクトにはすでにTODOリストがあります。これは課題追跡と呼ばれます。
本当の問題はこの文にあると思います:
問題管理システムでチケットを作成できます。これにより、混乱が生じ、管理者が後のスプリントまたはバックログに移動する可能性があります。
課題追跡が混乱を招く場合は、それを修正する方法を見つけてください。セレモニーが少ない特別な問題のタイプ/タグかもしれません。多分サブイシュー。たぶん、式典は完全に少なくなります。実際にはわかりません。しかし、問題追跡システムが多くの作業を作成する場合、その問題を追加するだけでなく、人々がパブリックフォーラムで手の込んだ質問を作成する場合、何かが深刻な問題です。
管理者がタスクの最後の部分を過度に遅延させる場合、2つのオプションがあります。
これが悪い考えである理由を経営陣に相談してください。
単一のタスクとして処理します。これは、ゴールドスタンダードソリューションかもしれません。完璧な世界では、各ステップで必要な3つの変更を行うことができるはずです。 1つをマスターブランチに適用し、ビルドしてデプロイします。それまでの間、2番目をマスターブランチに適用し、すべてを同じスプリントで実行するようにビルドおよびデプロイします。そうでない場合は、実行されません。論理的に1つの展開を行う場合、自動で実行しても意味があるかもしれませんが、実際には3つに分割されています。
私が探しているのは、TODOコメントに期限を設定できる方法です。この継続期限が切れていると、継続的インテグレーションシステム(現在未定)がビルドを拒否します。
あなたが仕事をして進んで行きたいと思っているなら、あなたが求めていることは実行可能です。
// TODO by v55:移行を作成して制約を新しい列に移動し、アプリ内の古い列への参照を削除します// TODO by v56:Create migration to drop old column
v55をデプロイするときに//TODO by v55
のgrep。配置ビルドは、統合テストとしてそれを行うスクリプトを実行します。
55をバージョントラッキングに関連付けるか、プロンプトを表示するだけです。
55を実行するときに// 54で// TODOをチェックしたい場合は、面白くなります。コードベースを55回検索するのは、// TODOで検索するだけです。次に、その結果を1〜55でフィルターします。これで、56は失敗をトリガーしません。
「ああ、それは必要ない。チェックがある限り、いつでも修正する」と思うかもしれません。いいえ、必要ありません。
私たちのチームにも非常に似た問題がありました。これを解決するために、参照するJIRA課題またはGit課題をチェックすることにより、これらのTODOを処理する静的分析チェックを作成しました。指定した課題が「開発中」列を通過すると、ビルドが失敗します。
ですから、TODOを忘れることなく快適に過ごすことができます。
Javaで、これのオープンソース実装を作成しました。はい、免責事項は私がこれを書いたことですが、私が言ったように、それは完全にオープンソースであり、ライセンスされています。
ツールは Westie と呼ばれ、Jira課題チェッカーの例はREADME.mdにあります。 GitIssueAnalyserも参照してください。
他に質問がある場合の自己宣伝を防ぐには、メッセージを送ってください。これを使用することに決めて提案がある場合は、githubで問題を提起してください。
TLDR:後でではなく、今すぐDBスクリプトを記述(およびテスト)してください。それらをコーディングして、実行がDBバージョンに依存するようにします。
例
例として、列名をSSN
からTaxID
に変更するとします。これは、国際化する際の一般的な要件です。
これを実現するには、TaxID
列とSSN
列の両方を一時的に使用している可能性があります。また、両方のバージョンをサポートしている間、一方を他方から更新するトリガーがあります。ただし、そのトリガーを無期限に保持したくないので、後で、下位互換性が不要になったら、そのトリガーを削除します(そしてSSN
列を削除します)。 ToDoアイテムを必要とせずに、これらすべてを事前にコーディングします。
この例では、ビルド101(存在しない)との互換性を維持しながら、ビルド102(新しい列がある)をデプロイします。
手順は次のとおりです。
1。バージョン管理テーブルをセットアップします
2つの列Configuration
とName
を持つValue
という単一のテーブルを追加します。
「TargetVersion」のName
を含む行を追加し、Value
をデプロイする新しいビルドのバージョンに設定します。
「CompatibleWith」のName
を含む行を追加し、Value
を、デプロイメントと互換性がなければならない最小バージョン番号に設定します。
すべての展開の前にこれらの行を検査して更新してください。
2。展開スクリプトの変更
TaxID
と並べてSSN
の新しい列を作成し、SSN
列からデータを取り込むスクリプトを追加します。このコードを、TargetVersionをチェックするIf
ステートメントで囲みます。ターゲットのバージョンが低すぎる場合(つまり、TaxID
がまだ必要ない場合)、スキップします。
SELECT @TargetVersion = TargetVersion FROM Configuration
IF @TargetVersion < '102' THEN RETURN
ALTER TABLE Customer ADD COLUMN taxID VarChar(12) NOT NULL
UPDATE Customer SET TaxID = SSN
TaxID
を挿入または更新するときにSSN
を生成するトリガーを作成するスクリプトを追加します。逆も同様です。このコードは、ターゲットバージョンと互換バージョンをチェックするIf
ステートメントで囲みます。 TargetVersionが低すぎる場合(TaxID
は不要)、またはCompatibleWithバージョンが高すぎる場合(SSN
フィールドは不要)はスキップします。
SELECT @TargetVersion = TargetVersion,
@CompatibleWith = CompatibleWith
FROM Configuration
IF @TargetVersion < '102' THEN RETURN
IF @CompatibleWith > '101' THEN RETURN
CREATE TRIGGER SSNAndTaxIDTrigger ON Customer etc.
SSN
列を削除するスクリプトを追加します。互換性のあるバージョンが十分に高い場合にのみ列を削除するIf
ステートメントで囲みます(SSN
は不要になります)。
SELECT @CompatibleWith = CompatibleWith FROM Configuration
IF @CompatibleWith <= '101' THEN RETURN
IF OBJECT_ID('SSNAndTaxIDTrigger') IS NOT NULL DROP TRIGGER SSNAndTaxIDTrigger
IF EXISTS (SELECT * FROM syscolumns c JOIN sysobject o ON o.id = c.is WHERE o.Name = 'Custeomr' AND c.Name = 'SSN') BEGIN
ALTER TABLE Customer DROP COLUMN SSN
END
3。テスト
本番環境でサポートできるようにしたいBlue/Greenバージョン番号の組み合わせでデプロイメントをテストしてください。 QA環境でConfiguration
テーブルを操作することにより、コードの準備ができたらすぐにテストできます。
4。導入プレイブック
エンジニアがCompatibleWithバージョンおよびTargetVersion行を更新するためのステップを追加します。 Blueにデプロイする場合は、TargetVersionをBlueのバージョン番号に設定し、CompatibleWithバージョンをGreenのバージョン番号に設定します。 Greenを展開している場合は、それらを逆にします。
落とし穴
配備スクリプトがそのDBテーブルに保持されているバージョン番号を参照して依存することは問題ありません。ランタイムコードではありません。
バージョン番号を検査するためのランタイムコードの作成を開始すると、アプリケーションに新しいレベルの複雑さが導入され、大きなメンテナンス性の問題になる可能性があります。各ランタイム実行パスをテストする必要があります。今後これらの条件を実行する場合、QAは 痛みの行列 をまとめて、リリースごとに検証する必要があります。私のアドバイスは、このような条件を展開スクリプトでのみ維持することです。
すべての結果
最後に、実行が早すぎることを恐れずに、すべてのコードを事前に(そしてそれもテストして)書くことができるはずです。また、コードは、後で心配する必要がないときに、下位互換性トリガーをクリーンアップします。
この方法では、コードについて考えているときに、すべてのコードを事前に記述してテストでき、面倒なToDoコメントに対処する必要がありません。
あなたはあなたのTODOアイデアに対して多くの反発を得ていますが、私は個人的にはそれで問題はないと思います。結局、移行が本番環境に移行することを確認するための最良の(そして最も簡単な)方法は、単体テストが失敗した場合に失敗することです。バージョンが55以上(または要件が何であれ)の場合に例外をスローする空の移行関数をスタブ化するのに、文字通り1分もかかりません。
次に、それを解放しようとすると、テストが失敗し、誰かがその例外を実際の移行コードに変換する必要があります。