Pleasanter Setup と Rds.json の Provider
データベースの構築・更新は CodeDefiner が担います。このページでは、CodeDefiner を画面から呼び出す Pleasanter Setup の動き方と、Rds.json の Provider に "Azure" を指定したときに CodeDefiner の処理がどう変わるかをまとめます。
結論:
- Pleasanter Setup は CodeDefiner を 決められたフローで呼び出すラッパー です。CodeDefiner のスイッチ(
/p/tなど)が使えないのは、Setup 側が渡す引数が限られているためです。画面が止まって見えても、logs/Implem.CodeDefiner_*.logを見れば処理中かどうか判断できます。 Provider: "Azure"を指定すると、CodeDefiner は テーブルの作成・更新だけ を行い、DB 作成・ユーザー作成・スキーマ作成・権限付与・セッション切断をスキップします。タイムゾーンには影響しません。
INFO
Rds.json の Provider の処理は 1.5.3.0 を対象にしています。Pleasanter Setup の節は対象バージョンの明記がない情報です。 確認したソースでも、CodeDefiner の action の分岐とログファイル名(Starter.cs#L30-L31、Starter.cs#L67-L117)、Provider の判定(Initializer.cs#L1026-L1034)、Configurator.Configure() の分岐(Configurator.cs#L25-L47)、SysLogModel.OnAzure(SysLogModel.cs#L3421)が同じであることを確認しています。
CodeDefiner の引数処理
CodeDefiner は Starter.Main(string[] args) で起動引数を受け取り、ArgsType() で /p や /t のようなスイッチを辞書化して処理を分岐します。
var argHash = ArgsType(args);
var action = args[0];
var path = argHash.Get("p")?.Replace('\\', Path.DirectorySeparatorChar);
var target = argHash.Get("t");さらに switch (action) で _rds・def・mvc などの処理を切り替える構造になっているため、CLI から細かく制御できます。
switch (action)
{
case "_rds":
case "def":
case "mvc":
// ...
}CodeDefiner のコマンド体系全体は CodeDefiner を参照してください。
Pleasanter Setup
CodeDefiner のラッパーとしての位置づけ
Pleasanter Setup は CodeDefiner を直接 CLI として使うのではなく、Setup 画面で決められたフローで呼び出すラッパー です。
そのため、CodeDefiner 側にスイッチの実装があっても、Pleasanter Setup の画面がそのスイッチを入力項目として持っていなければ引数として渡せません。「CodeDefiner が対応していない」のではなく、Pleasanter Setup から渡される引数が限定されている ことが、CodeDefiner 単体で使えたスイッチが Setup では使えない理由です。
内部で実行される CodeDefiner の処理
Pleasanter Setup の画面操作は、内部的には Implem.CodeDefiner/Starter.cs の switch (action) にある次の処理の組み合わせに相当します。
| Pleasanter Setup でのフェーズ | CodeDefiner の action | Starter.cs で実行される処理 |
|---|---|---|
| 初期 DB 構成 | _rds または rds | ConfigureDatabase()(rds の場合は続けてコード生成も実行) |
| 定義・コード生成 | _def または def または mvc | CreateDefinitionAccessorCode() / CreateMvcCode()(def は両方、_def は前者のみ) |
| DB 移行を伴う更新 | migrate | ConfigureDatabase() → MigrateDatabase() |
| パラメータ引き継ぎ系の更新 | merge | MergeParameters() |
CLI で手動実行する場合はこれらを個別のコマンドとして直接呼び出せます。Pleasanter Setup はこの個別処理を画面フローでまとめて実行します。
図を読み込み中…
手動実行との比較
| 観点 | 手動インストール / 手動バージョンアップ | Pleasanter Setup |
|---|---|---|
| 処理の実行単位 | _rds、def、migrate などを個別に実行 | 画面の操作単位で内部実行 |
| スイッチ指定 | 実行時に /p /t /f などを直接指定可能 | 画面が持つ入力項目に依存 |
| 進捗の把握 | 実行したコマンド単位で把握しやすい | 1 つの画面処理に見えるため内部工程が見えにくい |
| 失敗時の切り分け | どのコマンドで失敗したか追いやすい | ログを見て内部工程に分解して把握する必要がある |
バージョンアップの手順は バージョンアップ を参照してください。
画面が止まって見えるとき
DB 構成、定義生成、コード生成などの長時間処理の最中は、Pleasanter Setup の画面の進捗表示が細かく更新されないため、止まっているように見えます。
ただし CodeDefiner 側はログを出力しながら処理を続けています。Starter.Main は起動時に logs/Implem.CodeDefiner_yyyyMMdd_HHmmss.log を作成し、Trace に出力しています。
LogFolderName = "logs";
LogNameText = $"Implem.CodeDefiner_{DateTime.Now:yyyyMMdd_HHmmss}";
Directory.CreateDirectory(LogFolderName);
var logName = Path.Combine(LogFolderName, $"{LogNameText}.log");
Trace.Listeners.Add(new TextWriterTraceListener(logName));
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));ログで実行中かを確認する
Pleasanter Setup の実行中に最新のログを表示すると、処理が進んでいるか判断できます。次のコマンドは Pleasanter のインストールディレクトリ(例: C:\web\pleasanter。Implem.CodeDefiner.exe と logs フォルダがある場所)で実行します。
$latestLog = Get-ChildItem .\logs\Implem.CodeDefiner_*.log |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
Get-Content $latestLog.FullName -Wait次の 3 点が確認できれば、画面の更新が少なくても処理自体は動いていると判断できます。
- ログファイルの
LastWriteTimeが更新され続けている <INFO>や<SUCCESS>の行が追加されている- ログ末尾に
<SUCCESS>で始まる完了メッセージ行(...Completedを含む行)が出る
1.5.8.1 では、テーブルの処理中はテーブルごとに <INFO> TablesConfigurator.ConfigureTableSet: テーブル名 の行が出て、作り直すテーブルでは Tables.MigrateTable / Tables.CreateTable の行が続きます。ログにもコンソールにも同じ行が出ます(TablesConfigurator.cs#L151-L161、Consoles.cs#L18-L45)。同じ行のまま長く止まっているときは、そのテーブルの移行(全件のコピー)が続いています。データの多いテーブルほど時間がかかります。
CodeDefiner を直接実行したときの y の確認は、DB・ユーザー・スキーマの作成 / 更新とライセンス情報の表示、Issues / Results の列の減少チェックが終わったあとに出ます。y を入力したあとに動くのはテーブルの作成・移行と権限付与です。処理の順序と移行のしかたは CodeDefiner の「データベースの作成・更新」を参照してください。
Azure App Service(Windows)の Kudu で実行するとき
Azure App Service(Windows)の Kudu の Debug Console で CodeDefiner を実行すると、日本語の出力が文字化けすることがあります。Kudu の CMD のコードページは chcp で確認でき(例: Active code page: 437)、chcp 65001 で UTF-8(CP65001)に切り替えられます。エラーが出ずに Active code page: 65001 と表示されれば使えます。
chcp 65001 && echo テスト「テスト」が文字化けせずに表示されれば切り替わっています。Kudu のセッションを閉じるとコードページは元に戻るため、CodeDefiner を実行するバッチの先頭に書いておきます。
@echo off
chcp 65001 > nul
dotnet Implem.CodeDefiner.dll _rdsPowerShell の Debug Console では、chcp 65001 のあと [Console]::OutputEncoding を確認し、BodyName が utf-8 になっているかを見ます。chcp を実行しても [Console]::OutputEncoding は別途変更が必要な場合があります。Linux の App Service は既定で UTF-8 のため、この手順は要りません。
INFO
この節は Azure App Service(Windows)の Kudu で確認した内容で、プリザンターのソースとは関係しません。
Rds.json の Provider
設定値
データベースの設定ファイル App_Data/Parameters/Rds.json には Provider という項目があります。既定値は "Local" で、Azure SQL Database などの Azure 環境で動かす場合は "Azure" を指定します。
{
"Dbms": "PostgreSQL",
"Provider": "Local",
"SaConnectionString": "Server=localhost;Database=postgres;UID=postgres;PWD=SetSaPWD",
"OwnerConnectionString": "Server=localhost;Database=#ServiceName#;UID=#ServiceName#_Owner;PWD=SetAdminsPWD",
"UserConnectionString": "Server=localhost;Database=#ServiceName#;UID=#ServiceName#_User;PWD=SetUsersPWD",
"SqlCommandTimeOut": 0,
"MinimumTime": 3,
"DeadlockRetryCount": 4,
"DeadlockRetryInterval": 1000,
"DisableIndexChangeDetection": true,
"SysLogsSchemaVersion": 1,
"MySqlConnectingHost": "%"
}指定できる値は "Local" と "Azure" の 2 種類です。
初期化時の処理
起動時に Initializer.SetRdsParameters() が呼ばれ、Provider の値が判定されて Environments.RdsProvider に設定されます。"Azure" 以外の値はすべて "Local" として扱われます。
public static void SetRdsParameters()
{
Parameters.Rds.SaConnectionString =
Parameters.Rds.SaConnectionString.Replace(
"#ServiceName#", Environments.ServiceName);
Parameters.Rds.OwnerConnectionString =
Parameters.Rds.OwnerConnectionString.Replace(
"#ServiceName#", Environments.ServiceName);
Parameters.Rds.UserConnectionString =
Parameters.Rds.UserConnectionString.Replace(
"#ServiceName#", Environments.ServiceName);
switch (Parameters.Rds.Provider)
{
case "Azure":
Environments.RdsProvider = "Azure";
break;
default:
Environments.RdsProvider = "Local";
break;
}
Environments.DeadlockRetryCount = Parameters.Rds.DeadlockRetryCount;
Environments.DeadlockRetryInterval = Parameters.Rds.DeadlockRetryInterval;
}この Environments.RdsProvider が、以降の処理分岐のキーになります。
図を読み込み中…
CodeDefiner 実行時の違い
Provider の値が最も大きく影響するのは CodeDefiner の実行時です。Configurator.Configure() は Environments.RdsProvider == "Local" の条件で処理を分岐しています。
internal static bool Configure(
ISqlObjectFactory factory,
bool force,
bool noInput,
bool showLicenseInfo = true,
bool checkMigration = false)
{
if (checkMigration == false)
{
if (Environments.RdsProvider == "Local")
{
UsersConfigurator.KillTask(factory: factory);
RdsConfigurator.Configure(factory: factory);
UsersConfigurator.Configure(factory: factory);
SchemaConfigurator.Configure(factory: factory);
}
if (CheckColumnsShrinkage(
factory: factory,
force: force,
noInput: noInput,
showLicenseInfo: showLicenseInfo))
{
TablesConfigurator.Configure(factory: factory);
if (Environments.RdsProvider == "Local")
{
PrivilegeConfigurator.Configure(factory: factory);
}
return true;
}
return false;
}
else
{
var isCreatingDb = false;
if (Environments.RdsProvider == "Local")
{
isCreatingDb = !RdsConfigurator.Exists(factory: factory, databaseName: Environments.ServiceName);
// ... ログ出力
}
// ...
}
}| 処理 | Local | Azure |
|---|---|---|
| 既存 DB セッションの強制切断(KillTask) | 実行 | スキップ |
| データベースの作成・更新(RdsConfigurator) | 実行 | スキップ |
| DB ユーザーの作成・更新(UsersConfigurator) | 実行 | スキップ |
| スキーマの作成・更新(SchemaConfigurator) | 実行 | スキップ |
| テーブルの作成・更新(TablesConfigurator) | 実行 | 実行 |
| ユーザー権限の付与(PrivilegeConfigurator) | 実行 | スキップ |
Provider: "Azure" を設定した場合は テーブルの作成・更新だけ が実行され、それ以外の DB レベルの操作はすべてスキップされます。
スキップされる処理の内容
KillTask(セッションの強制切断)
Owner ユーザーと User ユーザーの既存 DB セッションを KILL コマンドで強制終了します。CodeDefiner による DB 変更をロックなしで安全に実行するための前処理です。
internal static void KillTask(ISqlObjectFactory factory)
{
KillTask(
factory: factory,
connectionString: Parameters.Rds.OwnerConnectionString);
KillTask(
factory: factory,
connectionString: Parameters.Rds.UserConnectionString);
}RdsConfigurator(データベースの作成・更新)
SA(システム管理者)権限でデータベース自体の作成や更新を行います。PostgreSQL では CREATE DATABASE、SQL Server では同等の DDL が実行されます。
internal static void Configure(ISqlObjectFactory factory)
{
if (!Exists(factory: factory, databaseName: Environments.ServiceName))
{
CreateDatabase(factory: factory, databaseName: Environments.ServiceName);
}
else
{
UpdateDatabase(factory: factory, databaseName: Environments.ServiceName);
}
}UsersConfigurator(DB ユーザーの作成・更新)
_Owner ユーザー(管理者)と _User ユーザー(一般)の DB ログインを作成・更新します。CREATE LOGIN や ALTER LOGIN に相当する SQL が SA 権限で実行されます。
private static string CreateUserCommandText(string uid, string pwd, string host)
{
return uid.EndsWith("_Owner")
? Def.Sql.CreateLoginAdmin
.Replace("#Pwd#", pwd)
.Replace("#MySqlConnectingHost#", host)
: Def.Sql.CreateLoginUser
.Replace("#Pwd#", pwd)
.Replace("#MySqlConnectingHost#", host);
}SchemaConfigurator(スキーマの作成・更新)
CREATE SCHEMA でスキーマを作成し、Owner・User に対してアクセス権を設定します。PostgreSQL での運用を想定した処理です。
internal static void Configure(ISqlObjectFactory factory)
{
if (factory.SqlDefinitionSetting.IsCreatingDb)
{
Def.SqlIoByAdmin(factory).ExecuteNonQuery(
factory: factory,
dbTransaction: null,
dbConnection: null,
commandText: Def.Sql.CreateSchema
.Replace("#Uid_Owner#", ocn["uid"])
.Replace("#Uid_User#", ucn["uid"])
.Replace("#SchemaName#", factory.SqlDefinitionSetting.SchemaName));
}
// ...
}PrivilegeConfigurator(権限付与)
GRANT 文で、Owner ユーザーには管理者権限を、User ユーザーには一般権限を付与します。
private static void Execute(ISqlObjectFactory factory, string connectionString, string host)
{
var cn = new TextData(connectionString, ';', '=');
if (cn["uid"].EndsWith("_Owner"))
{
// GRANT PRIVILEGE ADMIN を実行
}
else
{
// GRANT PRIVILEGE USER を実行
}
}Azure でスキップされる理由
Azure SQL Database は Microsoft が提供するマネージドな PaaS サービスで、ローカル環境とは次の点が異なります。
| 項目 | ローカル SQL Server | Azure SQL Database |
|---|---|---|
| DB 作成 | SA 権限で実行可能 | Azure ポータルや ARM テンプレートで事前作成 |
| SA 権限 | 利用可能 | 利用不可(マネージドサービスの制約) |
| セッション強制終了 | sp_who + KILL で可能 | SA レベル操作は制限される |
| ユーザー管理 | CREATE LOGIN で作成 | Azure AD 認証や SQL 認証はポータルで管理 |
| スキーマ・権限管理 | SA で自由に設定 | 事前に設定済みの想定 |
Azure SQL Database では、DB 作成、ユーザー管理、権限設定などのインフラレベルの管理は Azure が担います。CodeDefiner は「テーブルの作成・更新」だけを担当し、ほかの処理は Azure 側で事前に済んでいることが前提になっています。
アプリ実行時(SysLogs)への影響
アプリケーションの実行時にも RdsProvider が使われます。ログを記録するとき、OnAzure プロパティに Environments.RdsProvider == "Azure" の結果が設定されます。
private void SetProperties(
Context context,
SysLogTypes sysLogType = SysLogTypes.Info)
{
SysLogType = sysLogType;
OnAzure = Environments.RdsProvider == "Azure";
MachineName = Environments.MachineName;
// ...
}この値は SysLogs テーブルの OnAzure 列に保存されるため、ログのフィルタリングや分析に使えます。
タイムゾーンへの影響はない
Azure 環境では OS のタイムゾーンが UTC になることが多いため、Provider: "Azure" がタイムゾーンを UTC にしているように見えることがあります。しかし、Provider の設定とタイムゾーンの処理は 完全に独立 しています。
タイムゾーンは App_Data/Parameters/Service.json の TimeZoneDefault で設定します。
{
"Name": "Implem.Pleasanter",
"TimeZoneDefault": "UTC",
...
}起動時に Initializer.SetTimeZone() が呼ばれ、この値から Environments.TimeZoneInfoDefault が設定されます。
private static void SetTimeZone()
{
Environments.TimeZoneInfoDefault = TimeZoneInfo.GetSystemTimeZones()
.FirstOrDefault(o => o.Id == Parameters.Service.TimeZoneDefault)
?? TimeZoneInfo.Utc;
Def.ColumnDefinitionCollection
.FirstOrDefault(o => o.Id == "Users_TimeZone").Default = Environments.TimeZoneInfoDefault.Id;
}TimeZoneDefault に一致するタイムゾーンが見つからない場合は TimeZoneInfo.Utc にフォールバックします。既定値が "UTC" なので、変更しなければ UTC で動作します。RdsProvider の値はこの処理に一切関与しません。Azure 環境で UTC になるのは、Service.json の設定とサーバー OS のタイムゾーンが UTC であることが原因です。
タイムゾーンの考え方は タイムゾーンの考え方 を参照してください。