読者です 読者をやめる 読者になる 読者になる

【fuelphp】Redisでロック・排他制御する方法メモ

APIの実装でクライアントからの2重送信対策にRedisを使ってみた。
MySQLでやろうとも思ったのだが負荷のことを考えるとRedisの方がいいのかなという判断。

$token = クライアントから送られるトークン 

$redis = Redis::forge();
if (1 === $redis->setnx($token, 1)) {
  // ロックに成功したら有効期限に1分をセット                                                                                                                                                                 
  $redis->expireAt($token, time() + 60);
} else {
  // ロックに失敗(同じキーが登録済み)なら処理中断                                                                                                                                                                  
}

当初は$redist->get($key)で取得できたら、2重送信と判定していたのだがこれだと全く同タイミングだと正しく判定できない(排他制御できてない)。で、ググてみるとsetnxを使えとのことでした。動作確認したら期待通りの挙動となりました。以上です。

【javascript】iPhoneでpagehideが2回呼ばれたときの対応

今回やりたかったことは、ページから離れるとき(リンクとか)にその内容をサーバーに通知したいということ。pagehideで実装したのだが、なぜかiPhoneだとこれが2回呼ばれる現象だった(safarichromeともに)。

以下のようなコードで確認したところ、2回送信されるのを確認。おそらく全く同時刻にランダム文字列が生成してるためかrandの部分が同じものが送信される。

var flg = true;
window.addEventListener("pagehide", function() {
  if (flg) {
    flg = false;
    var rand = ランダム文字列を生成
    var img = new Image();
    img.src = "https://xxx/?rand=" + rand
    document.body.appendChild(img);
  }
});

なのでやはりサーバー側でちゃんと対応しないとダメだねということで対応しました。以上です。

ionic(corodva)info.plistに追記して日本語化対応する - ios

アプリ内から別アプリを開いたら起動したアプリが全て英語だったのでその対応。というかionicで作ったアプリ自体が日本語化されてなかった。

xcodeでの開発の場合は、info.plistを直接いじればよいけどcorodva使ってる場合はxcode上で直接編集したものはbuild時に戻ってしまうのでcordovaで完結するようにする。

config.xmlへの記述でいけるのかと思ったのだがなぜかうまくいかなかったので別途プラグインを用意してplugin.xmlから追記する形でやってる人がいたのでそのやり方を真似させてもらった。

plugins-dev/plugin.xml

<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" id="plugin-localization-ios" version="0.1" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
  <name>Localization Ios</name>
  <platform name="ios">
    <config-file target="*-Info.plist" parent="CFBundleDevelopmentRegion">
      <array>
        <string>Japanese</string>
      </array>
    </config-file>
    <config-file target="*-Info.plist" parent="CFBundleLocalizations">
      <array>
        <string>ja</string>
      </array>
    </config-file>
  </platform>
</plugin>

プラグインをプロジェクトへ組み込む

$ ionic plugin add plugins-dev/

platforms/ios/SampleCalendar/SampleCalendar-Info.plist

<key>CFBundleDevelopmentRegion</key>
<array>
 <string>Japanese</string>
</array>                                                                                                                                                                                                           
・・・                                                                                                                                                                                                             
<key>CFBundleLocalizations</key>
<array>
  <string>ja</string>
</array>

info.plistに追記されていればOK。

これで終わろうと思ったらプラグインありました。

https://github.com/enricodeleo/cordova-plugin-ios-localized-strings

$ ionic plugin add cordova-plugin-ios-localized-strings --variable MAIN_LANGUAGE=Japanese --variable ADDITIONAL_LANGUAGES=ja

これだけでいける。けど、指定したパラメータの情報ってどこにも保持されない気がするのでチーム開発だと厳しいのかな。。。以上です

gulp-concatでファイルを新規作成したときに動かなかったときの対応

gulp-concatがうまく動かなかった時のメモ。こんなことでひっかかる人あまりいなそうだけどハマったのでメモしておく。ファイルの更新では上手くいくが、新規作成と削除で上手く動かなかった。ディレクトリの階層が深くなるとダメなのかなとか思ったけど全然関係なかった。

うまくいかない

var gulp = require("gulp"),
  concat = require("gulp-concat");

gulp.task("js.concat-controllers", function() {
  return gulp.src("./src/controllers/**/*.js")
    .pipe(concat("controllers.js"))
    .pipe(gulp.dest("build"));
});

gulp.task("watch", function() {
  gulp.watch(["./src/controllers/**/*.js"], ["js.concat-controllers"]);
});

こうしたらうまくいった

var gulp = require("gulp"),
  concat = require("gulp-concat");

gulp.task("js.concat-controllers", function() {
  return gulp.src("src/controllers/**/*.js") // ★先頭の「./」を削除
    .pipe(concat("controllers.js"))
    .pipe(gulp.dest("build"));
});

gulp.task("watch", function() {
  gulp.watch(["src/controllers/**/*.js"], ["js.concat-controllers"]);// ★先頭の「./」を削除
});

以上です

やっぱりphpのスクリプトはcronに直接設定しないほうがいいかもしれない

また初歩的なことでつまづいてしまった。ありがちなミスで開発中にコマンド上で実行してうまくいってたけどcronに登録したらエラーになってたってやつ。スクリプト内で呼び出す外部ファイルとかフルパスで書いておけば問題ないくらいで最近この形にしてたけどうまくいかないことがあって原因わかるのに時間かかった。

こんなかんじのcron設定

5 10 * * * php /path/to/script.php
5 10 * * * PATH="/usr/local/bin:$PATH" php /path/to/script.php

cronに設定されたスクリプトはそのままだとbashrc、bash_profileあたりが読み込まれないので環境変数まわりがシェルでログインしての開発中とだいぶ状況が異なる。

script.sh

#!/bin/bash -l                                                                                                                                                                                                     
php /path/to/script.php

こんなかんじにcron設定

5 10 * * * /path/to/script.sh

まぁ、cron内でPATHとかちゃんと設定してから呼べば問題ないとは思うのだけど。こっちの方が間違いなさそう。以前はこうやってたけどいつのまにか直接phpファイル実行するように書いてた。。。以上です

【CasperJS】プロキシを使う方法

やりかた違うけかもしれないけど

これだと動かなかった

var casper = require('casper').create({
  "proxy": "http://proxy.example.com:port",
  "proxy-auth": "user:password",
});                                                                                                                                                                                                             

これだと動いた

$ casperjs /path/to/myscript.js --proxy=http://proxy.example.com:port --proxy-auth=user:password

以上です

ionic(corodva)でplugin rmで「Path must be a string. Received undefined」の対応

自作したプラグインを削除しようとしたら以下のようなエラーが発生。rmしてaddし直したかったのだがハマった。。。

Error during processing of action! Attempting to revert...

Error: Uh oh!
Path must be a string. Received undefined

色々試してたらplugin.xmlに以下のような記述があるとなるみたいだった。

<framework src="src/ios/sample.framework" custom="true" />

plugins/plugin-sample/plugin.xmlからを削除して再度ionic plugin rmしたら無事削除できた。けどこれ毎回やるのって手間だな。。。別の対応も考えた方がよさそう。。以上です。