heroku connect 苦肉の四苦八苦
TRANSCRIPT
Heroku Connect苦肉の四苦八苦
大久保英樹
自己紹介
• 名前:大久保英樹
• 職業:フリーランスプログラマ
• アカウント:@Oakbow7
• Herokuを扱う案件は8個目くらい?
• Heroku Connectを扱う案件は4個目くらい?
4U Lifecareとなでしこナース
• フォー・ユー・ライフケア株式会社• https://4ulifecare.com/
• 医療系スタートアップ
• 活用が限定されている医療人材を活かす
• なでしこナース• https://nadeshikonurse.jp/
• 看護師向けの人材紹介サービス
• 利用ユーザは看護師と病院・施設
なでしこナース
病院・施設看護師
運営者
管理管理
求人に応募
採用
Heroku Salesforce
Salesforce
なでしこナース
SalesforcePartner
Commyunity病院・施設
Heroku看護師
Salesfoce運営
HerokuConnect
今日お話しすること
• Heroku Connectおさらい
• インピーダンスミスマッチその1• Heroku と Salesforceの双方向同期で、IDをどうするか
• インピーダンスミスマッチその2• Salesforceのキャメルケース文化とRailsのスネークケース文化のギャップの解消
• 現在の開発サイクル
Heroku Connectおさらい
HerokuConnect
HerokuPostgres Salesfoce
Heroku Connectおさらい
• SalesforceのオブジェクトとHeroku Postgresのテーブルを双方向に同期してくれるアドオン
• あくまでも主となるのはSalesforceオブジェクト。同期対象のオブジェクトとそのカラムをHeroku Connectコンソールで選択すると、オブジェクトに対応したテーブルが自動生成される。逆方向はできない
• Heroku PostgreSQL -> Salesforceの同期時、Salesforceのヴァリデーションに引っかかると同期エラーが起きる。
Heroku Connectおさらい
• テーブル作成はHeroku Connectを介してしか行えない(フレームワークのマイグレーション機能は原則そのまま使えない)
• Salesforce側のオブジェクト定義に依存するので、テーブル名、カラム名やデータ型、データ長さは変更できない
• 親と子どちらのレコードが先に同期されるか分からないので、FK(外部参照制約)は使えない(貼ることは可能だが、FKエラーで同期失敗する)
• サロゲートキーとしてIDカラムが生成されるが、Salesforce側には同期されない
Heroku Connectおさらい
HerokuConnect
HerokuPostgres
Salesfoce
Rails
Railsの期待するデータベーススキーマ(理想)
Heroku Connectが作るデータベーススキーマ(現実)
Heroku Postgres
Heroku Postgres Salesforce
id
sfid ← sfid
mofid__c ⇄ mofID__c
body__c ⇄ Body__c
read__c ⇄ Read__c
name ⇄ Name
usermofid__c ⇄ UserMofId__c
user__c ⇄ User__c
conversationmofid__c ⇄ ConversationMofId__c
conversation__c ⇄ Conversation__c
createddate ⇄ CreatedDate
systemmodstamp ⇄ SystemModStamp
isdeleted ⇄ IsDeleted
conversations__r__mofid__c
user__r__mofid__c
インピーダンスミスマッチその1
• PKをうまく同期できない• Salesforce側のPKはsfid
• Heroku Postgres側のPKはid
インピーダンスミスマッチその1
• 結合にsfidを使用した場合
• Heroku側でレコードをInsert(sfidはNULL)• InsertしたレコードをSalesforceに同期• Salesforceでsfidを発番• 更新したレコードをHeroku Postgresに同期
• PKを取得するために同期が二回必要• HerokuにとってはSalesforceは所詮外部サービスなので、PKが外部依存なのは開発する上で非常に不利(ローカルでどう開発する?テストは?CIで回せる?)
インピーダンスミスマッチその1
インピーダンスミスマッチその1解決編
• 結合に外部IDを使う(データ型は文字列型)
• Heroku側でレコードをInsertするときはPostgreSQLのシーケンスを突っ込む
• Salesforce側でレコードをInsertするときは、トリガでsfidを突っ込む(1トランザクションで実行するよう頑張る)
• idでもsfidでもない外部IDカラムexernal_id(ExternalId__c)を作り、これを同期する。
• Heroku Postgres ではこのカラムをPKに指定(照合順序に注意)
• Salesforceではこのカラムを外部IDとして設定する
インピーダンスミスマッチその1解決編
インピーダンスミスマッチその1解決編
インピーダンスミスマッチその1解決編
インピーダンスミスマッチその1解決編
インピーダンスミスマッチその1解決編
インピーダンスミスマッチその1解決編
インピーダンスミスマッチその1解決編2
インピーダンスミスマッチその2
• Salesforceはキャメルケース文化なので、オブジェクトやフィールド名は基本的にキャメルケース
• カスタムオブジェクトやカスタムフィールドは、末尾に__cが必ずつく(キモい)
• PostgreSQLのテーブル名やカラム名は大文字小文字を区別しない(ので、小文字で表現される)
• Railsはスネークケース文化
• レコードの作成日時、更新日時のフィールド名(カラム名)はそれぞれ異なっている
インピーダンスミスマッチその2
Rails(理想) PostgreSQL(現実) Salesforce
updated_at systemmodstamp SystemModStamp
created_at createddate CreatedDate
work_location_address1 worklocationaddress1__c WorkLocationAddress1__c
contract_start_on contractstartdate__c ContractStartDate__c
emergency_contact_details emergencycontactdetails__c EmergencyContactDetails__c
id externalid ExternalId
opportunity_technical_skill opportunitytechnicalskill__c OpportunityTechnicalSkill__c
インピーダンスミスマッチその2解決編
Rails ModelDB View
(Updatable View)
DB Table
インピーダンスミスマッチその2解決編
インピーダンスミスマッチその2解決編
インピーダンスミスマッチその2解決編
インピーダンスミスマッチその2解決編
インピーダンスミスマッチその2解決編
インピーダンスミスマッチその2解決編
環境 環境変数 Salesforce テーブル作成 カラム追加 カラム削除
ローカル開発 development なし される される される
ローカルテスト
test なし される される される
CI test なし される される される
Review App production なし される される される
ステージング production あり されない されない されない
本番 production あり されない されない されない
ミスマッチを解消
HerokuConnect
HerokuPostgres
Salesfoce
RailsRailsで扱いやすいように作った
更新可能ビュー
Heroku Connectが作るsalesforceスキーマ
Heroku Postgres
現在の開発サイクル
Review App
feature branchlocal Circle CI
master branch Staging
Production
Pull Request Auto Testing
Merge
Auto Deployment
Promoting
Create Review App
現在の開発サイクル