カテゴリー : 2015年 3月

[Node.js] phantom モジュールの addCookie メソッドの引数が変更された

Node.js 向けの PhantomJS wrapper である phantom の addCookie メソッドの引数がバージョン 0.7.1 から 0.7.2 で変更になりました。

そのため addCookie メソッドを使ってる箇所がエラーで動かなくなってしまいました。

phantom stdout: TypeError: incompatible type of argument(s) in call to addCookie(); candidates were
    addCookie(QVariantMap)
 
 
phantom stdout:   /u/apps/myapp/shared/node_modules/phantom/shim.js:5621
  /u/apps/com/shared/node_modules/phantom/shim.js:4526
  /u/apps/com/shared/node_modules/phantom/shim.js:4502
  /u/apps/com/shared/node_modules/phantom/shim.js:4382
  /u/apps/com/shared/node_modules/phantom/shim.js:4370

変更点は、

addCookie: (name, value, domain, cb=->) ->

から

addCookie: (cookie, cb=->) ->

に arguments が変更されているだけです。

なので name, value, domain と個別に引数に渡されていたのを cookie オブジェクトにまとめて渡すように、addCookie メソッドを呼び出しているコードを修正すれば OK です。

詳しくは上記の issue と pull request を読むと分かりますが PhantomJS の API に合わせる方針で修正されたようです。

[JavaScript] Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.

ローカル環境でローカルにある JSON ファイルを $.getJSON しようとすると Chrome では file スキーマは読み込んでくれなくてエラーが発生します。

var jsonFilePath = "./json/sample.json";
 
$.getJSON(jsonFilePath, function(data){
  // do something
});

エラーメッセージ

XMLHttpRequest cannot load file:///Users/bakorer/Downloads/hoge.json.
Cross origin requests are only supported for protocol schemes:
http, data, chrome, chrome-extension, https, chrome-extension-resource.

ステージングサーバに設置して http 経由で確認するしかなさそうです。

簡単に確認する方法だと DropBox の Public ディレクトリに設置して、https://dl.dropboxusercontent.com/u/xxx/index.html とかいう URL でアクセスすることで確認できます。


参考情報

[MongoDB] 銀行口座のスキーマ定義

以前、Mongoose (MongoDB) で銀行口座の情報を取り扱う Scheme の定義をしたときに悩んで付けた field 名を公開します。

MongoDB

BANK_ACCOUNT_TYPE =
  SAVINGS: 1
  CURRENT: 2
 
BANK_ACCOUNT_TYPE_KEYS = Object.keys(BANK_ACCOUNT_TYPE)
BANK_ACCOUNT_TYPE_PATTERN = BANK_ACCOUNT_TYPE_KEYS.map (k)-> BANK_ACCOUNT_TYPE[k]
 
HogeScheme = new Scheme
bank_account:
  bank_name:
    type: String
  bank_code:
    type: String
  branch_name:
    type: String
  branch_code:
    type: String
  account_type:
    type: Number
    enum: BANK_ACCOUNT_TYPE_PATTERN
  account_number:
    type: Number
  account_holder_name:
    type: String
  account_holder_name_kana:
    type: String

というような感じにしました。

[Nginx] upstream timed out (110: Connection timed out) while reading response header from upstream

当サイト codenote.net が 504 Gateway Time-out で接続しにくい状態になっていました。

まず、Nginx のエラーログを確認すると upstream timed out (110: Connection timed out) while reading response header from upstream というエラーが出てました。

$ tail -F /var/log/nginx/codenote.net/error.log 
2015/03/28 23:45:04 [error] 20407#0: *537270 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 223.135.69.50, server: codenote.net, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm/www.sock", host: "codenote.net"

ひとまず PHP-FPM のプロセスを再起動して一旦は直ったものの、またすぐに繋がらなくなりました。

$ service php-fpm restart
Stopping php-fpm:                                          [  OK  ]
Starting php-fpm:                                          [  OK  ]

調査してみると PHP-FPM の設定に問題があるようで、確認してみたら process manager の設定がほぼデフォルトのままの状態でした。ちゃんと設定していたはずなんですけど…

/etc/php-fpm.d/www.conf

以下、pm (process manager) のデフォルト設定です。

