2014年6月19日 (木)

HerokuでPlay2のコンパイルを速くする

昨日別件(Play起動時にGruntも実行する)で教えてもらったドキュメントです。

http://www.playframework.com/documentation/2.4.x/SBTCookbook

なんと、この文書の下の方に「Disable documentation」として、コンパイル時のScalaDocの生成を止める方法が記載されています。

やり方はbuild.sbtに以下を記述するだけ

 

sources in (Compile, doc) := Seq.empty

publishArtifact in (Compile, packageDoc) := false

 

このドキュメントは未リリースの2.4のものですが2.3でも問題なく動きます。

実測で2分くらい速くなりました。素晴らしい(^^v

2014年6月13日 (金)

WebSocketリクエストのヘッダ

なんとなくWebSocket APIの動作が思った通りにならなかったので、各種ブラウザのWebSocket接続リクエストのHeaderを調査しました。

このサイトではCookieを使ってないのでヘッダにCookieでてませんが、使っていれば普通にCookieが出力されます。

あと、Herokuのルータが付けてるヘッダ(x-forwarded-forなど)はカットしました。

★Chrome
cache-control: no-cache  
connect-time: 4  
connection: Upgrade  
Content-Length: 0  
Host: room-sandbox.herokuapp.com  
origin: http://shunjikonishi.github.io  
pragma: no-cache  
sec-websocket-extensions: permessage-deflate; client_max_window_bits, x-webkit-deflate-frame  
sec-websocket-key: (snip)
sec-websocket-version: 13  
total-route-time: 1  
upgrade: websocket  
user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36  
via: 1.1 vegur  

★Firefox
accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8  
accept-encoding: gzip, deflate  
accept-language: ja,en-us;q=0.7,en;q=0.3  
cache-control: no-cache  
connect-time: 2  
connection: Upgrade  
Content-Length: 0  
Host: room-sandbox.herokuapp.com  
origin: http://shunjikonishi.github.io  
pragma: no-cache  
sec-websocket-key: (snip)
sec-websocket-version: 13  
total-route-time: 0  
upgrade: websocket  
user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0  
via: 1.1 vegur  

★IE11
cache-control: no-cache  
connect-time: 1  
connection: Upgrade  
Content-Length: 0  
Host: room-sandbox.herokuapp.com  
origin: http://shunjikonishi.github.io  
sec-websocket-key: (snip)
sec-websocket-version: 13  
total-route-time: 0  
upgrade: Websocket  
user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko  
via: 1.1 vegur  

★Mac Safari
cache-control: no-cache  
connect-time: 1  
connection: Upgrade  
Content-Length: 0  
Host: room-sandbox.herokuapp.com  
origin: http://shunjikonishi.github.io  
pragma: no-cache  
sec-websocket-extensions: x-webkit-deflate-frame  
sec-websocket-key: (snip)
sec-websocket-version: 13  
total-route-time: 1  
upgrade: websocket  
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.76.4 (KHTML, like Gecko) Version/7.0.4 Safari/537.76.4  
via: 1.1 vegur  

★Android
cache-control: no-cache  
connect-time: 0  
connection: Upgrade  
Content-Length: 0  
Host: room-sandbox.herokuapp.com  
origin: http://shunjikonishi.github.io  
pragma: no-cache  
sec-websocket-extensions: permessage-deflate; client_max_window_bits, x-webkit-deflate-frame  
sec-websocket-key: (snip)
sec-websocket-version: 13  
total-route-time: 0  
upgrade: websocket  
user-agent: Mozilla/5.0 (Linux; Android 4.1.2; P-02E Build/JZO54K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.141 Mobile Safari/537.36  
via: 1.1 vegur  

★iPad
cache-control: no-cache  
connect-time: 0  
connection: Upgrade  
Content-Length: 0  
Host: room-sandbox.herokuapp.com  
origin: http://shunjikonishi.github.io  
pragma: no-cache  
sec-websocket-extensions: x-webkit-deflate-frame  
sec-websocket-key: (snip)
sec-websocket-version: 13  
total-route-time: 0  
upgrade: websocket  
user-agent: Mozilla/5.0 (iPad; CPU OS 7_1_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D201 Safari/9537.53  
via: 1.1 vegur  

□□□□

ほとんど余計なヘッダはついてないですね。

Firefox以外はAccept, Appcept-Encoding, Accept-Languageはついていません。

なるほど。確かにHTMLページを返すことを目的としたプロトコルではないので付ける必要ないですね。

納得いきました。

2014年6月10日 (火)

S1dcmaxでWebSocketの話をしてきた

ども、小西です。

昨日6月9日にビルボードライブ東京で行われたSalesforce1 Developers Community MAXというイベントでWebSocketの話をしてきました。

会場名をもう一回言うけどビルボードライブ東京だよ!Googleのインドアビューで見るとこんなだよ!!

なんでこんなところでテッキーな話を。。。と思ったけど見る側にしたら机もあって良かったのかも。(^^;

発表資料はこれ。

http://shunjikonishi.github.io/slides/websocket/index.html


持ち時間に対してとにかく内容を詰め込んだので置き去りにされた人も多かったかも。。。

あいすいません。m(_ _)m


資料はそれだけ見ればわかるように作ったつもりなので、気になる人は見てくだされ。
プレゼン中に口頭でのみ説明した内容もだいたい文章で入ってます。

春頃からこのブログでも何度もWebSocketの話題をとりあげていて、言いたいこともたくさんあったんだけど、だいたいこれで全部吐き出せたかな。(^^;


セキュリティの話とかWebSocketをAjaxの代替として使う話とかは他ではあまり見かけたことがない内容で個人的には結構満足してるけど、果たして一般受けするかどうかは謎。。。(^^;

以下今回のイベントでの個人的なトピックです。


★Happy HourにまさかのQuizar

今回Salesforceの岡本さんのご厚意(?)で、Happy Hourの余興で3月に作ったQuizarによるクイズゲームが行われました。優勝賞品はプレステ4!!

多分50人くらいが参加してたんじゃないかな?ぶっちゃけこれまでにそんな人数での実践をしたことはなかったんだけど、まぁ普通に動いて良かった。(^^;

ちなみにこれ元々は参加人数は最大50人に制限してたのを、200人まで参加可能なように会場でその場で修正しました。(^^;

作った当時はどの程度の同時接続を捌けるのかに関してあまり確信がなかったけど、その後にやったC10Kのテストの感触から言うとDynoを増やせば1000人とかでも普通に捌けるとは思います。(これが数万、数十万のオーダまでいけるようであれば、テレビとかでも使えそうだけどさすがにそれは自信ないなぁ。。。クライアントへのpushをもうちょっと賢くすればできるかもしれないけど。)

まぁ機会(と度胸)があれば試してみてください。(^^;
何にせよ会場の皆さんにWebSocketアプリを体感してもらえたのは良かったと思います。岡本さんありがとうございました。

Quizarは特に宣伝しているわけでもなく、この先大幅な機能追加が行われることもないと思うけど、ひっそりと営業中なので勉強会等をやる機会のある人は使ってみてください。
ご意見、プルリク等は歓迎します。(^^;

スターがいっぱいつくと開発/運営方針とかも変わるかもよ?(^^;


★@i556 HackChallenge癒しアプリケーション部門で優勝

同僚の@i556が見事優勝して10万円GET!!!

おめでとう!!!
そしてごちそうさま!(と、先に言ってみる)

作ったアプリはタスクを癒し系アイコン(タスクの達成度が高いほど癒し度アップ)でカレンダー上に表示してユーザーのモチベーションを上げるというもの(で、あってるよね?)


優勝者発表の前から猫には勝てると思っていたよ。
本当におめでとう。

ちなみにHeroku賞はまさかの該当者なし。。。
もうちょっと早くにお題出しとけよ。。。(--

自分のプレゼンでテンぱっててそれどころじゃなかったんだけど俺もなんか出しておけば良かった。(--


★REVEAL.jsの話

ちょろっと聞かれたけど、今回プレゼンに使ったREVEAL.js。はっきり言ってイケてる。
ていうか、プログラマが使うプレゼンツールとしては最強なんじゃなかろうか。
なにせ、基本マークダウンだけでプレゼンが作れて足りないところはHTMLとJavaScriptでどうにでもできるので。

興味のある人はサンプルサイトを覗いてみると良いと思う。
ストーンズの50年とかマジかっこよくてお勧め。

とりあえず試してみたい人は

https://github.com/shunjikonishi/slides

をcloneしてgrunt起動すれば動きます。
基本content.mdだけ編集すれば良いのでドキュメントとかまったく読まなくてもそれなりに使えると思う。

今回使ったプログラム要素は

  • プレゼンの残り時間とスライド一枚当たりの時間を画面に表示
  • iframeでアプリ埋め込み
  • お絵描きのWebSocketサンプル埋め込み
  • setIntervalのデモ
  • js-sequence-diagramsの埋め込み(ただしブラウザのSVGのレンダリングにバグがあるのか表示が安定しなかったため本番ではイメージに差し替え)

など。
今朝になってトップにTwitterとFacebookのソーシャルボタンも追加してみた。(^^;

これ本当に何でもできるのでTwitterのTLを埋め込むとか、アイデア次第で色々なことができそう。
WebSocketを使えばそれこそ聴衆参加型のプレゼンもできるはず。
なんか思いついたらそのうちどこかでチャレンジしてみたい(^^;

2014年5月29日 (木)

Reveal.jsとRemotes.ioのコンボがいけてる話

ども、小西です。
社内勉強会向けにGrunt超入門というスライドを作りました。

http://shunjikonishi.github.io/slides/grunt-introduction/index.html

URLを見るとわかると思いますがスライドの公開先はGitHub Pagesです。
スライドの中身のGruntについては既に良記事もたくさんあって、今さら感もあるので割とどうでも良いんですが、今回紹介したいのはこれを作成するのに使ったReveal.jsというWebプレゼンライブラリについてです。

これ、「パワポなんか頼まれたって触ってやらねー!」というツワモノの同僚が見つけて作成したものをパクってマークダウンだけ書き換えて作ったんですが、これがなかなかいけてます。(^^v


★ Reveal.js

僕は知りませんでしたが割と有名なライブラリのようです。
日本語でも紹介記事がけっこう見つかりますが、やっぱり一番わかりやすいのは本家のWebサイトでしょう。

http://lab.hakim.se/reveal-js/#/

Reveal.jsの紹介自体がReveal.jsで作られたスライドで紹介されています。
これ見ればだいたい何ができるかはわかると思います。

個人的に良いと思うのは

  • マークダウンだけでスライドが作れる
  • HTMLやJavaScriptとの組み合わせも可能
  • スタイルやレイアウトはCSSで調整可能
  • jsオンリーなのでGitHub.ioで公開可能
  • ローカルではGruntで起動するnode.jsのサーバでライブリロードで動作確認できる
  • PC上のスライドをスマホで操作できる


というあたりです。
一番驚いたのは最後のスマホ連携で、これは最近すっかりおなじみのWebSocketですよ。

PCでスライドを表示すると画面右にちょっと邪魔な感じで電源マークみたいなのが表示されていると思いますが、ここをマウスオーバーするとQRコードが表示されそれをスマホで読みこむとリモートにあるWebSocketサーバを介してスマホとPCが接続され、スマホでのスワイプ操作によってスライドのページ送りができるという仕組みです。

なるほど。WebSocketにはこういう使い方もあるわけですね。今ならWebRTCでもできそうですけど、これはこれで面白い使い方だと思います。

で、それ以上に面白いと思ったのはこの機能がReveal.js単体で実現されているのではなく別サービスとの組み合わせで実現されているという点です。


★ Remotes.io

その組み合わせとして使われているサービスがRemotes.ioです。

http://remotes.io/

これはWebSocketで接続されているホストに対してスマホで発生したイベント(右スワイプとかタップとか)を通知するだけのサービスです。

Remotes.ioを利用するサイトはまずRemotes.ioが提供するJavaScriptをページにインクルードします。

そうすると先に見たようなQRコードが画面に組み込まれます。
そこにスマホが接続されるとRemotes.ioによってスマホ側で発生したイベントが通知されるので後はサイト側でそれらのイベントに対応するイベントハンドラを書けばOKです。(Reveal.jsではスワイプイベントをスライドのページ送りに対応させています。)
QRコードはスマホとの接続が確立されると画面から消えるので複数のスマホが1台のPCに接続されることはありません。


いやー、これは本当に驚いたアイデアです。
WebSocket、使い方次第で色々と面白いことができそう!ということを最近色々なところで主張しているんですがその可能性を示してくれる事例だと思います。(^^v

2014年5月23日 (金)

Heroku Meetup #12

行ってきました。
ていうか、LTしてきました。(^^;

今回は同僚の@i556の発表があったり、がちゃぴん先生(@kosaki55tea)の濃ゆいカーネルの話があったりで、非常に面白かったです。


★ WordPress On Heroku

http://www.slideshare.net/kokorojw/wordpress-on-heroku

いや思った以上に良く調べていたんでびっくりした。(^^;
普段結構とっぴょうしもないことを言ってることが多いので、どんな発表になるのかと思ってたけど、資料も過不足なくわかりやすくまとまっていて良い感じ。

そういえば前に社内で発表してたデザインの話にもとても感心したことを思い出し、実はできる子です。> @i556(^^;

WordPress使ったことがないのでHerokuでWordPressが動くことのインパクトがどれくらいあるのか正直よくわからないんだけど、やりたい人がたくさんいるのであればもうこの際、

WordPress込みでbuildpack作っちゃえば良いんじゃね?

とちょっと思いました。
ClearDBやCloudinaryの無償版をbuildpackで追加することはできるはずだし、DBのURLをファイルに転記することもbuildpack内でできます。(Heroku的にはPostgresを使って欲しいだろうけど。)

ID/Passwordはとりあえず環境変数に自動生成したものを書きだしておいて、設定ファイルでそれを見るようにするか、あるいは「.profile.d」にログインスクリプトを用意してDyno起動時に設定ファイルを書き換えるという方法でもできそうです。

WordPress本体はgitでバージョン管理するようなものではないだろうし、これができれば一度もgit pushしないでWordPressを動かすことができる気がするんだけどできないかな?(^^;

(。。。と書いてるそばから気が付いたけど一度もgit pushしないとSlugコンパイル自体が走らない気がする。PlatformAPIのSlug関連のAPIをbuildpackから叩くことができればなんとかなるかもしれないけど、ちょっと難しいかも。。。)

しかしまぁ少なくとも手順を大幅に簡略化することはできるはず。
気が向いたら試してみれ。 > @i556(^^;


★ Linux Container Update

http://www.slideshare.net/kosaki55tea/linux-container-update

正直Kernelの話とか完全に守備範囲外なわけですが、お話とても面白かったです。(というか、わかるように話をしてくれていたと思う。)

レイヤが違ってもやってることも考え方もあんまり変わらないですね。ただ考えなきゃいけないことの種類が全く違うだけで。

その中で一番興味を惹かれたのはやっぱりLive Migrationの話コンテナプロセスを丸ごとコピーして他のホストで復活させる。マジでか!!!

個人的には本当にちゃんと動くの?というところかなり懐疑的だけど理屈はわかります。

死にそうなプロセスをコピーしても、コピーした先でやっぱり死ぬだけなんじゃないの?と思って先生に質問したところそれはやっぱりその通り、とのこと。

使いどころとしては1ホスト内で複数のコンテナをあげる運用している事業者が、なんらかの閾値を決めてホストを監視して、閾値を越えて動作がやばそうになったコンテナがあったら他のまっとうなコンテナをLive Migrationする、みたいな感じになるんだと思う。

。。。それは凄いな!!!
この技術が浸透して当たり前のものになると、ハードの寿命を越えて永遠に動き続けるプロセスを作ることも不可能ではないってことか!(実際にはその間にOSのアップデートなんかがあって現実的ではないだろうけど。)

非常に先行きが楽しみな技術です。(^^


★ My LT: 一番簡単なWebSocketの試し方

http://www.slideshare.net/shunjikonishi/websocket-34998961

多くは語るまい。
6/9のSalesforce1 Develper Community MAXに話を聞きにきてくださいっちゅーことですよ。(^^;


2014年5月16日 (金)

APIサーバでCORSを使う

昨日はSODECに行ってきました。

最近はこうした展示会でこれはスゲー!という衝撃をうけることは少ないんですが、プロダクトを見る時に「どういう風に作ってるんだろうなぁ」ということを想像しながら眺めているせいか、ちょいちょい今まで考えもしなかったようなことを思いつきます。(毎回そうなんですが思いつく内容が特定のプロダクトからの直接の連想でないところが不思議なところです。ほとんどの場合帰り道や寝る直前などにふと降りてきます。(^^;)

今回の話はその思いつきの内容のメモです。

あ、あと知人の吉田さんに著書をいただきました。

帰りに1章だけ読みましたが、自分(開発者)とは違う視点からセキュリティを俯瞰している印象でなかなか興味深いです。

技術者だけでなく経営層の人も読んでみると良いかも。(ステマ)

 

★ CORSとは

Cross Orign Resource Sharingの略でその名の通り異なるドメインでリソースを共有するための仕組みです。

JavaScriptにはSame Origin Policyがあるので通常は異なるドメインのREST APIをAjaxでたたくことはできませんが、CORSを使うとそれが可能になります。

資料としてはこれがわかりやすいです。

https://developer.mozilla.org/ja/docs/HTTP_access_control

一番有名な実装例はおそらくAmazon S3で、CORSを利用することでブラウザからのファイルのS3への直接アップロードを可能にしています。

 

★ CORSのサーバサイド実装

上記リンク先を見ると実装に必要なことはだいたいわかるんですが、大まかにまとめると以下のようになります。

  • HttpResponseのAccess-Control-Allow-Originでアクセスを許可するOriginを指定する
  • 同じくAccess-Control-Allow-Methodsで許可するメソッドを指定する
  • プリフライトリクエストに備えてHTTPメソッドのOPTIONSに対応する
  • Cookieを使用する場合はAccess-Control-Allow-Credentials: true をつける

ほとんどHttpヘッダの制御だけなのでたいていのフレームワークではハンドル可能です。唯一OPTIONSへの対応だけが不安でしたが、とりあえずPlayframeworkではroutesに普通に「OPTIONS /hogehoge ...」を定義するだけでいけました。

クライアント側はブラウザがよしなにやってくれるので基本的には自分で実装すべきものはありません。(というかHttpClient自体を自前で用意するのであればそもそもSameOriginPolicyの制限を受けないので何もする必要がありません。)

唯一Cookieを利用する場合は自分でxhr#withCredentialsをtrueにする必要があります。jQueryだとやり方にすこし癖がありますがこの辺を見ればすぐにできると思います。

 

★CORSをAPIサーバで使うことを考える

さて、このCORS。僕はS3の事例でしか使ったことがなかったので静的に設定するモノという先入観があったんですが、よくよく考えるとHttpヘッダだけの対応なので動的に変更することが可能です。

例えばユーザ毎に固有のURLを用意するようなサービスの場合、URL毎にAccess-Control-Allow-Originを変更することは楽勝でできますし、認証後にすべてのユーザに対して同一のURLでAPIを提供するようなサービスであってもCookie併用で切り替えることができるはずです。

これで指定のドメイン以外からのリクエストをはじくことができますが、curlやChromeのコンソールなどからでも簡単に偽装リクエストを送ることはできるのでセキュリティ要件は別途考えなければなりません

あとは、ブラウザからの直接アクセスをはじくためにOriginヘッダのないリクエストははじくなどの対応を入れても良いでしょう。

これらができると、今まではSameOriginPolicy回避のためにサーバから実行するしかなかった外部APIの実行がブラウザ上から直接できるようになるので、アプリの可能性は大きく広がりそうな気がします。

 

★ 既存サービスの実装状況など

自分に思いつく程度のことだから既存のサービスではもう結構実装されてるんじゃないの?とおもってざっと検索してみましたが、あんまりそういうサービスない(追記)みたいですね。

Salesforceで検索してみたら3年も前によく見知った人が対応しろや!と声をあげていて流石と思いましたが、未だ対応されていないようです。残念。。。

その中で異彩をはなっているのは我らがHerokuです。

https://devcenter.heroku.com/articles/platform-api-reference#cors

え、「*」で許可してるってこと???

それは流石にやりすぎなんじゃ。。。(--

つーことは、つまりHeroku DashboardはGitHub.ioでも作れるってことですね。(^^;

(追記)

文中のよく見知った人(冨田さん)から、Google+ API, Facebook Graph API, GitHub APIがCORSに対応していることを教えていただきました。ありがとうございます。

これらも「*」で許可しているみたいですね。先行して認証があるAPIの場合はそれもアリな選択肢ということなんでしょう。

2014年5月14日 (水)

Heroku Connect来ました

Heroku ConnectがGAになったようです。

https://blog.heroku.com/archives/2014/5/13/introducing_heroku_connect

と言っても現状では使うためには直接コンタクトをとる必要があるようです。
以下、ざっとドキュメントを読んだまとめと感想です。節立てはドキュメントを踏襲していますが、個人的に引っ掛かったところを中心にまとめているだけで決して翻訳ではないので、ん?と思った方は原典をあたってください。(^^;


ちなみに1節読む毎に書いていたので先に書いた疑問が後で自己解決していることもあります。具体的にはINSERTに関する推測が最後に全部ひっくり返ります。直そうかとも思ったんですが、文章の流れもあるのでそのままにしました。


★ How Heroku Connect works

  • Heroku ConnectはSalesforceオブジェクトのレプリカをPostgreSQL上に作成するもの
  • テーブル名、列名はSalesforceと同じになる(ただし小文字)
  • Salesforce、DBの変更が双方向に同期する
  • SF -> DBの同期には「LastModifiedDate」列を利用する
  • DB -> SFの同期にはDatabaseのトリガーを利用する
  • DBの変更の反映はUserPermissionsとValidationRulesの影響を受ける
  • DBの変更は変更されたカラムのみが更新対象となる


これを読む限りSalesforce側になんらかのこのためのオブジェクトが仕込まれたということはなく、完全に外部からAPIの制御だけで作られているように見えます。

スキーマは常にSalesforceと完全に同じになるのかな?
そうだとすると以下の点が気になります。

  • 必要な列のみをDBに持たせることはできないのか?
  • スキーマの変更にどのように対応するのか?(最低限列の追加には対応してほしい)
  • ID列の扱いは?これがそのまま主キーになるの?


特に最後のID列の扱いは気になるところで、実はDB側ではUPDATEはできてもINSERTはできないんじゃないの?という気がします。(IDが生成できないので)
あと、DELETEの扱いはどうなるのかというのも気になるところです。

INSERTが扱えないんじゃないかと思う根拠はもう一個あって、以前にDB -> SFの片方向同期を自前で実装した時に参照(親子)関係の扱いがけっこう面倒だった記憶があるからです。

必ず親を先に同期するとか、外部キーが必要などいくつか注意すべき点があるんですが、その辺が考慮されているとはここからは読み取れません。


★ Synchronization frequency

  • デフォルトではSFの変更検知のポーリングは10分単位
  • ただしHeroku ConnectのUIを開いている間は3分になる
  • デフォルトではDBの変更検知のポーリングは5分単位
  • ただしHeroku ConnectのUIを開いている間は1分になる
  • Fast Synchモードにした場合更新頻度は30秒に一回になるがその分APIを消費する(Developer Editionの場合はほぼ間違いなくAPIを使いきる)


DBトリガーを使っているにも関わらずポーリングもあるということは、トリガーで行っているのは管理用の別テーブルへのINSERTだけでそれをまとめて更新しているってことでしょうね。5分の間に2回更新が発生したら2回のUPDATEが実行されるんですかね?(それで問題ないと思いますけど)


★ Heroku Connect and Salesforce API consumption

  • 同期オブジェクト1つにつき約500のAPIを消費する
  • リードオンリーモードの場合はAPIの消費はもう少し少ない
  • APIは更新ボリュームによってSOAPとBulkを自動的に使い分ける
  • DB -> SFで1度に更新できるのは200レコードなので10000レコードの更新は50APIを消費する
  • 初回の同期(全データコピー)は500万レコードで120分程度かかる(外部IDがない場合)


残念ながらAPIの優遇は一切ないようです。。。(--
1度に200件というのもSOAP APIの制限そのままですし。

初回120分というのはBulkを使ってもこれ位ってことですかね。(SOAPだとどう考えてももっと遅そうだし、Bulkを使わない理由がない)
スループットにすると694件/秒なのでそんなもんかとも思いますが、速いCPUのDBを使っていればもうちょっと速いんじゃないかとも思います。

外部IDの有無で性能が変わるというのはDB側でもForeign keyをちゃんと定義しているということでしょう。


★ How Salesforce objects map to Postgres database tables

  • セットアップ時にオブジェクトに対応するテーブルが自動で作られる
  • テーブル名、列名はSalesforceオブジェクトと同じ(ただし小文字)
  • DBの主キーはAuto Increment
  • SFのIDは「sfid」という列となりUnique Indexが付与される


先に書いたIDに対する疑問の回答が書かれていました。
これを読む限りやっぱりINSERTはできそうにない気がします。


★ Provisioning the add-on

  • Heroku Connectはアプリと同じリージョン(US or EU)に配置される
  • アドオンを追加したら最初にWebUIでセットアップをする
  • 設定項目は対象DB、使用するDBのスキーマ名、SF認証情報など
  • SF認証に使用するユーザーは十分な権限を持っている必要があるので連携専用のユーザーを用意することが望ましい。


ブログアナウンスでは使いたい人は直接連絡しろとありましたが、CLIのheroku addons:addで追加できるみたいですね。(試してませんが。)
日本でSalesforceを使う場合は当然日本に置くので、Herokuもとっとと日本リージョンを持ってこいっちゅー話です。

関係ないですけどCLIからアドオンの管理画面をコマンドで開けるということを初めて知りました。


heroku addons:open papertrail -a xxxx


地味に便利です。


★ Mapping objects

  • WebUIで同期するオブジェクトの設定ができる
  • SFユーザに「View All Data」と「API Enabled」の権限が必要
  • あとは一覧からポイント&クリックで設定できる
  • 同期の状態はWebUIで確認できる


どうやら同期する列も選択できるらしい。

WebUIがどの程度の情報をサポートしているのかは気になるところ。


★ Resolving read errors

認証に使用するSFユーザに十分な権限がなかったり、オブジェクトに読み取り制限がかかっている場合は同期が正しく実行できないという話


★ Accessing the synchronized tables

DB側でのデータへのアクセス方法。普通にログインしてSELECTするだけ。スキーマがデフォルトでは「salesforce」になっているのでpsqlを使う場合はsearch_pathにsalesforceを加えると良い。


★ Updating data in Salesforce

  • デフォルトはReadOnlyモードなのでDBの更新を反映するにはRead/Writeモードに変更する
  • DBの更新は<テーブル名>_trigger_logsというテーブルに記録され、それを元に更新が行われる
  • DB -> SFの更新結果は「SUCCESSFUL」「IGNORED」「FAILED」のいずれか
  • SUCCESSFULのデータはtrigger_logsから削除されるが、それ以外は残る


予想通り、DBトリガで別テーブルにINSERTしているだけのようです。
IGNOREDっていうのはどういう時に発生するんでしょうね?また、SUCCESSFUL以外のレコードは残り続けるとありますが、それがいつ消えるのかとかリトライはされないのかというのも気になります。


★ Inserting records to Salesforce

なんと!ここまでの予想を覆してDBへのInsertは可能だそうです。
どうやって実現しているかというと単純にsfid列はNULLABLEなのでそれは無視して、必要な列のみでINSERTするだけ。
あとは同期のタイミングでsfid列が自動で設定されるようです。
ちなみにINSERT後に同期が走る前にUPDATEやDELETEが行われた場合も、それらはちゃんとマージされる(DELETEの場合は何もなかったことになる)ようです。
master/detail関係のレコードも外部IDが設定されていればちゃんと反映されるとのこと。

先に書いた参照関係に対する懸念についても丁寧に説明されています。
ここに来てHeroku Connectへの評価は10段階位跳ね上がりました。(^^v


★ Using External IDs to manage relationships

AccountとContactを例に参照関係の解決のための外部IDの設定方法が書かれています。
要するにAccount側に外部ID列を追加しておけば、同期時にそれを利用することができるってことですね。

若干冗長ですが、これは仕方ないかな。。。


★ Resolving write errors

認証ユーザに十分な権限がなかったり、SFオブジェクトのValidation Rulesに引っ掛かった場合にはエラーとなる。
あるいは計算フィールドも同期可能だが、そこへの書き込みはエラーとなる。

これらのエラーはDBに記録されWebUIから確認できる。


★ Schema changes

スキーマ変更は問題なし。
列の追加はHeroku Connectの動作に何の影響もなく、その列を同期したいならマッピングを追加すれば良い。既存行の値はその時に同期される。

列の削除や変更では同期がエラーになるのでマッピングの変更が必要


★ Pausing Heroku Connect

WebUIからHeroku Connectの同期を一時的に停止できる。

オブジェクト単位ではできなくて、全体での停止しかできないらしい。


★ Import and export of configuration files

yaml形式でマッピングのインポート/エクスポートができる。
Sandboxで定義したマッピングを本番に移行する場合などに有用


★ Notifications

エラーや同期処理が60秒以内に終了しない場合などにはオーナーに対してメール通知が飛ぶ


★ Security

Heroku ConnectはSalesforceのOAuthトークンを保存している。
データ転送はすべてSSL。

ふと気になったけど、Heroku ConnectのIPは固定されるんですかね?
Salesforce側でAPIのIP制限がかかっている場合の対処方法があるのかどうかはちょっと気になるところです。


★ Using Heroku Connect and the demo Rails app

Heroku Connectを使ったRailsのサンプルアプリがあるのでまずは試してみるが良い。
このサンプルアプリではAccoutとContactを同期する
セキュリティについては特に考慮されてないので間違ってもこのデモアプリを本番環境のSalesforceで動かしてはいけない


★ Removing Heroku Connect from your Heroku app

WebUIからもCLIからも削除可能


★ FAQ
★ Support

省略。
なんかリトライする場合はtrigger_logsテーブルを直接UPDATEすれば良い、みたいなことが書かれていてなかなか衝撃的(^^;


□□□□
以上、同期処理自体はほとんど自力でやった時と同じようなものですが、WebUIで同期状況が継続的に監視できるのは良いですね。
どうでも良いけど料金体系がどこにも記載されてないような。。。

2014年5月 8日 (木)

GitHub pagesの運用を考える

なんか色々手を広げすぎてて自分の首を絞めている。。。(--
WebSocket関連だけでも書きたいことはわりといっぱいあるけど、なかなか手が回らない。。。
なのに今回も脱線ネタ(^^;

GitHub pages

ちょっとしたオープンソースのプロジェクトを作るのであれば、ソースはGitHub、ホームページはGitHub pagesで作成するのが一番お手軽だと思う。

GitHub pagesとはGitHub上で「gh-pages」というブランチを作成するとその内容をWebページとして公開できる機能のこと。機能自体の説明はかなり今更なので知らない人はググってくだされ。(^^;

さて、このGitHub pages。実体としては単なるGitブランチなので、素直に使おうとするとプロジェクトのルートで「git checkout gh-pages」としてブランチを切り替えながら管理することになる。

が、プロジェクトのソースとGitHub pagesで公開したいWebコンテンツはまるっきり異なるので、checkoutの度にディレクトリ構造がごっそりと入れ替わるのはできればさけたい。

個人的にはこのあたりの管理要件として

  • ソースとGitHub pagesのWebコンテンツを同一ディレクトリ内で管理したい
  • ソースとGitHub pagesの内容をcheckoutで切り替えたくない

という二つがあったのでこのあたりの記事を参考にしながら、それを可能とする方法を考えてみた。

手順

以下の手順はGitHub上で既にソースコードが管理されている前提からスタートしています。

1. GitHub上でgh-pagesをジェネる

gh-pagesのコンテンツはもちろん、自分で一から作っても良いのだが、久々にGitHubのジェネレーターを使ったらいい感じのテンプレートがかなりたくさん揃っていたので、よっぽどデザインにこだわりのある人以外はもうこれで良いんじゃないかと思う。(^^;
あとからカスタマイズするのにも特に不都合はないし。

これだけでgh-pagesブランチが作成されて、そこにコンテンツがコミットされます。

2. プロジェクトルートに「gh-pages」というディレクトリを作成し、そのディレクトリを.gitignoreに追加

gh-pagesの管理用のディレクトリを作成し、そのディレクトリを.gitignoreに追加して管理対象外にします。

3. gh-pagesディレクトリに移動してGitHubからgh-pagesブランチの内容を取得

具体的なコマンドは以下のような感じ

cd gh-pages
git init
git remote add origin git@github.com:xxxx/yyyy.git
git checkout -b gh-pages
git pull origin gh-pages
git branch -d master

ようするにgh-pagesディレクトリをgh-pagesブランチ専用のディレクトリにしちゃう。
masterブランチは特に必要ないので削除する。

以降はプロジェクトルートとgh-pagesを移動しながら、普段と同じ感覚のgit操作で両方を管理できる。
(「git config --global push.default matching」を設定しておけばブランチ名を省略できるのでますます便利)

他にもっと良い方法がありそうな気もするけど、本気でググると見たことないgitコマンドがいっぱいでてきて憂鬱になったので、手持ちの技だけで対処してみた。(^^;
とりあえずは満足(^^v

2014年4月30日 (水)

SalesforceのMeetupに行ってきた

4/28にSalesforce Developer User Group Meetup #5に行ってきました。

今回先に行われたHack Challengeの成果発表がメインコンテンツだと思って行ったんですが、実際に行ってみると真のメインコンテンツはこれでした。

ごちそうさまでした。(^^;

 

さて、今回FLECTも発表の場をいただけたのですが、発表自体は@i556がやってくれました。その渾身の資料がこちら

 

http://www.slideshare.net/kokorojw/inside-quizar

 

持ち味でてて良かったです。(^^;

動画も是非大音量でお楽しみください。

 

途中実際にSalesforceのクイズをやったんですが、その結果はこちら。

 

http://www.quizar.info/room/3/ranking

 

(個別イベントへのパーマリンクはないので、上記ページ表示後「4/28」の行をクリックしてください。)

 

ここでも優勝は(Hack Challengeで100万円をGETした)@a_kurataniさんです。さすがです。

クイズに参加した方は

 

マイページ > 参加ルーム > イベント > 問題

 

と辿ることで出題された問題を振りかえることができます。そこには問題の解説や参考リンクも含まれているので、時間が足りなくて良く見れなかった方はご確認ください。

 

こうした勉強会で使うのはそこそこ面白いんじゃないかと思ってますが、課題もまだまだあるというのが今回の感想です。。今回気が付いただけでも

 

  • 10秒は短すぎるので制限時間はある程度選択できる方が良い
  • 制限時間のゲージがまだ動いているのに回答すると「時間切れ」と言われるバグがある

 

などがあるので、これは近日直します。(GWの宿題(^^;;)

 

ちなみに後者のバグは原因だけは調べましたが、AndroidのChromeではJavaScriptのsetTimeoutが端末がスリープしたり、ホームボタン押してバックグラウンドに行ったりすると停止するのが原因です。(ゲージはsetTimeoutで100msごとに動かしているが、制限時間のチェックは実際の時間を計測している)

この辺ブラウザ毎に動作が違うようなので、これもそのうちブログねたにします。(^^v

2014年4月24日 (木)

WebSocket通信のメリットを考える

何故だか昨日のエントリが意外なほど読まれている。(^^;;;


Twitterでの言及も過去最大級かも。特に、


サーバーとの通信はAjax併用でも良いんですが、多分全部WebSocketでやる方がシンプルだし速度面やセキュリティ面でも優位があります。

 

この文章に引っ掛かった人が多いようで、これについてもうちょっと掘り下げてみます。


★ Ajaxの代替としてのWebSocket

そもそもの話として、素のWebSocketではリクエスト(この場合クライアント→サーバのメッセージの意)とレスポンス(サーバ→クライアント)を対応付けることができません。これを実現するためには自力でサーバ/クライアントの双方にメッセージをハンドリングするための仕組みを実装しならず、それは結構めんどうな作業です。

今回、その部分をフレームワーク化しようとしているので、それが実現できた場合のメリットを考えてみます。
ざっと思いつくのは以下です。

  • KeepAliveかつ、httpヘッダのパースも不要になるので速い
  • 特に断続的なリクエストが大量にある場合大きな優位となる(実験結果)
  • 冗長構成でサーバが複数台ある場合も単一クライアントからのリクエストは常に同一サーバに送信される
  • 単一接続からのリクエストは常に同一クライアントからのリクエストであることが保証される


速度メリットは実はおまけみたいなもので、重要なのは最後の2つです。これ、言い換えればWebSocketをAjaxの代替として使うことでステートフルな通信が可能になるということなんです。

既存のWebサーバーではリクエストルーティング機構のインスタンスはサーバー単位で1つなので、リクエスト処理の流れは

  1. リクエスト受信
  2. Cookieを使用してユーザーを同定
  3. 必要ならMemcache等からステート情報を取得
  4. リクエストを処理


のようになりますが、WebSocketの場合接続毎にリクエストルーティングのインスタンスを作ることができるので、2、3の手順がまるまる不要になります。

リクエスト処理のパフォーマンスを出すためになんらかのキャッシュを行う場合もオンメモリだけで間に合いますし、Cookieやhiddenパラメータを使って情報を引き回すことも不要になります。

# ただし、意図しない切断はありえるので長時間ステートを保持することや常にステートが維持されていることを前提としたプログラミングをすることはお勧めしません。この辺のベストプラクティスはまだ確立されていないので当面は自分のバランス感覚だけが頼りになります。(^^;


★ WebSocketとセキュリティ

前述の通り、WebSocketでは単一接続からのリクエストは同一クライアントからのものであることが保証されます。

近年のJavaScriptプログラミングでは処理全体をdocument#readyのクロージャで括るのが一般的ですが、その場合仮にXSSの脆弱性があったとしても外部から接続済みのWebSocketインスタンスにアクセスすることは不可能です。

つまり、最初の接続時にクライアントの確認をしっかりと行っておけば以降のリクエストは攻撃ではないと見なすことができます。なのでCSRFのチェック等は不要です。

問題は接続時の確認を、どのように行うかですがこれはこの資料が参考になります。

http://www.slideshare.net/muneakinishimura/webhtml5-31749532

ほとんどの場合はくログイン認証自体は従来のhttp(s)接続で行ってその後はCookie併用でクライアントを同定することになると思います。
http接続とws接続が同じオリジンであればこれで十分なはずです。


次節で紹介するWebSocketにはSame Origin Policyがないことを利用したスケールアウトを行う場合はもう少し考慮が必要になります。


★ WebSocketとスケール

とりあえずルームモデルでも単純な水平スケールが可能であることは確認済みです。


ただ、この方法には効率の悪い部分があります。

というのは、サーバ100台に対して100人のユーザが1つのルームに入室した場合、最悪100人全員が異なるサーバに接続する可能性があるからです。
ユーザがばらけるとバックエンドのRedisの負荷が上がるので同じルームのユーザは1台とは言わないまでも極力小数のサーバに集中してほしいのです。

HerokuやELBなどフロントにロードバランサがいる場合、こうしたリクエストを適切にふりわけることはできません。(パス毎にリクエストを振り分けるロードバランサがあれば、可能ですがあまり筋の良い解決方法とは思えません。)

が、実はもっと簡単な解決方法があります
WebSocketにはSame Origin Policyがないので単純にサーバを分けてしまえば良いのです。

ページをリクエストするホストが「http://www.quizar.info/...」だったとしても、その中でws接続するホストは「ws://room1.quizar.info/...」であっても良いわけですね。

この場合、接続時のクライアント認証をどうするかが課題になりますが、Cookieのドメインを明示するとかバックエンドキャッシュを使うとかいくつか方法はあると思います。(必要に迫られたらちゃんと考えます。(^^;)

このアーキテクチャを採用する場合、同一のコードベースから簡単に複数のアプリケーションを作成できるHerokuは最強のWebSocketプラットフォームだと思いますが、実際にやって良いかどうかはまた別の話です。(少なくとも課金を減らす目的でやるのはアウトだと思います。実際に必要になったら問い合わせますが、パッケージ買いでその範囲で行う分には問題ないだろうと思います。)


★ 課題

最大の課題はやはり切断時の対処です。HerokuもELBも無通信状態が長く続くと切断されますし、スマホの場合スリープやブラウザから別アプリに切り替えることも当たり前の操作なのでそれも考慮しなければなりません。また、Herokuを使う場合はデイリー再起動への考慮も必要になります。

この部分もフレームワークで吸収できればと思っていますが、もうちょっと試行錯誤が必要なのでそれはまたおいおい。(^^;

□□□□
以上、現時点でのWebSocketに対する考察でした。
WebSocket。既存のhttp通信の延長で考えている人が多いと思いますが、うまく使えば劇的なパラダイムシフトが発生するかもしれません。

どこに辿りつくのかわかりませんが、もうちょっとこの道を進んでみたいと思います。(^^;;;

採用情報

株式会社フレクトでは、事業拡大のため、
Salesforce/Force.comのアプリケーション
開発
HerokuやAWSなどのクラウドプラッ
トフォーム上でのWebアプリケーション開発

エンジニア、マネージャーを募集中です。

未経験でも、これからクラウドをやってみた
い方、是非ご応募下さい。

フレクト採用ページへ

会社紹介

株式会社フレクトは、
認定コンサルタント
認定上級デベロッパー
認定デベロッパー
が在籍している、
セールスフォースパートナーです。
heroku partnersにも登録されています。
herokuパートナー
株式会社フレクトのSalesforce/Force.com
導入支援サービス
弊社の認定プロフェッショナルが支援致します。
・Visualforce/Apexによるアプリ開発
・Salesforceと連携するWebアプリ開発
も承っております。
セールスフォースご検討の際は、
お気軽にお問合せください。
Powered by Six Apart