Core のマイグレーションの番号の規約と共有表(Core_)
Core.Data のマイグレーションは FluentMigrator で書かれ、DatabaseMigrator がアプリ自身の分と Core.Data が持つ共有の分を、まとめて番号順に当てます。このページは、番号の範囲の規約、Core が作る表、更新時の注意を説明します。対象は 0.1.0-preview.9 です。
プレビュー版・未確認の範囲
プレビュー版の間は、共有マイグレーションの内容が変わり得ます(概要)。このページはソースの読み取りに基づきます。4 つの RDBMS の実機で適用して確かめた内容ではありません。 MySQL の照合順序についても同様です(後述)。
番号の範囲
アプリ同士は DB を共有しない(アプリごとに別の DB を持つ)前提です。同じ DB に同居するのは、Core の共有分と、そのアプリ 1 つだけです。番号は桁で範囲を分けます(_documents/コア化の方針.md)。
| 桁 | 範囲 | 持ち主 |
|---|---|---|
| 4 桁 | M0001〜M9999 | アプリ(Core の共有表を前提にしないもの) |
| 5 桁 | M10001〜M99999 | Core の共有マイグレーション(Core.Data が持つ) |
| 6 桁 | M100000 以降 | アプリ(Core の共有表の後に動かしたいもの。例: 旧い表の行を Core の共有表へ写す) |
- 各アプリは、自分の番号(1〜9999)を、ほかのアプリと調整せずに使えます。DB を共有しないので衝突しません。
- 実行は番号順です。桁で範囲が分かれているので、同じ DB に同居しても衝突しません。
- Core の共有マイグレーションは、アプリが何もしなくても当たります。
DatabaseMigratorは、アプリのマイグレーションのアセンブリに加えて Core.Data のアセンブリも走査します preview.6 以降。 - 既存の番号は変えません。 公開したマイグレーションの変更も、番号の振り直しもしません。直すときは、新しいマイグレーションを足します。
Core の共有マイグレーションの作法
Core の共有分は、そのツールの DB すべてに当たります。ツールごとに Core の版を上げる時期が違うため、次を守る方針です(_documents/コア化の方針.md)。
- 追加だけにする(テーブルの追加・列の追加・索引の追加)。列の削除・型の変更・名前の変更のような、壊す変更は入れない。
- 古い版のアプリが動いている DB に当たっても、そのアプリが壊れないこと(先に足してから、使う側を切り替える)。
- 共有のテーブルは
Core_の接頭辞を付ける。 アプリのテーブルと同じ名前になる事故を防ぐ。
共有表の一覧
preview.9 までに、7 つのマイグレーションが Core_ の表を作ります。どれも preview.6 で追加され、その後の版で列の変更はありません(タグ間の差分で確認)。
| マイグレーション | 表 | 用途 | 対応するストア |
|---|---|---|---|
| M10001 | Core_RateLimits | 複数台で共有するレート制限の数え(固定窓) | RateLimitStore |
| M10002 | Core_AdminInvitations | 管理者の招待(トークンは SHA-256 だけを保管) | AdminInvitationStore |
| M10003 | Core_AppSettings | 管理画面から編集するアプリ設定 | AppSettingStore |
| M10004 | Core_MailOutbox | メールの送信待ち(アウトボックス) | MailOutbox |
| M10005 | Core_AuditLogs | 管理操作の記録 | AuditLogStore |
| M10006 | Core_AdminUsers、Core_AdminSetup、Core_AdminRecoveryCodes | 管理者・最初の管理者の排他の印・TOTP の復旧コード | AdminUserStore |
| M10007 | Core_AdminSessions | 管理者のサーバ側セッション(ID は SHA-256 だけを保管) | AdminSessionStore |
各ストアの使い方は 共有ストア を参照してください。FluentMigrator 自身の管理表 VersionInfo も、DB に作られます(GetStatus が最後に適用した日時を読むために使う表)。
表の定義(要点)
| 表 | 主な列・制約 |
|---|---|
Core_RateLimits | LimitKey(主キー、200 文字)、Window、HitCount |
Core_AdminInvitations | InvitationId(主キー)、AdminUserId、TokenHash(64 文字、一意索引)、ExpiresAt、UsedAt、CreatedAt、CreatedBy |
Core_AppSettings | SettingKey(主キー、256 文字)、Value、IsSecret、UpdatedAt、UpdatedBy |
Core_MailOutbox | MailId(主キー)、Kind、SubjectId、PayloadProtected、Status、RetryCount、NextAttemptAt、LastError(1024 文字)、LockedBy、LockedUntil、CreatedAt、UpdatedAt。Status と NextAttemptAt の索引 |
Core_AuditLogs | AuditLogId(主キー)、OccurredAt(降順の索引)、ActorKey、ActorLoginId、Action、Succeeded、StatusCode、TargetType、TargetId、DetailJson、IpAddress。ほかの表への外部キーは張らない |
Core_AdminUsers | Id(主キー)、LoginId、LoginIdKey(小文字にした値、一意索引)、PasswordHash、Role、IsDisabled、FailedLoginCount、LockedUntil、LastLoginAt、CreatedAt、TotpSecretCipher、TotpPendingCipher、TotpLastTimeStep、Language(16 文字) |
Core_AdminSetup | Id(主キー。1 行だけ入れて、最初の管理者を作ったことの印にする) |
Core_AdminRecoveryCodes | UserId と CodeHash の複合主キー、UsedAt |
Core_AdminSessions | Id(主キー。セッション ID の SHA-256)、UserId、Kind、CreatedAt、ExpiresAt、IpAddress、UserAgent、SAML の SamlNameId・SamlSessionIndex、Pleasanter のログインの PleasanterTenantId・PleasanterUserId・PleasanterVerifiedAt。UserId・ExpiresAt・SamlNameId の索引 |
MySQL の照合順序
M10002・M10003・M10004・M10005・M10006(Core_AdminUsers と Core_AdminRecoveryCodes)・M10007 は、MySQL のときだけ表を utf8mb4 の utf8mb4_0900_as_cs(大文字小文字を区別する照合順序)へ変換します。ハッシュの比較を大文字小文字を区別する側へ揃え、文字列を utf8mb4 で持つためです。この照合順序を持たない MySQL 系の製品(古い版や MariaDB など)で適用できるかは、このマニュアルでは確認していません。
更新時の注意
- preview.5 以前から preview.6 以降へ上げると、DB に
Core_の表が作られます。 使わないストアの表も作られます。マイグレーションは前方のみに当てる方針で、ロールバック用のスクリプトには頼りません。 - アプリの
M0001〜M9999は、Core の共有表を前提にできません。 共有表の後に動かしたい移行(旧い表から Core の表へ行を写すなど)は 6 桁の番号にします。 - DB に当たったマイグレーションの確認は、
PendingMigrations(未適用の型名の一覧)かGetStatus(適用済みの最大の版・未適用の件数・最後に適用した日時)で行えます(DB の接続・暗号化・排他)。 - 排他で待たされる、取れずに
TimeoutExceptionになる場合は、同じ DB に対して別のインスタンスがマイグレーションを実行中でないか確認します。ロック名は<id>-startup-migrationsです。