; Choose how the process manager will control the number of child processes.
; Possible Values:
;   static  - a fixed number (pm.max_children) of child processes;
;   dynamic - the number of child processes are set dynamically based on the
;             following directives:
;             pm.max_children      - the maximum number of children that can
;                                    be alive at the same time.
;             pm.start_servers     - the number of children created on startup.
;             pm.min_spare_servers - the minimum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is less than this
;                                    number then some children will be created.
;             pm.max_spare_servers - the maximum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is greater than this
;                                    number then some children will be killed.
; Note: This value is mandatory.
pm = dynamic
 
; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes to be created when pm is set to 'dynamic'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
; CGI.
; Note: Used when pm is set to either 'static' or 'dynamic'
; Note: This value is mandatory.
pm.max_children = 9
 
; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
pm.start_servers = 3
 
; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.min_spare_servers = 2
 
; The desired maximum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.max_spare_servers = 4
 
; The number of requests each child process should execute before respawning.
; This can be useful to work around memory leaks in 3rd party libraries. For
; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
; Default Value: 0
pm.max_requests = 200

下記の設定に変更しました。

pm = static
pm.max_children = 30
pm.max_requests = 500

pm = static は最初から小プロセスの起動数を固定する設定です。dynamic だと動的ですが、最初から確保できる static の方が利用するリソースが把握しやすいので static にします。

max_children は起動する小プロセスの最大数です。

max_requests は子プロセスが再起動するまでに実行するリクエスト数です。

PHP-FPM の process manager の設定を変更後、504 Gateway Time-out は表示されず快適にアクセスできるようになりました。

参考情報

[WordPress] モバイル端末向けの使いやすいテーマ Hew

WordPress の無料テーマ Hew がモバイルサイト向けに使いやすそうなのでご紹介します。

hew-screenshot-main

サイトへの訪問者のほとんどがモバイル端末のケースだと、PC・モバイルのそれぞれテーマを用意するのは面倒なのでモバイルに特化したいということが最近増えてきました。そんなとき Hew のようなレスポンシブデザインのテーマを使うことで、とかなり作業時間を短縮できてすごく助かってます。

レスポンシブデザインの WordPress テーマはたくさんありますが、Hew は PC とモバイルで大きくレイアウトに変更が変わらない軽めのレスポンシブデザインという点が個人的にポイント高いです。

カンタンに画面共有できるサービス join.me がペアプロやMTGにとっても便利

join.me というサクッと画面共有できるサービスがめっちゃ便利で、メルカリのエンジニアさんたちがペアプログラミングに使っているという話を聞いて 本日 MTG で使ってみました。

join-me

本日の MTG は Backlog と Github issue を眺めながら来週の開発タスクの工数算出するという内容でした。「この機能は開発工数 3 時間で、レビューや QA に 2 時間ぐらい掛かるかな?」というような内容を話しながら、手元で issue に comment したり Backlog に工数を入力していました。この手元の作業を大きめの外部ディスプレイに出力せずに、画面共有することができるのはとても便利でした。

使い方については、

とかに詳しく書かれていますので、そちらを参考にしてください。

とても簡単にスクリーンキャストができてとても便利でした。動作も重たくなく、スムーズに使えるのでオススメです。

[Mongoose] 途中から field に default 定義を追加する場合の実装方針

Mongoose で途中から field に default 定義を追加する場合の実装方針を忘れないように書き残しておきます。

var mongoose = require('mongoose');
 
var orderSchema = new mongoose.Schema({
  // 合計金額
  amount: {
    type: Number
  },
  // 送料無料の条件が適用される閾値 (単位: USD)
  freeShippingThreshold: {
    type: Number,
    default: 100
  }
});
 
var Order = mongoose.model('Order', orderSchema);
 
 
/**
 * Case1: 新規 instance
 * instance 化されたときはデフォルト値が入った状態で便利
 **/
var order = new Order();
/**
 * order : {
 *    _id: 5512abca1c6bb890a82b0951,
 *    freeShippingThreshold: 100
 * }
 **/
 
 
/**
 * Case2: MongoDB に保存されている既存データから取得した instance
 *
 * MongoDB に保存されているデータは下記の通り
 * 
 * order : {
 *   _id: 50169294b1b4a1c21e00001e,
 *   amount: 150
 * }
 **/
Order.findOne(function (err, order) {
  /**
   * Mongoose の findOne method で instance 取得したときは、
   * 値が入ってなければ default に設定した値がセットされる
   * 
   * order : {
   *   _id: 50169294b1b4a1c21e00001e,
   *   amount: 150,
   *   freeShippingThreshold: 100
   * }
   **/
});

