TT Lab
はじめる
学ぶ 学習パス コース

取り消せない変更

変更結果を証拠で説明する

TT Labで続きを見る

一言でいうと

変更の報告書は、承認・実行の監査・観測した現在の行を、同じ時点で照合し、確認できていない事実を「完了」という言葉に混ぜてはいけません。

なぜ必要なのか

エイリアン・フェスティバルのキャンセル作業が終わったというメッセージが届きました。運用担当者は「3件処理しました」と言い、顧客は「3人とも元どおりになりましたか」と尋ねます。同じ3件という数字が、別々の質問を覆い隠しています。承認した3つのIDが合っているか、そのときに変更が確定したか、その後に別の担当者が変更していないか、いまもその状態か、はどれも別のことです。

報告書を長く書けば、問題は解決するでしょうか。根拠のない完了の文を3ページに引き延ばすと、さらにもっともらしい誤解になります。今回は、DBを再び直す人ではなく、すでに実行された変更を調査し、顧客が次の行動を決められるように説明する担当者になります。入力は、承認の一覧、実行当時の監査、観測時点の現在の行です。出力は、機械が検査する構造と、人が読む説明を、あわせて持つ小さな証拠のまとまりです。

前のチャンクのレッスンは、作業を引き継いで実行しました。今回の報告ツールには、実行の権限を任せません。不一致が見つかったら、保留の理由を書き、承認や現在の値を、報告書に合わせて上書きしません。報告を緑色にするために事実を変えた瞬間、調査と実行の境界が消えます。

どう動くのか

1. 件数より先に、集合と意味を合わせる

承認IDが1・2・5で、監査IDが1・2・31なら、どちらも3件ですが、完了ではありません。承認の範囲外のID 31は、確認が必要な事故の候補で、ID 5は、監査がない対象です。2つの集合の長さを比べるだけでは、この違いを見つけられません。

IDだけでも十分ではありません。監査の前のrevision・後のrevision・数量が、承認した内容と一致してはじめて、その変更の確定の根拠として数えます。監査が記録した後のrevisionは、承認時のrevision+1でなければなりません。現在の行の顧客・数量・状態・revisionは、そのあとにまた変わったかどうかを確認する、別の資料です。同じcancelledの状態でも、revisionがより大きければ、その後の作業があった可能性があるので、黙って一致として処理しません。

今回の顧客との契約の分類は、次のとおりです。committedは、承認と正確に合う監査があるID、remainingは、残りの承認IDです。committedのうち、現在の値も合っていればmatching、現在の行がなければmissing、それ以外はdriftedです。承認の範囲外の監査や、前後のバージョン・数量が違う監査は、invalid_auditとして別に残します。形式そのものが壊れているデータや、IDが重複しているデータは、分析の前に拒否します。

監査がないremainingの、現在の状態だけを見て、未実行だと断定することはできません。別の経路の作業があったかもしれませんし、監査が欠落したのかもしれません。このレッスンは、「確定の根拠がない」と報告します。実際の実行を再開するには、前のレッスンの現在の条件・新しい承認の検証が必要です。報告書を実行の許可証として使わないでください。

2. 複数のSELECTに、同じ瞬間を見せる

承認を読んだあとで、別の接続が注文と監査をまとめて確定します。報告ツールがそのあとで監査と注文を読むと、最初のクエリは前の時点、次のクエリは新しい時点になることがあります。BEGINを入れたという事実だけでは、複数の参照が同じ瞬間になるわけではありません。

今回の収集は、PostgreSQLのREPEATABLE READ READ ONLYトランザクションを使います。同じ観測の中の通常のテーブルの参照を、一貫したスナップショットに保ちながら、報告のコードが業務のテーブルを変更できないようにします。分離レベルの公式ドキュメントで、Read CommittedとRepeatable Readの参照時点を比べ、SET TRANSACTIONのREAD ONLYの制限も読んでみてください。

ラボは、文字列で分離レベルを書いたかどうかだけを見るのではありません。after-planまたはafter-auditの地点で、別の接続が実際の注文・監査をコミットします。今回の収集には新しい変更が混ざらず、収集を終えたあとに再び観測したときだけ見えなければなりません。読み取り専用の区間でUPDATEを試みると、実際のDBが拒否するかどうかも確認します。

この保証は、すべての業務データが正しいという保証ではありません。もとの監査が壊れていれば、一貫したスナップショットにも、その破損がそのまま見えます。複数のシステムの外部APIまで、同じ瞬間にまとめてくれるわけでもありません。今回の対象は、同じPostgreSQLの中の通常のテーブルで、収集したデータの業務上の整合性は、そのあとのステップで別に検査します。

3. 借りた接続の状態を返す

psycopgの接続は、再利用されることがあります。今回の呼び出しで、読み取り専用・分離レベル・短い制限時間を設定したなら、次の呼び出しにそのまま残してはいけません。このラボは、autocommit=Trueで、呼び出しの開始時に開いているトランザクションがない接続を、契約として受け取ります。収集のコンテキストの中でだけ設定を適用し、成功・失敗のあとにIDLEに戻ります。