Case1 の新規インスタンスを作成するケースは、デフォルトで freeShippingThreshold に 100 が入ってるので、使い回しが便利です。何の問題もなさそうですね。

Case2 は既に MongoDB に保存されているが freeShippingThreshold に値が入ってないので、 100 が入った状態で order インスタンスを取得できます。しかし、この order が保存されたときはキャンペーン期間中で送料無料の閾値が $50 になっていたので 50 が入ったデータが欲しいわけです。こういうケースは後から default: 100 を設定するタイミングで既存データに適切な freeShippingThreshold を設定してあげる必要があるわけです。

以上、うっかりしてると陥るかもしれない Mongoose の運用事例でした。

[Windows] 誤ってプログラムを削除したときは「システムの復元」で元に戻す

Javaのアップデートを促す偽サイトが頻繁に表示される問題を解決したときに、不要と判断して「プログラムの削除と変更」からプログラムをアンインストールしまくりました。

いくつかプログラムを削除して問題は解決したものの、一部のソフトウェアが動かなくなったり音が出なくなるなどの問題が発生しました。必要なプログラムまで削除してしまったみたいでした。

こういうときには、システムの復元という機能を使うとカンタンに元通りにすることができるので覚えておくといいかもしれません。

僕はひさしく Windows を触ってなかったのでこの機能の存在をすっかり忘れていて、復旧に少し手間取ったことがありました。

[MongoDB] field を削除するコマンド

MongoDB で不要なフィールドを削除するには db.collection.update を $unset で利用します。

MongoDB

$unset のためのデータ事前準備

まず、検証用のデータを insert します。今回は3件新規登録します。

> db.users.insert( { name : 'test' , age : 20 } )
> db.users.insert( { name : 'hoge' , age : 50 } )
> db.users.insert( { name : 'spam' , age : 90 } )
 
> db.users.find()
{ "_id" : ObjectId("55102489395c0a2d41edd220"), "name" : "test", "age" : 20 }
{ "_id" : ObjectId("551024c0395c0a2d41edd221"), "name" : "hoge", "age" : 50 }
{ "_id" : ObjectId("551025fc395c0a2d41edd222"), "name" : "spam", "age" : 90 }

1件だけ $unset する

特定の _id の document の field を削除する場合、第一引数に条件を指定して、1件だけしか削除しないように第四引数に false を指定します。

> db.users.update( { _id : ObjectId( "55102489395c0a2d41edd220" ) } , { $unset : { age : 1 } } , false , false )
> db.users.find()
{ "_id" : ObjectId("55102489395c0a2d41edd220"), "name" : "test" }
{ "_id" : ObjectId("551024c0395c0a2d41edd221"), "name" : "hoge", "age" : 50 }
{ "_id" : ObjectId("551025fc395c0a2d41edd222"), "name" : "spam", "age" : 90 }

全件 $unset する

全ての document の特定の field を削除する場合、第一引数に {} を指定して全ドキュメントを対象にして、第四引数に true を指定して該当する全ドキュメントのフィールドを削除対象にします。

> db.users.update( { } , { $unset : { age : 1 } } , false , true )
> db.users.find()
{ "_id" : ObjectId("55102489395c0a2d41edd220"), "name" : "test" }
{ "_id" : ObjectId("551024c0395c0a2d41edd221"), "name" : "hoge" }
{ "_id" : ObjectId("551025fc395c0a2d41edd222"), "name" : "spam" }

$unset の使い方まとめ

最後に注意点として、update メソッドはすべてのドキュメントの field を吹っ飛ばす可能性があるので、本番データではできるだけ使わないようにしたいですね。

参考情報

[Windows] Javaのアップデートを促す偽サイトと解決方法

2014年10月ぐらいでしょうか、Javaのアップデートを促す偽サイトが流行っていましたね。

僕の周りでも家族や知人など数名が感染していて、解決するまでにやったことメモっていたのを公開しておきます。

  • ブラウザのキャッシュ、Cookie、履歴など全て削除
  • IObit Uninstallerで怪しいプログラムをアンインストール

やったことはこの2つだけです。解決したら IObit Uninstaller は常駐して邪魔だと思うので、これもアンインストールしてしまいましょう。

解決するまでに数時間もかかったので、普段から「変なサイトを開かない」「怪しい広告やリンクをクリックしない」など気をつけてインターネットしないといけませんね。