借りた接続は閉じず、publishが自分で作った接続だけを閉じます。ファイルを書いている間、DBのスナップショットを開き続ける理由もありません。データを収集したあと、接続を閉じてから、直列化とファイルの置き換えを進めます。psycopgのトランザクション管理を見て、入れ子のトランザクションと、実際のコミットの違いを、もう一度確認してください。ドキュメントのバージョンとは別に、ラボでは、インストールされているpsycopg 3.2.3で実行します。

4. 人に見せる説明も、同じ根拠から作る

機械用の結果にholdと書いておきながら、顧客への説明に「完了しました」と書くと、データは内部ですでに衝突しています。今回のバンドルは、evidence・report・summaryをあわせて入れます。summaryは、同じanalyzeの結果から、承認・確定・未確定・現在の一致・その後の差異・欠落・監査の不一致のIDを示す、平文です。

完了という言葉にも、範囲を付けます。completeは「観測時点での完了」であり、観測のあとの状態まで維持されるという約束ではありません。問題のある監査・その後の差異・欠落があればhold、そうした問題がなくても、確定の根拠がない承認IDが残っていればincompleteです。完了より保留が先なのは、残りを実行する前に、現在の異常を説明する必要があるからです。

報告書は、SQLでもHTMLでもありません。JSONの文字列と数値は、データとして扱い、実行しません。時刻とスナップショットの表記は、あとでどの観測を指すのかを識別する、メタデータです。値を直接入力できるという事実を忘れて、公的に認証された時刻のように説明してはいけません。

現場での姿

ハッシュが合っているのに、偽りの報告になりうる

直列化するときに、キーの順序・空白・UTF-8の表現を固定すれば、同じ正規のデータのバイト列とハッシュが同じになります。これは今回の形式のローカルな規則であり、すべてのJSONツールが自動で同じバイト列を作る標準だとは主張しません。数値・文字列・ブール値を区別し、重複したキーやNaNのような入力も拒否します。PythonのJSONドキュメントの直列化オプションとobject_pairs_hookを参照してください。

ハッシュは、内容が変わったかどうかを照らし合わせる手段であり、出所を認証する署名ではありません。誰かが判定だけをcompleteに変えて、ハッシュを計算し直せば、単純なハッシュの検査には通ります。そのため、evidenceからreportとsummaryを再計算して、あわせて比べます。逆に、観測時刻などの証拠全体を一貫して新しく作り、ハッシュも計算すれば、この検査だけでは虚構を見分けられません。ラボは、この場合が通ってしまう反例も見せます。内部の一致と真偽は、別の要求です。

実際の顧客に渡すときには、信頼できる収集の経路、アクセス制御、変更できない記録と承認の体制が、追加で必要になることがあります。今回のファイル形式を作ったからといって、その組織の証拠保全のポリシーをすべて実装したとは言いません。ユーザー認証や、顧客ごとのDBへのアクセス権限も、この分析関数の役割ではありません。

報告書のファイルを半分だけ上書きしたまま失敗したら

既存のreport.jsonを、書き込みモードで先に開くと、あとのエラーが、以前の完成版まで消してしまうことがあります。同じディレクトリの別の一時ファイルに、完成したバイト列を書いて閉じ、os.replaceで送り先を入れ替えます。置き換えの前のエラーなら古いファイルが残り、置き換えのあとに応答だけを失った場合は、新しいファイルが完成した状態で残ります。os.replaceのドキュメントと、失敗した位置を、あわせて読んでください。

ラボは、通常の例外で、自分の一時ファイルを片付け、ほかのファイルには触れないかどうかも検査します。プロセスの強制終了では、finallyが実行されないことがあり、電源障害にはファイルシステムの耐久性の問題が加わります。今回の検証は、通常の実行と、注入した例外でのファイルの置き換えの保全であり、強制終了・ディスクの破損・電源障害までは証明しません。

FDEの報告は、次の決定を助ける仕事

Palantir FDSEの求人は、顧客に合わせた実装と、複数のステークホルダーとの協業を扱っています。これを根拠に、顧客が読む説明と、技術チームが再検証する構造を、あわせて作る課題を設計しました。その会社の内部の様式や、必須の技術パターンを再現したという意味ではありません。

次のラボですること

宇宙のお祭りの変更の証拠を、一貫して収集し、同じ件数の別のID・監査のバージョンの誤り・その後の変更を分離します。人が読む説明と、機械の判定を同じ根拠から作り、ハッシュを計算し直した誤った結論と、重複したJSONのキーも拒否します。最後に、読み取り専用のDBの収集から、既存のファイルを保全する発行までをつなぎます。

ラボは、仮想のデータと、受講生ごとの使い捨てのDBだけを使います。外部の顧客に報告書を送ったり、運用DBを変更したりする作業はありません。